Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add temperature, driving conditions, storm warning info to event summaries #80

Open
nmlorg opened this issue Nov 30, 2019 · 8 comments
Open
Assignees
Labels
enhancement New feature or request

Comments

@nmlorg
Copy link
Owner

nmlorg commented Nov 30, 2019

  1. Maintain a cache of location string to lat/lon. Whenever an unknown location is seen, use an API like Google Geocoding API to look it up.
  2. Maintain a cache of lat/lon to forecast grid point using https://api.weather.gov/points/LAT,LON. Note that lat and lon must be truncated to 4 decimal points.
  3. Whenever an event is displayed, look up its forecast grid point's forecast for the given time. This might just be done in m.m.events.format_event the same way ticketing information is checked. It might make sense to introduce some kind of caching layer here that only exists for the duration of the current request (something shoved into ctx?).

Note that weather.gov's API provides two forecast streams:  hourly and daily. For example, Capitol Hill, Seattle, WA geocodes (1) to:

{
   "results" : [
      {
         "geometry" : {
            "location" : {
               "lat" : 47.625305,
               "lng" : -122.3221835
            }
         }
      }
   ]
}

which maps to forecast grid point (2):

{
    "properties": {
        "forecast": "https://api.weather.gov/gridpoints/SEW/124,68/forecast",
        "forecastHourly": "https://api.weather.gov/gridpoints/SEW/124,68/forecast/hourly",
    }
}

which provides forecasts for2019-11-29T18:00:00-08:00 through 2019-12-06T18:00:00-08:00 in 12-hour blocks and 2019-11-29T18:00:00-08:00 through 2019-12-06T06:00:00-08:00 in 1-hour blocks, resp.; so if we had an event taking place at noon on Dec 6, it might make sense to go with the 12-hour forecast. (Though in practice it might not be worth the effort if the extra coverage is consistently so small.)

@nmlorg nmlorg added the enhancement New feature or request label Nov 30, 2019
@nmlorg
Copy link
Owner Author

nmlorg commented Nov 30, 2019

Note that only the daily (12-hourly) forecast includes free-form description text, and only the raw gridpoints endpoint seems to include weather advisories:

https://api.weather.gov/gridpoints/MPX/107,71/forecast/hourly

            {
                "number": 1,
                "name": "",
                "startTime": "2019-11-29T20:00:00-06:00",
                "endTime": "2019-11-29T21:00:00-06:00",
                "isDaytime": false,
                "temperature": 32,
                "temperatureUnit": "F",
                "temperatureTrend": null,
                "windSpeed": "10 mph",
                "windDirection": "ESE",
                "icon": "https://api.weather.gov/icons/land/night/snow_fzra,30?size=small",
                "shortForecast": "Chance Light Snow",
                "detailedForecast": ""
            },

 

https://api.weather.gov/gridpoints/MPX/107,71/forecast

            {
                "number": 1,
                "name": "Tonight",
                "startTime": "2019-11-29T20:00:00-06:00",
                "endTime": "2019-11-30T06:00:00-06:00",
                "isDaytime": false,
                "temperature": 31,
                "temperatureUnit": "F",
                "temperatureTrend": null,
                "windSpeed": "10 to 20 mph",
                "windDirection": "E",
                "icon": "https://api.weather.gov/icons/land/night/snow_fzra,100/sleet,100?size=medium",
                "shortForecast": "Light Snow",
                "detailedForecast": "A chance of snow and a slight chance of freezing rain before 9pm, then snow and a slight chance of thunderstorms between 9pm and 5am, then snow and a chance of sleet and a slight chance of thunderstorms. Cloudy, with a low around 31. East wind 10 to 20 mph, with gusts as high as 25 mph. Chance of precipitation is 100%. New snow accumulation of 1 to 3 inches possible."
            },

 

https://api.weather.gov/gridpoints/MPX/107,71

        "hazards": {
            "values": [
                {
                    "validTime": "2019-11-30T03:00:00+00:00/P1DT15H",
                    "value": [
                        {
                            "phenomenon": "WS",
                            "significance": "W",
                            "event_number": "2"
                        }
                    ]
                }
            ]
        },

@nmlorg
Copy link
Owner Author

nmlorg commented Nov 30, 2019

