This is the third in the short series of my journey building the Slack Tempest WeatherBot. In this post I'm walking through the steps to incorporate external data from the National Weather Service (NWS) API for alerts and forecast options. The previous post walked through adding interactivity to the WeatherBot which really improved the bot's overall usability.
The NWS has an API!
I've been working with our campus weather station for many years, and part of that work over a decade ago incorporated just-in-time alert data. The NWS had a product (not an API, per se) that was more like an RSS feed for specific location or zones. This was sufficient for the purposes of the campus station as it contained all the basic bits...but it was clunky and old, and not really something I wanted to onboard for the WeatherBot. Fortunately, a relatively new service of NWS is an API proper, though still a work in progress. However, their Swagger documentation is a great view into the work in progress!
The gist of using the NWS API is that everything can be based on geocoordinates for the "point." This provides a more specific location than the more generic fire/county zone model, and that's especially important for certain types of alerts (namely warnings) as those might not apply to the full zone.
Integrating NWS API Alerts
Since our Tempest station metadata gives us our coordinates, it's super easy to round those to the precision necessary for the NWS API (4-digits). This point data also allows us to identify the zone(s) in which a point may be included...which may be helpful or necessary for other calls down the road.
Out of the gate (and knowing from past experience that several alerts can and often are active for a location at a given time), I decided to create a class for individual alerts. In combination with the parent functionality code, I can create and manage multiple alerts and sort them by "severity" levels. Much like the TempestObservation
class, the NWSAlert
class also provides formatted output in the proper/expected Slack Block structure for use in bot features.
It's important to note that NWS Alerts have their own consistent and unique formatting nuances; the class also addresses some of that detail.
With the class and API functions in place, adding alert support was a matter of injecting more blocks into the app home tab...and also adding a few arguments to the /weather
slash command such as /weather alerts
and /weather alerts force
.
Most of the time, using one of these commands results in the following:
However, during an active warning (such as this Particularly Dangerous Situation (PDS) warning from a nasty storm we had on May 12, 2022), the alert's full details are shown:
When an active alert is issued, the App Home tab displays a condensed version of the alert text:
The NWS API Has Rules
While the whole intent of the NWS API is to be open and free of charge, they have some basic rules for folks to follow. Specifically:
- Rate limits are in effect, although exact details are undocumented: be a good user;
- No authentication is required, but each system should set an appropriate
User-Agent
with contact details for requests; and
- Some things are still in development and might change without notice.
To that end, I built the WeatherBot with defaults to not ping the NWS API more than once every 10 minutes. This can be overridden with the force
slash argument noted above as a one-off use case and not standard procedure.
What About Forecasts?
The NWSAPIFunctions.php
code for the NWS API includes support to generate and write out forecast data for use in the bot. I added just enough basic support (at the time of this post series) to support using NWS forecast data; however, I haven't personally used it in my own WeatherBot instance. This is primarily because I like the nature of the Tempest forecast data better (on the whole) than the more narrative NWS data.
However, I also appreciate the narrative NWS forecast information...so I stopped implementation while I considered ways to mix the two datasets (data from Tempest and narrative from NWS). To date I haven't returned to that evaluation...so it's a "maybe" thing for the future.
Time for Job Processes
To improve performance by caching requests, it was time to create a couple of "jobs" that could run in the background (by cron
) and fetch updated alert and/or forecast data. Out of this was born some of the stuff in the jobs/
directory which included maintenance mechanisms for maintaining the Slack user list, periodically re-generating the station metadata, and cleaning up history. These automation jobs help keep things running smoothly (and in a tidy manner).
Other External Data Possibilities
I don't have any other external data sources personally identified, but what is cool about the bot on the whole is that it can be extended to include other data sources (radar imagery would be super cool) without a lot of effort. I wouldn't call the bot structure truly "modular," but the core functionality of the app home tab and slash command responses lend themselves well to the injection or addition of other "things," whatever that might mean to a use case.
What's Next?
The next and "final" post in this summer series I outline my addition to what I call "push" notices for high-impact events such as lightning strikes and new weather alerts, which have come in super handy during this spring/summer storm season!
Headline image of WeatherBot alert via Matt Zaske