NWS - Weather.Gov - Custom Alert Pushes

This has been done via a HACS, but it wasn’t flexible enough for me. I have set up a system to push weather alerts from weather.gov to my phone via a persistent notification. I’m looking to improve this setup and would appreciate any input!

Change anything noted with CHANGE_ME

Limitations

  • No Idea how well this handles multiple notifications
  • The persistent message is cut off and wont show the whole message

Explanation:

  1. Mobile Device Notification Group:
    Defines a notification group named “Mobile Devices” that is used in the push notification automation.

  2. Weather Alerts JSON Pull:

  • Sets up a REST sensor to pull weather alert data from weather.gov for specific zones in Phoenix.
  • The User-Agent header follows etiquette guidelines from weather.gov documentation.
  • Data is fetched every 5 minutes and stored as JSON attributes.
  1. Weather Alerts Sensor Report:
    Creates a template sensor that consolidates multiple attributes from the JSON data, such as areas, events, effective times, expiry times, headlines, message types, severities, certainties, and urgencies.

  2. Active Weather Alerts Count:
    Another template sensor that counts the number of active weather alerts based on the JSON data. This is used for the automation.

  3. Automation:

  • Triggers when there is at least one active weather alert.
  • Sends a persistent notification to the mobile devices with details about the alert, including events, headlines, effective times, expiry times, severities, certainties, urgencies, message types, and areas.

Here’s my current configuration:
/homeassistant/configuration.yaml

# Mobile Device Notification Group
# This is used for pushing to multiple user devices. Not needed if you want to send to a single device.
notify:
  - name: Mobile Devices
    platform: group
    services:
      - service: mobile_app_CHANGE_ME
      - service: mobile_app_CHANGE_ME

# Weather Alerts JSON Pull
# This is where I pull the information from to build the sensor that the alerts use.
  - platform: rest
    name: Weather Alerts JSON
    resource: https://api.weather.gov/alerts/active?zone=AZZ550,AZZ548,AZZ543 #CHANGE_ME - Can be single or multiple zones
# Found on https://www.weather.gov/psr/Phoenix_CWA_Zones. Can also look here https://alerts.weather.gov/
    method: GET
    headers:
      User-Agent: (HomeAssistant, Email@CHANGE_ME.com) # Etiquette defined on https://www.weather.gov/documentation. Should be (application, [email protected])
      Accept: application/geo+json
    scan_interval: 300  # Check every 5 minutes
    timeout: 120 
    json_attributes:
      - features
    value_template: "{{ value_json['title'] }}"
    
# Weather Alerts Sensor Report
# This builds a single sensor with multiple attributes. Look at the sensor state for finding other alerts to poll.
template:
  - sensor:
      - name: "Weather Alert Sensor"
        state: >
          {% if states.sensor.weather_alerts_json.attributes.features %}
            {{ states.sensor.weather_alerts_json.attributes.features | length }} active alerts
          {% else %}
            No active alerts
          {% endif %}
        attributes:
          areas: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.areaDesc') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          events: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.event') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          effective_times: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.effective') | map('as_timestamp') | map('timestamp_custom', '%H:%M %m-%d-%Y') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          expiry_times: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.expires') | map('as_timestamp') | map('timestamp_custom', '%H:%M %m-%d-%Y') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          headlines: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.headline') | join(' | ') }}
            {% else %}
              unknown
            {% endif %}
          message_types: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.messageType') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          severities: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.severity') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          certainties: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.certainty') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
          urgencies: >
            {% if states.sensor.weather_alerts_json.attributes.features %}
              {{ states.sensor.weather_alerts_json.attributes.features | map(attribute='properties.urgency') | join(', ') }}
            {% else %}
              unknown
            {% endif %}
  - sensor:
  # You can also use https://api.weather.gov/alerts/active/count. I am using multiple zones so it is difficult to count (because two zones can have the same alert), so I am testing this.
      - name: "Active Weather Alerts Count"
        state: >
          {% if states.sensor.weather_alerts_json.attributes.features %}
            {{ states.sensor.weather_alerts_json.attributes.features | length }}
          {% else %}
            0
          {% endif %}