Poking around some more, it looks like we might want to take the forecastZone field from https://api.weather.gov/points/LAT,LON, strip everything before the last '/', then use that to pull advisories directly from api.weather.gov/alerts. For example, Capitol Hill's full properties definition is:

    "properties": {
        "@id": "https://api.weather.gov/points/47.6253,-122.3221",
        "@type": "wx:Point",
        "cwa": "SEW",
        "forecastOffice": "https://api.weather.gov/offices/SEW",
        "gridX": 124,
        "gridY": 68,
        "forecast": "https://api.weather.gov/gridpoints/SEW/124,68/forecast",
        "forecastHourly": "https://api.weather.gov/gridpoints/SEW/124,68/forecast/hourly",
        "forecastGridData": "https://api.weather.gov/gridpoints/SEW/124,68",
        "observationStations": "https://api.weather.gov/gridpoints/SEW/124,68/stations",
        "relativeLocation": {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -122.350876,
                    47.620499000000002
                ]
            },
            "properties": {
                "city": "Seattle",
                "state": "WA",
                "distance": {
                    "value": 2221.7450616248334,
                    "unitCode": "unit:m"
                },
                "bearing": {
                    "value": 76,
                    "unitCode": "unit:degrees_true"
                }
            }
        },
        "forecastZone": "https://api.weather.gov/zones/forecast/WAZ558",
        "county": "https://api.weather.gov/zones/county/WAC033",
        "fireWeatherZone": "https://api.weather.gov/zones/fire/WAZ654",
        "timeZone": "America/Los_Angeles",
        "radarStation": "KATX"
    }

and https://api.weather.gov/alerts/active?zone=WAZ558 currently gives:

{
    "type": "FeatureCollection",
    "features": [],
    "title": "current watches, warnings, and advisories for Seattle and Vicinity (WAZ558) WA",
    "updated": "2019-11-24T00:00:00+00:00"
}

 
Minneapolis, MN is currently under a winter storm warning, being pushed to Android devices linking back to https://www.google.org/publicalerts/alert?aid=f51afc5f2c0d1ae9. Its full properties definition is:

    "properties": {
        "@id": "https://api.weather.gov/points/44.9777,-93.265",
        "@type": "wx:Point",
        "cwa": "MPX",
        "forecastOffice": "https://api.weather.gov/offices/MPX",
        "gridX": 107,
        "gridY": 71,
        "forecast": "https://api.weather.gov/gridpoints/MPX/107,71/forecast",
        "forecastHourly": "https://api.weather.gov/gridpoints/MPX/107,71/forecast/hourly",
        "forecastGridData": "https://api.weather.gov/gridpoints/MPX/107,71",
        "observationStations": "https://api.weather.gov/gridpoints/MPX/107,71/stations",
        "relativeLocation": {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -93.268320000000003,
                    44.963324
                ]
            },
            "properties": {
                "city": "Minneapolis",
                "state": "MN",
                "distance": {
                    "value": 1619.735883443921,
                    "unitCode": "unit:m"
                },
                "bearing": {
                    "value": 9,
                    "unitCode": "unit:degrees_true"
                }
            }
        },
        "forecastZone": "https://api.weather.gov/zones/forecast/MNZ060",
        "county": "https://api.weather.gov/zones/county/MNC053",
        "fireWeatherZone": "https://api.weather.gov/zones/fire/MNZ060",
        "timeZone": "America/Chicago",
        "radarStation": "KMPX"
    }

and https://api.weather.gov/alerts/active?zone=MNZ060 currently gives:

{
    "@context": [
        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
        {
            "wx": "https://api.weather.gov/ontology#",
            "@vocab": "https://api.weather.gov/ontology#"
        }
    ],
    "type": "FeatureCollection",
    "features": [
        {
            "id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3935103-3346792",
            "type": "Feature",
            "geometry": null,
            "properties": {
                "@id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3935103-3346792",
                "@type": "wx:Alert",
                "id": "NWS-IDP-PROD-3935103-3346792",
                "areaDesc": "Carver; St. Croix; McLeod; Ramsey; Kandiyohi; Wright; Meeker; Dunn; Washington; Chippewa; Hennepin; Anoka",
                "geocode": {
                    "UGC": [
                        "MNZ068",
                        "WIZ023",
                        "MNZ066",
                        "MNZ062",
                        "MNZ057",
                        "MNZ059",
                        "MNZ058",
                        "WIZ025",
                        "MNZ063",
                        "WIZ027",
                        "MNZ060",
                        "MNZ061"
                    ],
                    "SAME": [
                        "027019",
                        "055109",
                        "027085",
                        "027123",
                        "027067",
                        "027171",
                        "027093",
                        "055033",
                        "027163",
                        "055017",
                        "027053",
                        "027003"
                    ]
                },
                "affectedZones": [
                    "https://api.weather.gov/zones/forecast/MNZ068",
                    "https://api.weather.gov/zones/forecast/WIZ023",
                    "https://api.weather.gov/zones/forecast/MNZ066",
                    "https://api.weather.gov/zones/forecast/MNZ062",
                    "https://api.weather.gov/zones/forecast/MNZ057",
                    "https://api.weather.gov/zones/forecast/MNZ059",
                    "https://api.weather.gov/zones/forecast/MNZ058",
                    "https://api.weather.gov/zones/forecast/WIZ025",
                    "https://api.weather.gov/zones/forecast/MNZ063",
                    "https://api.weather.gov/zones/forecast/WIZ027",
                    "https://api.weather.gov/zones/forecast/MNZ060",
                    "https://api.weather.gov/zones/forecast/MNZ061"
                ],
                "references": [
                    {
                        "@id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3934596-3346306",
                        "identifier": "NWS-IDP-PROD-3934596-3346306",
                        "sender": "[email protected]",
                        "sent": "2019-11-29T12:09:00-06:00"
                    },
                    {
                        "@id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3934596-3346307",
                        "identifier": "NWS-IDP-PROD-3934596-3346307",
                        "sender": "[email protected]",
                        "sent": "2019-11-29T12:09:00-06:00"
                    }
                ],
                "sent": "2019-11-29T16:45:00-06:00",
                "effective": "2019-11-29T16:45:00-06:00",
                "onset": "2019-11-29T21:00:00-06:00",
                "expires": "2019-11-30T03:00:00-06:00",
                "ends": "2019-12-01T12:00:00-06:00",
                "status": "Actual",
                "messageType": "Update",
                "category": "Met",
                "severity": "Severe",
                "certainty": "Likely",
                "urgency": "Expected",
                "event": "Winter Storm Warning",
                "sender": "[email protected]",
                "senderName": "NWS Twin Cities/Chanhassen MN",
                "headline": "Winter Storm Warning issued November 29 at 4:45PM CST until December 1 at 12:00PM CST by NWS Twin Cities/Chanhassen MN",
                "description": "...HEAVY SNOW EXPECTED THIS WEEKEND ACROSS CENTRAL MINNESOTA AND\nNORTHWEST WISCONSIN WITH A WINTRY MIX TO THE SOUTH...\n...VERY TIGHT SNOWFALL GRADIENT POSSIBLE FROM CANBY TO THE TWIN\nCITIES AND EAU CLAIRE AREAS SATURDAY...\n\n.A Winter Storm Warning is in effect tonight through Sunday\nmorning for areas along and north of a line from Canby and the\nTwin Cities to Eau Claire. Snow is expected to start this\nevening. A total of 8 to 14 inches are expected by Sunday\nmorning, with the lighter amounts on the southern edge of the\nwarning. From Canby to the Twin Cities and Eau Claire, snow will\nturn to a wintry mix Saturday and then turn back to snow Saturday\nnight and Sunday morning. There is expected to be a very tight\nsnow gradient somewhere near this line with all snow to the north\nand a prolonged mix to the south. Gusty east winds of 30 to 40\nmph could lead to patchy blowing snow as well.\n\nA Winter Weather Advisory is in effect for south central\nMinnesota and portions of west central Wisconsin tonight. The snow\nwill likely turn to rain and possibly a rain/sleet mix Saturday\nmorning before turning back to snow Saturday night.\n\n* WHAT...Heavy mixed precipitation expected. Total snow\naccumulations of 6 to 10 inches and ice accumulations of a\nlight glaze. Winds gusting as high as 40 mph.\n\n* WHERE...Portions of west central Wisconsin and central and\neast central Minnesota.\n\n* WHEN...From 9 PM this evening to noon CST Sunday.\n\n* IMPACTS...Travel could be very difficult. Patchy blowing snow\ncould significantly reduce visibility.\n\n* ADDITIONAL DETAILS...Snow will fall tonight, then turn to a\nwintry mix Saturday before turning back to snow Saturday night.\nPrecipitation may remain all snow north of a line from Canby, to\nthe Twin Cities, and Eau Claire. If this occurs, around a foot\nof snow can be expected.",
                "instruction": "If you must travel, keep an extra flashlight, food, and water in\nyour vehicle in case of an emergency.\n\nThe latest road conditions for the state you are calling from can\nbe obtained by calling 5 1 1.",
                "response": "Prepare",
                "parameters": {
                    "NWSheadline": [
                        "WINTER STORM WARNING REMAINS IN EFFECT FROM 9 PM THIS EVENING TO NOON CST SUNDAY"
                    ],
                    "HazardType": [
                        "Heavy Mixed precipitation, Mixed Precipitation"
                    ],
                    "VTEC": [
                        "/O.CON.KMPX.WS.W.0012.191130T0300Z-191201T1800Z/"
                    ],
                    "EAS-ORG": [
                        "WXR"
                    ],
                    "PIL": [
                        "MPXWSWMPX"
                    ],
                    "BLOCKCHANNEL": [
                        "CMAS",
                        "EAS",
                        "NWEM"
                    ],
                    "eventEndingTime": [
                        "2019-12-01T12:00:00-06:00"
                    ]
                }
            }
        }
    ],
    "title": "current watches, warnings, and advisories for Hennepin (MNZ060) MN",
    "updated": "2019-11-29T22:46:14+00:00"
}

