I have installed this HACS device called NWS Alerts to give me access to NWS weather alerts. It produces a numeric value that equals the number of active alerts. If you look at its attributes, you see the text of the alerts in a not very user-friendly format.
Is there some other device I can use to display the actual alert text on a dashboard? If not can someone point me to an example of how to write a python script to extract and format the attribute info for display on a dashboard?
I believe the alert text is an attribute when there is one active. It pretty bizarre that this isnāt mentioned in the documentation. Anyways, you can get all kinds of information directly from the NWS with a bit of study and the RESTful integration. The NWS forecasts are better than whats available from the various HA weather integrations.
OK Iāve found some info on how to do templates. Looks pretty straightforward. But the one I saw just gets the attribute text. For this device the text looks like this:
- Event: Winter Weather Advisory
ID: 2954b65b-3d02-b971-5cc0-c49376c4edaf
URL: >-
https://api.weather.gov/alerts/urn:oid:2.49.0.1.840.0.e7aa5e0f16df9a0e7e0bd54d02befd197bcc48bb.001.2
Headline: >-
WINTER WEATHER ADVISORY IN EFFECT FROM 3 PM THIS AFTERNOON TO 5 AM MST
SATURDAY FOR ELEVATIONS ABOVE 5000 FEET... ...WINTER WEATHER ADVISORY IS
CANCELLED
Type: Alert
Status: Actual
Severity: Moderate
Certainty: Likely
Sent: '2025-03-14T02:07:00-07:00'
Onset: '2025-03-14T15:00:00-07:00'
Expires: '2025-03-14T15:00:00-07:00'
Ends: '2025-03-15T05:00:00-07:00'
AreasAffected: Mazatzal Mountains; Pinal/Superstition Mountains; Southeast Gila County
Description: |-
* WHAT...Snow expected for elevations above 5000 feet. Total snow
accumulations between 4 and 6 inches.
* WHERE...Mazatzal Mountains, Pinal/Superstition Mountains, and
Southeast Gila County.
* WHEN...From 3 PM this afternoon to 5 AM MST Saturday.
* IMPACTS...Travel could be very difficult. The hazardous conditions
could impact the Friday evening commute.
Instruction: |-
Slow down and use caution while traveling. The latest road
conditions for the s
tate you are calling from can be obtained by
calling 5 1 1.
Worse, yesterday when there were three warnings, they were just stacked on top of one another. At most Iād like to display the what/where/when and have it linked to the URL. Is there a way to parse?
@dzmiller I will have a look at what I can get from NWS, but this has what I need if I can find a way to parse it.
The RESTful integration will put the JSON into entities and attributes. Claude can help you with how to parse the one to many array which is the most complicated part.
Itās worth learning how to parse the JSON into entities as this is the standard API format. Learn it once and apply it everywhere. Also using Claude for things like JSON and regex is often good enough to feel like cheating.
But you will need to think about what data structure in HA you want with the alerts, which the integration author did not do. Nothing wrong with the way he did it, its just not particularly conducive for quality output to either the front end or voice.
What is going to be the challenge for me is that we donāt get a lot of severe weather where I live, so I will need to wait till we do and save the json so I can develop a way to use it.
OK here is the solution Iāve come up with. It is detecting No active alerts, so presumably it will detect active alerts too. Will have to wait until there is an alert for my area to know for sure.
Add to configuration.yaml (substitute your coordinates for {lat},{long}):
For anyone thatās interested, Iāve refined a markdown card that prioritizes alerts, de-duplicates, and displays them on the dashboard. Special weather statements will provide a description of the weather; others only show the alert and expiration.
Code:
type: conditional
conditions:
- entity: sensor.nws_alerts_alerts
state_not: "0"
card:
type: markdown
content: >-
{% set alerts = state_attr('sensor.nws_alerts_alerts', 'Alerts') |
default([]) %} {% set priority_order = ['Tornado Warning', 'Severe
Thunderstorm Warning', 'Flash Flood Warning',
'Tornado Watch', 'Severe Thunderstorm Watch', 'Flood Watch'] %}
# ā ļø WEATHER ALERTS ā ļø
{% macro render_alert(alert) %}
{% set expires = as_timestamp(alert.Expires) if alert.Expires else 0 %}
{% set ends = as_timestamp(alert.Ends) if alert.Ends else 0 %}
{% set relevant_time = expires if expires > ends else ends %}
{% set label = 'Expires' if expires >= ends else 'Ends' %}
{% set time_remaining = relevant_time - as_timestamp(now()) %}
{% set days = (time_remaining // 86400) | int %}
{% set hours = (time_remaining % 86400) // 3600 %}
{% set minutes = (time_remaining % 3600) // 60 %}
{% set formatted_time = relevant_time | timestamp_custom('%-d %b %H:%M', true) %}
---
## **{{ alert.Event }}**
> {% if time_remaining >= 86400 -%}{{ days }}d {{ '%02d' % hours }}:{{ '%02d' % minutes }}({{ label }}: {{ formatted_time }}){% elif time_remaining > 0 -%}{{ '%02d' % hours }}:{{ '%02d' % minutes }} Remaining
> _({{ label }}: {{ formatted_time }})_
{% else -%}
_EXPIRED_
{% endif %}
{% if "Special" in alert.Event and alert.Description %}
{{ alert.Description }}
{% endif %}
{% endmacro %}
{% for event_type in priority_order %}
{% set matched = alerts | selectattr('Event', 'equalto', event_type) | list %}
{% if matched %}
{% set most_recent = matched | sort(attribute='Expires', reverse=True) | first %}
{{ render_alert(most_recent) }}
{% endif %}
{% endfor %}
{% set others = alerts | rejectattr('Event', 'in', priority_order) | list %}
{% for alert in others %}
{{ render_alert(alert) }}
{% endfor %}
text_only: true
Thanks. Mine doesnāt seem to be working so I will try this. One question: for the priority, where can I find a list of possible alerts? We donāt have tornados where I live but we have dust storms so I need to know the correct phrase.
Update: an almost complete list is here. For dust storms itās āDust Storm Warningā.
An alert just came through but the exact same alert is repeated four times. Iām guessing this happens because itās checking periodically and finding the same alert when it does. Is there some way the script can check if an alert is already being displayed? I donāt know enough about YAML to figure this out.
Also Iād like to ignore alerts that arenāt in my priority list. Do I assume correctly that I can do that by deleting that last block that starts with {% set others = alerts?
If you are in the East Valley like I am, I get about three to four alerts at certain times of the year. Weather, dust storms, polution level, etc. Mine duplicates as well because they keep sending them out.
Would you mind sharing your yaml. I would like to see what a setup looks like specifically designed for our area, where we very rarely have Ice and Snow storms.
Thanks