This is the automation I built in the UI and use to push to mobile devices.

alias: Active Weather Alerts Push
description: Sends a persistent notification for active weather alerts in Phoenix
trigger:
  - platform: numeric_state
    entity_id: sensor.active_weather_alerts_count
    above: 0
condition:
  - condition: template
    value_template: "{{ trigger.from_state.state | int == 0 }}"
action:
  - service: notify.mobile_devices
    data:
      title: Weather Alert
      message: >
        Events: {{ state_attr('sensor.weather_alert_sensor', 'events') }} \n
        Headlines: {{ state_attr('sensor.weather_alert_sensor', 'headlines') }}
        \n \n         Effective Times: {{
        state_attr('sensor.weather_alert_sensor','effective_times') }} \n 
        Expiry Times: {{ state_attr('sensor.weather_alert_sensor',
        'expiry_times') }} \n \n Severities: {{
        state_attr('sensor.weather_alert_sensor', 'severities') }} \n
        Certainties: {{ state_attr('sensor.weather_alert_sensor', 'certainties')
        }} \n  Urgencies: {{
        state_attr('sensor.weather_alert_sensor','urgencies') }} \n Message
        Types: {{ state_attr('sensor.weather_alert_sensor','message_types') }}
        \n \n Areas: {{ state_attr('sensor.weather_alert_sensor', 'areas') }} \n
mode: single
1 Like

Did something change? I don’t see a “length” field under “features” in the data being pulled back from api.weather.gov. How are you getting the number of warnings? I get “unavailable” returned and nothing works.

I haven’t been able to test this yet. I’ve only had a single push to my device at a time.

So it may return nothing with multiple alerts.

How are you even getting an alert count if the field you are using isn’t in the data? Or am I missing something you are doing?

Sorry, read that wrong on the length.

This is not working for me. Here is what I have.

       Events: {{ state_attr('sensor.nws_alerts', 'events') }}
        Headlines: {{ state_attr('sensor.nws_alerts', 'headlines') }}
        Effective Times: {{state_attr('sensor.weather_alert_sensor','effective_times') }}
        Expiry Times: {{ state_attr('sensor.weather_alert_sensor','expiry_times') }} 
        Severities: {{ state_attr('sensor.weather_alert_sensor', 'severities') }} 
        Certainties: {{ state_attr('sensor.weather_alert_sensor', 'certainties') }} 
        Urgencies: {{ state_attr('sensor.weather_alert_sensor','urgencies') }} 
        Message Types: {{ state_attr('sensor.weather_alert_sensor','message_types') }}
        Areas: {{ state_attr('sensor.weather_alert_sensor', 'areas') }} 

This is the read out.

    Events: None
    Headlines: None
    Effective Times: None
    Expiry Times: None 
    Severities: None 
    Certainties: None 
    Urgencies: None 
    Message Types: None
    Areas: None

So the only way I could get this to work is do this:

        Events: {{ state_attr('sensor.nws_alerts', 'Alerts')[0].Event }}
        Headlines: {{ state_attr('sensor.nws_alerts','Alerts')[0].Headline }}
        Effective Times: {{state_attr('sensor.nws_alerts','Alerts')[0].Onset }}
        Expiry Times: {{ state_attr('sensor.nws_alerts','Alerts')[0].Expires }} 
        Severities: {{ state_attr('sensor.nws_alerts','Alerts')[0].Severity }} 
        Certainties: {{ state_attr('sensor.nws_alerts','Alerts')[0].Certainty }} 
        Urgencies: {{ state_attr('sensor.nws_alerts','Alerts')[0].urgencies }} 
        Message Types: {{ state_attr('sensor.nws_alerts','Alerts')[0].Type }}
        Areas: {{ state_attr('sensor.nws_alerts','Alerts')[0].areas }} 

This works and is fine. But is there someway I can make the [0] a variable that when I create the sensor and message. It will count up to the state of the actual sensor state? Example my sensor.nws_alert is at 2 right now.

If not that is fine. I can hard code 5 or 6 layers. Some may never be used. I can’t remember how it was done in the past. It has been to many years ago.

Ryan