@nmlorg
Copy link
Owner Author

nmlorg commented Nov 30, 2019

UI-wise, the current Minneapolis warning might look like:

Event Title
TOMORROW, Sat 30ᵗʰ, 8–11:59ᵖᵐ @ Event Location
⚠ Winter Storm Warning: Heavy Mixed precipitation, Mixed Precipitation
Second Event
² ᵈᵃʸˢ Sun, Dec 1ˢᵗ, 5–9ᵖᵐ @ Second Location
⚠ Winter Storm Warning: Heavy Mixed precipitation, Mixed Precipitation

where the hazard line links to either a location-specific URL, like https://forecast.weather.gov/showsigwx.php?warnzone=MNZ060&warncounty=MNC053&firewxzone=MNZ060, or to an advisory-specific URL, like https://alerts-v2.weather.gov/products/NWS-IDP-PROD-3935103-3346792.

nmlorg added a commit that referenced this issue Dec 1, 2019
…ies.

This is very quick and dirty. Right now we display the temperature if it is outside of the range 65‒85℉ / 18‒29℃, and any free-form forecast text that contains the words "rain" or "snow".

A followup will extend this to include warnings and alerts (like "Winter Storm Warning: Heavy Mixed precipitation, Mixed Precipitation"). This should probably be displayed in groups in general, though, rather than just as additional weather exceptions (both because the information is more pressing and because alerts aren't really forecasted).

See #80.
@nmlorg
Copy link
Owner Author

nmlorg commented Dec 2, 2019

As of dddc581, the bot displays the temperature and short form of the hourly forecast for each event's start time iff the latter contains one of: 'blizzard', 'freezing', 'heavy', 'hurricane', 'ice', 'snow', 'tornado', 'tropical'.

For weather advisories, I'm leaning toward having the bot announce them as they are posted/are updated/expire, as completely independent messages (even if no regular announcements are configured?).

This could be kept separate:  If a group is configured either with an explicit location, or has explicitly opted in to weather advisories, go ahead.

Otherwise, it could guess at the group's location by examining its configured calendars for upcoming (and also past?) events. It may need to go beyond the currently configured /events range, however, and/or go before the range to check past events, so this might end up being a bit invasive. (m.u.eventutil.get_group_events might need to bypass m.c.multicalendar.MultiCalendar.get_overlap (or partially reimplement it, or call it multiple times) to get a usable collection of events, then perform/duplicate the date range filtering itself.)

This could also be hybrid:  Only an explicitly configured location is used for advisories, but as part of a pseudo schema change the bot could do a one-off examination of each group's configured calendars to set an initial explicit location.

I think I'm leaning toward having the bot self configure on the fly, just calling get_overlap(now, now + max(period, 90 * 24 * 60 * 60)), then manually filtering the returned value for the actual period (the same way it manually filters for count). The return type could then be changed from a list of events to a tuple of (alerts, events). The /events handler could ignore the alerts (maybe?) but the daily announcement loop could examine all groups with one or more calendars (and a timezone?) set and use the existing get_group_events calls to independently identify weather alerts to announce (shoving them into the same cache as the most-recent daily announcement, so it can only post on change).

@Raeitus
Copy link

Raeitus commented Dec 2, 2019

Would be nice to change the weather provider to https://openweathermap.org/ instead of the US Gov Weather as it covers weather world wide and has a lot of APIs to help developers.

It is also used in many open sourced weather apps.

@nmlorg
Copy link
Owner Author

nmlorg commented Dec 2, 2019

Minor implementation note:  We'll always be going from free-form[ish] address string to either alerts or forecast, but won't always (ever?) be pulling both alerts and forecasts at the same time. It might make sense to introduce a new geoutil.Geo (or Location, Point) class with get_forecast(when) and get_alerts() methods.

Alternatively, just change hourlyforecast to accept an address and perform the [self-caching] geocode call (and do the time filtering) itself.

nmlorg added a commit that referenced this issue Dec 10, 2019
… at least one event (with a geocode-able location) in the next 90 days.

See #80 (comment).

Test running this for the past few days, it turns out there's a lot of noise due to both (1) api.weather.gov's intermittent unavailability and (2) NWS frequently updating alerts to tweak the wording, estimates, or affected areas. The latter sometimes causes alerts to be re-posted even if the 250-character blurb doesn't change, simply because the way they update an alert is to cancel it and issue a brand new one in its place (so the alert id, which is included in the URL, changes).

A followup should probably include some kind of diffing behavior, possibly literally calling _quick_diff, but tweaking it to at least show 250 characters of context, and possibly allowing it to actually find multiple changes.
@nmlorg
Copy link
Owner Author

nmlorg commented Dec 10, 2019

Test running 04b9d91 for the past few days, it turns out there's a lot of noise due to both (1) api.weather.gov's intermittent unavailability and (2) NWS frequently updating alerts to tweak the wording, estimates, or affected areas. The latter sometimes causes alerts to be re-posted even if the 250-character blurb doesn't change, simply because the way they update an alert is to cancel it and issue a brand new one in its place (so the alert id, which is included in the URL, changes).

For example:

1:00:04 PM
Winter Weather Advisory NWS-IDP-PROD-3947931-3356042

...QUICK BURST OF HEAVY SNOW TONIGHT THROUGH MONDAY...

.A Winter Storm Warning has been issued for central Minnesota, namely Douglas, Todd, Morrison, Mille Lacs and Kanabec counties, for tonight through Monday morning.

A Winter Weather Advisory re…
3:00:08 PM
Winter Weather Advisory NWS-IDP-PROD-3948131-3356175

...QUICK BURST OF HEAVY SNOW TONIGHT THROUGH MONDAY...

.A Winter Storm Warning has been issued for central Minnesota, namely Douglas, Todd, Morrison, Mille Lacs and Kanabec counties, for tonight through Monday morning.

A Winter Weather Advisory re…
6:00:08 PM
Winter Weather Advisory NWS-IDP-PROD-3948271-3356260

...QUICK BURST OF HEAVY SNOW TONIGHT THROUGH MONDAY WILL IMPACT MONDAY MORNING COMMUTE...

.A Winter Storm Warning continues for central Minnesota, namely Douglas, Todd, Morrison, Mille Lacs and Kanabec counties, for tonight through Monday morning.
…
1:00:06 AM
Winter Weather Advisory NWS-IDP-PROD-3948605-3356489

...QUICK BURST OF HEAVY SNOW WILL IMPACT MONDAY MORNING COMMUTE...

.A Winter Storm Warning continues for central Minnesota, namely Douglas, Todd, Morrison, Mille Lacs and Kanabec counties, through Monday morning.

A Winter Weather Advisory is now i…

A followup should probably include some kind of diffing behavior, possibly literally calling _quick_diff, but tweaking it to at least show 250 characters of context, and possibly allowing it to actually find multiple changes. (Maybe just run it as is on each paragraph?)

nmlorg added a commit that referenced this issue Dec 10, 2019
…ates until the next announcement.

If the most-recent weather alert is deleted, act as if it hadn't been sent in the first place (i.e. go ahead with sending an update, just drop the reply_to_message_id).

Fixes #79. Also see #80 (comment) (upcoming diffing behavior will be affected).
@nmlorg
Copy link
Owner Author

nmlorg commented Dec 11, 2019

Feedback:

While it's very considerate of you to post these, my phone, my computer, the radio, and the TV all consistently update me on the weather so it's a little excessive.

These weather updates would be most salient if they were made during or right before any sanctioned events on the calendar

(This particular group has had 11 alerts posted in the past 4 days.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants