Severe Weather Alerts from the US National Weather Service

EDIT (04/2023): There is a new integration that can be used in place of the information found in this first post.

It uses the custom integration found here. There is additional information at that link for configuration and usage examples


Due to the possible discontinuation of the WU weather API at the end of the year, I was motivated to find a reliable alternative for timely emergency weather notifications. We already have a weather radio but it’s in a part of the house that we might not hear at all times so I wanted to come up with a way to augment that system. Here is what I’ve come up with.

This set up uses the public API directly from the US National Weather Service so unfortunately it won’t be useful to anyone outside the US. But I recently saw a post by a non-US user addressing the same scenario for the EU so that may be an option for those users.

This will allow several functions including a persistent pop-up notification on your HA front end, a notification to whichever notify service you use (I’m using Pushbullet in this example), and, if you use the awesome custom component by @keatontaylor (Echo Devices (Alexa) as Media Player - Testers Needed), it will also trigger an announcement to all of your Echo devices.

I’m no programming expert so some of this stuff might be done more smoothly (and I’m open to suggestions…) but I’ve tested it as much as I can and it’s working so far. I haven’t been able to fully test the “warning” test yet but I’m pretty confident it will work. At least it worked using created data in my template editor.

Also thanks to @pnbruckner for helping me sort out some details.

You first need to find either your NWS Zone ID or County ID. I’m not sure which is better but I used my Zone ID here.

You can find your Zone ID by going to https://alerts.weather.gov/, scroll down to your state and click on the “zone list” then look for the entry for your county.

Here are the code sections:

Once you have your Zone ID you create two sensors, replacing my zone id (INZ009) with yours. The Zone ID is case sensitive!:

  sensor:  
    - platform: rest
      resource: https://api.weather.gov/alerts/active/count
      name: NWS Alert Count
      value_template: >
        {% if value_json.zones.INZ009 is defined %}
          {{ value_json.zones.INZ009 }}
        {% else %}
          0
        {% endif %}
      headers:
        User-Agent: Homeassistant
        Accept: application/ld+json
      scan_interval: 60
        
    - platform: rest
      resource: https://api.weather.gov/alerts/active?zone=INZ009
      name: NWS Alert Event
      value_template: >
        {% if value_json.features[0] is defined %}
          {{ value_json['features'][0]['properties'].event }}
        {% else %}
          None
        {% endif %}
      json_attributes:
        - features
      headers:
        User-Agent: Homeassistant
        Accept: application/geo+json
      scan_interval: 60

Then you create the automations:

- alias: 'NWS Weather Alert Pop Up Control'
  trigger:
    platform: state
    entity_id: sensor.nws_alert_count
  action:
    service: script.nws_popup_on_wx_alert
    
- alias: NWS Notification Weather Alert
  trigger:
    platform: state
    entity_id: sensor.nws_alert_count
  condition:
    condition: template
    value_template: '{{states.sensor.nws_alert_count.state | int > 0}}'
  action:
    - service: notify.pushbullet_notify
      data:
        message: "NWS: {{ states.sensor.nws_alert_event.state }}"
        
- alias: NWS Announcement Weather Alert
  trigger:
    - platform: state
      entity_id: sensor.nws_alert_count
  condition:
    condition: and
    conditions:
      - condition: template
        value_template: '{{states.sensor.nws_alert_count.state | int > 0}}'
        ## Added a time condition because I don't want a non-emergency alert waking me up
      - condition: or
        conditions:
          - condition: time
            after: '09:00:00'
            before: '23:00:00'
          - condition: template
            value_template: >
              {{ 'Warning' in states.sensor.nws_alert_event.state }}
  action:
    #- service: media_player.volume_set
    #  data:
    #    entity_id:
    #      - media_player.computer_room_dot
    #      - media_player.kitchen_dot
    #      - media_player.livingroom_dot
    #      - media_player.master_bedroom_dot
    #    volume_level: 0.9
    - service: media_player.alexa_tts
      data_template:
        entity_id: 
          - media_player.computer_room_dot
          - media_player.kitchen_dot
          - media_player.livingroom_dot
          - media_player.master_bedroom_dot
          - media_player.garage_dot
          - media_player.big_room_dot
        message: "Attention!. . . Attention!. . . The National Weather Service has issued a 
        {{ states.sensor.nws_alert_event.state }} for your area. 
        It expires at {{ as_timestamp(state_attr('sensor.nws_alert_event', 'features')[0].properties.expires)| timestamp_custom('%-I:%M %p on %-m-%-d-%Y') }}."
    - delay: '00:00:10'
    - service: media_player.alexa_tts
      data_template:
        entity_id: 
          - media_player.computer_room_dot
          - media_player.kitchen_dot
          - media_player.livingroom_dot
          - media_player.master_bedroom_dot
          - media_player.garage_dot
          - media_player.big_room_dot  
        message: "Attention!. . . Attention!. . . The National Weather Service has issued a 
        {{ states.sensor.nws_alert_event.state }} for your area. 
        It expires at {{ as_timestamp(state_attr('sensor.nws_alert_event', 'features')[0].properties.expires)| timestamp_custom('%-I:%M %p on %-m-%-d-%Y') }}."

You’ll notice I repeat the announcement twice in case the first announcement doesn’t wake you up. And the only announcement that happens between 11PM & 9AM are alerts that contain a ‘warning’ in the event.

And I haven’t worked out the volume setting part yet. If anyone has any working solutions feel free to let me know.

Last you create the script that generates the persistent notification pop-up:

nws_popup_on_wx_alert:
    alias: NWS Weather Alert Pop Up
    sequence:
        ## Dismiss any current alert so the UI isn't filled 
        ## up with these if there are more then one.
        ## Only show the latest alert
      - service: persistent_notification.dismiss
        data:
          notification_id: "nwswxalert"
        ## Create a new persistant notification in the UI for a new alert
      - service_template: >
          {% if states.sensor.nws_alert_event.state != 'None' %}
            persistent_notification.create
          {% endif %}
        data_template:
          notification_id: "nwswxalert"
          message: "{{ state_attr('sensor.nws_alert_event', 'features')[0].properties.description }}"
          title: '{{ states.sensor.nws_alert_event.state }}'    

I will (hopefully) also come up with a way to handle notifications when there are more than one simultaneous alerts for an area. I have a work in progress but I need to be able to test it.

If you don’t have any active alerts and would like to test all of this the just go to https://api.weather.gov/alerts/active/count and search in those results for a zone that has an entry and use that ID.

I hope this helps others and I’m looking forward to constructive feedback.

23 Likes

Ok, ironically I just received an alert on my weather radio that didn’t show up on the HA alert page.

For some reason the alert from the NWS didn’t get set for my zone id but it did for my county id.

So disregard what I said above about not using the county code. I modified my original sensors to catch both codes. You can find your county code at the same web address above used for finding the zone.

Here is the updated sensor section:

- platform: rest
  resource: https://api.weather.gov/alerts/active/count
  name: NWS Alert Count
  value_template: >
    {% if value_json.zones.INZ009 is defined %}
      {{ value_json.zones.INZ009 }}
    {% elif value_json.zones.INC033 is defined %}
      {{ value_json.zones.INC033 }}
    {% else %}
      0
    {% endif %}
  #json_attributes:
  #  - event
  #  - description
  #  - instructions
  #  - expires
  headers:
    User-Agent: Homeassistant
    Accept: application/ld+json
  scan_interval: 60
    
- platform: rest
  resource: https://api.weather.gov/alerts/active?zone=INZ009,INC033
  name: NWS Alert Event
  value_template: >
    {% if value_json.features[0] is defined %}
      {{ value_json['features'][0]['properties'].event }}
    {% else %}
      None
    {% endif %}
  json_attributes:
    - features
  #  - description
  #  - instructions
  #  - expires
  headers:
    User-Agent: Homeassistant
    Accept: application/geo+json
  scan_interval: 60

It’s really strange that several fog alerts got triggered for my zone id last night but today a severe thunderstorm watch didn’t get an alert set. That’s kind of ridiculous.

Oh, well. Using both should fix that. I hope…

1 Like

Nice job. I’m sure this will become more popular as weather underground phases out. I’m north of you up in canada though so cant use it. I’ll have to figure out some other way to get the blizzard warnings. Nice to see somebody preparing for the worst in terms of weather underground and the weather.

Thanks!

I’m sure that Canada has to have some equivalent that you can pull similar info from.

I looked quickly at environment canada’s website environment canada data services page .Dont really know to much about ways of getting data but looks like it would have to be rss feed parser setup …I dont think there is an api. I tried with ifttt rss feed reader with no success to get weather warnings. Its kind of above my knowledge level but maybe I will come back to it. I’m kind of at the level where I have integrated quite a few components even custom components and my interface and configuration.yaml are a mess and I think I have to start breaking out things with include …not to mention lovelace…ugh. Good job though I mean alot of this stuff is fun and although I wouldn’t completely rely on ha for this info this is something of real value that can make a serious difference

I tried to use a RSS feed component for pulling out some info from the feed but it seems that it doesn’t create attributes in a json standard format so I couldn’t figure out a reasonable way of using the info I needed from it.

Maybe now that I have a working alert system i can spend some time working that out too.

Yes I saw another thread where somebody was trying to use the ha feed parser for NOAA and I think was struggling with it. Thanks. Either way I have my snow shovel and sled dogs… just kidding the only huskies I know do not work for a living

Yep, I think that was probably me.

Now installed and will be testing in The Great State of Texas… where severe weather… just is.
Thank you.

I have recently developed the geo_location component, and am now in the process of adding platforms. My focus at the moment are GeoJSON and GeoRSS feeds, and the platforms include external events based on the vicinity to your HA installation.
In parallel I’m trying to make this new platform more useful, for example by implementing a geo location based automation trigger.
I haven’t looked at CAP feeds, but I believe they often also come with some sort of geo location information embedded.
If anyone is interested in looking into this, I’d be happy to help.

1 Like

@dasbooter and @finity

NOAA also puts out Common Alerting Protocol notices, which is what you might be noticing. I authored a little python library to convert all the CAP versions to standard Python objects.

I’m currently scraping a number of these alerts (NOAA, RFS, CA, Taiwan, and a few other places) and storing them in a PostGIS database. If you see some value in integrating it with HASS, then please let me know and I’d be happy to flush out some details.

2 Likes

YEAH!
Bad news… we had a really big storm here in Central Texas today.
Good news… This little thingie you put together worked flawlessly!

1 Like

Awesome, good to know!

I think…:worried:

Hope everyone is OK.

1 Like

When I saw the notification (I’m out of town), I called partner and ask if Alexa gave her a verbal warning. She confirmed that every one of our echo, and dots, did indeed speak up. She was a bit taken back because this was a new one but she is now finally acknowledging that my little hobby actually has a use. :slight_smile:

1 Like

I tried the sensor as posted by @finity, and it broke my recorder. Seems having a hurricane go by makes the list of alerts too long to stick into the database, and having an excessively long SQL query actually borks the recorder until the hass service is restarted. Icky.

 2018-10-10 10:36:40 ERROR (Recorder) [homeassistant.components.recorder.util] Error executing query: (_mysql_exceptions.DataError) (1406, "Data too long for column 'event_data' at row 1") [SQL: 'INSERT INTO events (event_type, event_data, origin, time_fired, created, context_id, context_user_id) VALUES (%s, %s, %s, %s, %s, %s, %s)'] [parameters: ('state_changed', '{"entity_id": "sensor.nws_alert_event", "new_state": {"last_changed": "2018-10-10T15:36:40.468924+00:00", "entity_id": "sensor.nws_alert_event", "con ... (68707 characters truncated) ... l; Santa Rosa Coastal; Okaloosa Coastal"}, "geometry": null, "type": "Feature"}], "friendly_name": "NWS Alert Event"}, "state": "Hurricane Warning"}}', 'LOCAL', datetime.datetime(2018, 10, 10, 15, 36, 40, 468997, tzinfo=<UTC>), datetime.datetime(2018, 10, 10, 15, 36, 40, 475520), 'aa244d704c424398a8fbf1959627dc03', None)] (Background on this error at: http://sqlalche.me/e/9h9h)

The family and the house are fine, we were just on the western edge of Michael’s path. Max winds around 35-40 knots. The worst damage was we had a trash can get blown over.

Anyways, how can we work around this? The recorder thing, not the trash can :grin:

You can select entities to ignore in the recorder. I haven’t set that sensor to be ignored but I also haven’t had more than 2 alerts at any time either so I haven’t had any crashes.

Try that and see what happens. I’ll do some more testing to see what I can get to fail.

Do you have any idea how many alerts were sent out simultaneously?

Glad to hear everyone in your circle is fine.

I’m sure it was a lot! Last year during hurricane Harvey my condo smoke/fire/carbon monoxide/weather warner went off so many times after we lost power that it wore out the fresh batteries I put in it.
Also… I recall the text of the alerts being WAY longer than 255 characters… if that impacts the code at all. :slight_smile:

I don’t think it affects anything because we are pulling the state out of the “event” title and it is less than 255 characters. I was told there are no limitations on the characters in the attributes tho. and “features” is an attribute of the sensor and that’s where all the text is in the alert.

The most alerts I saw active at one time was eight…it was ugly out there.

I think the recorder was trying to store the entire set of objects, and that ended up being a really long string.

I think the best solution is to just exclude that sensor from the recorder.