Also on Mac. I use BBedit for all my yaml editing.
Thanks, I’ve updated my code for the dates from/to section to match yours, as it looks a bit clearer than what I was using
Just had a last minute met office warning of ice go off at around 10pm on my phone from met office app. Took about 10mins to show in home-assistant but no notification from home-assistant from the automation which did work a few days ago…
Does it only look per ‘day’? or does it ping out as they come in?
Looks like the somerset sensor isn’t working as no entity with this name…
Any ideas on what I’ve missed? Thanks
Ok all fixed. Was some syntax errors but mainly I need to start using separate.yaml files to keep it all working.
Thanks guys for making this its super cool!
Glad you got it sorted!
you can set the frequency (it’s optional but not sure what the default is):
sensor:
platform: feedparser
scan_interval:
hours: 1
Although I’m searching the region ‘sw’ I’m also checking the summary for ‘Devon’ - in the same way as posted above for ‘Somerset’
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Devon' ignorecase=True) %}
As the current Ice warning for the region sw only applies to Gloucestershire, Swindon and Wiltshire, I was expecting to see the ‘No warnings at present’ message in my alerts popup, as per the code:
{% else %} No warnings at present
However nothing is rendering in my popup at all. I’ve used the same spacing and indentation as per what has been posted above, as far as I can tell. I’ve tried swapping ‘Devon’ for ‘Gloucestershire’, and reloaded my templates, but I’m still not getting the current warning displaying in my popup. Is anyone able to check this with their code and see if the same happens? If not, there must be something not quite right with my code here:
Code
- type: markdown
content: >
{% if state_attr('sensor.weather_alerts','entries') != [] %}
{% for item in state_attr('sensor.weather_alerts','entries') %}
{% for type, icon in
[
('extreme heat', 'weather-sunny-alert'),
('fog', 'weather-fog'),
('ice', 'car-traction-control'),
('lightning', 'weather-lightning'),
('rain', 'weather-pouring'),
('rain, wind', 'weather-pouring'),
('snow', 'weather-snowy-heavy'),
('snow, ice', 'weather-snowy-heavy'),
('thunderstorm', 'weather-lightning'),
('thunderstorms', 'weather-lightning-rainy'),
('wind', 'weather-windy')
]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Devon' ignorecase=True) %}
{% set color = item.summary.split(' ')[0] %}
{% set summary = item.summary | regex_findall_index('(.*) affecting South West England: (.*) valid from (.*) to (.*)', ignorecase=True) %}
{% set link = item.link %}
{% set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{% set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{% set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{% set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{% set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{% set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
| | |
| -: | -- |
| <font color = {%- if 'Yellow' == color %}'gold' {%- elif 'Amber' == color %}'darkorange' {%- else %}'firebrick' {%- endif %}>
<ha-icon icon={{ "'mdi:" + icon + "'" }}>
</ha-icon></font>
| <a href='{{ link }}'>**{{ summary[0] }}** </a>
|
| from: | **{{ time_local_from }}**, {{ date_from }} |
| to: | **{{ time_local_to }}**, {{ date_to }} |
{% endfor %}
<br>
{% endfor %}
{% else %} No warnings at present
{% endif %}
@Scoff Well spotted. It works when there are no weather alerts at all, but not when there are alerts, just not for your area. Here is the ‘fix’:
Create a new sensor that is specific to Devon:
template: #---------------------------------------------------------------------
- sensor:
- name: "Weather Alerts Devon"
state: >
{{ state_attr('sensor.weather_alerts','entries')
| map(attribute='summary')
| select('search', 'Devon')
| list
| count
}}
…and then change that line in the card to:
content: >
{% if states('sensor.weather_alerts_devon') != '0' %}
Sorry, I didn’t notice this as I use (my version of) sensor.weather_alerts_devon
in a conditional card that hides the whole thing when there is no alert.
Please let me know that this works for you.
For anyone else that is using this code, here is the full package (for se/Oxon):
Code
sensor: #-----------------------------------------------------------------------
- platform: feedparser
name: "Weather Alerts"
feed_url: 'http://metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/se'
scan_interval:
hours: 1
date_format: '%a, %b %d %I:%M %p'
inclusions:
- summary
- link
template: #---------------------------------------------------------------------
- sensor:
- name: "Weather Alerts Oxfordshire"
state: >
{{ state_attr('sensor.weather_alerts','entries')
| map(attribute='summary')
| select('search', 'Oxfordshire')
| list
| count
}}
automation: #-------------------------------------------------------------------
- alias: "Weather: Notify weather warnings"
id: weather_notify_warnings
trigger:
- platform: state
entity_id: sensor.weather_alerts_oxfordshire
variables:
message: |
{% for item in state_attr('sensor.weather_alerts','entries') %}
{% for type in [
('extreme heat'),('fog'),('ice'),('lightning'),('rain'),('rain, wind'),('snow'),('snow, ice'),('thunderstorm'),('thunderstorms'),('wind')]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Oxfordshire', ignorecase=True) %}
{% set summary = item.summary | regex_findall_index('(.*) of (.*) affecting .* valid from (.*) to (.*)', ignorecase=True) %}
{% set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{% set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{% set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{% set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{% set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{% set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{{ summary[0] }}
{{ summary[1] }}
{{ time_local_from }}➜{{ time_local_to }}
{{ date_from }}
{% endfor %}
{% endfor %}
condition:
- "{{ trigger.to_state.state not in ['unknown', 'unavailable','0'] }}"
- "{{ trigger.from_state.state not in ['unknown', 'unavailable','0'] }}"
action:
- service: notify.notify
data:
title: "Met Office"
message: "{{ message }}"
data:
tag: weather_alert # will replace earlier alerts with this tag
…and the card:
type: markdown
content: >
{% if states('sensor.weather_alerts_oxfordshire') != '0' %}
{% for item in state_attr('sensor.weather_alerts','entries') %}
{% for type, icon in
[
('extreme heat', 'weather-sunny-alert'),
('fog', 'weather-fog'),
('ice', 'car-traction-control'),
('lightning', 'weather-lightning'),
('rain', 'weather-pouring'),
('rain, wind', 'weather-pouring'),
('snow', 'weather-snowy-heavy'),
('snow, ice', 'weather-snowy-heavy'),
('thunderstorm', 'weather-lightning'),
('thunderstorms', 'weather-lightning-rainy'),
('wind', 'weather-windy')
]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Oxfordshire', ignorecase=True) %}
{% set color = item.summary.split(' ')[0] %}
{% set summary = item.summary | regex_findall_index('(.*) affecting London & South East England: (.*) valid from (.*) to (.*)', ignorecase=True) %}
{% set link = item.link %}
{% set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{% set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{% set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{% set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{% set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{% set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
| | |
| -: | -- |
| <font color = {%- if 'Yellow' == color %}'gold' {%- elif 'Amber' == color %}'darkorange' {%- else %}'firebrick' {%- endif %}>
<ha-icon icon={{ "'mdi:" + icon + "'" }}>
</ha-icon></font>
| <a href='{{ link }}'>**{{ summary[0] }}** </a>
|
| from: | **{{ time_local_from }}**, {{ date_from }} |
| to: | **{{ time_local_to }}**, {{ date_to }} |
{% endfor %}
<br>
{% endfor %}
{% else %} No warnings at present
{% endif %}
btw, how did you hide your code behind that drop-down arrow? Edit: worked it out - thanks!
Ahh I see, thanks very much for that, i’ll get the additional devon specific sensor set up, and amend my card to reference that sensor accordingly.
This is great, I just had to modified automation a bit as it produces to many empty lines. Also added some emojis
- alias: "Weather: Notify weather warnings"
id: weather_notify_warnings
trigger:
- platform: state
entity_id: sensor.weather_alerts_oxfordshire
variables:
message: |
{%- for item in state_attr('sensor.weather_alerts','entries') %}
{%- for type in [
('extreme heat'),('fog'),('ice'),('lightning'),('rain'),('rain, wind'),('snow'),('snow, ice'),('thunderstorm'),('thunderstorms'),('wind')]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Oxfordshire', ignorecase=True) %}
{%- set summary = item.summary | regex_findall_index('(.*) of (.*) affecting .* valid from (.*) to (.*)', ignorecase=True) %}
{%- set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{%- set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{%- set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{%- set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{%- set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{%- set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
<b>⚠️ {{ summary[0] }}</b>
{{ summary[1] }}
{{ time_local_from }} ➜ {{ time_local_to }}
{%- if date_from == date_to %}
{{ date_from }}
{%- else %}
{{ date_from }} ➜ {{ date_to }}
{%- endif %}
{%- endfor %}
{%- endfor %}
condition:
- "{{ trigger.to_state.state not in ['unknown', 'unavailable','0'] }}"
- "{{ trigger.from_state.state not in ['unknown', 'unavailable','0'] }}"
action:
- service: notify.notify
data:
title: "⛅ Met Office"
message: "{{ message }}"
data:
tag: weather_alert # will replace earlier alerts with this tag
Interesting - I don’t get any empty lines at all.
Maybe that’s Android issue. BTW empty lines are between each item (when you have at least 2 warnings) so they are initially not well visible but when you put the message part code into the dev tools template, you may see it @jchh
No, I haven’t had extra lines with 2 simultaneous warnings (at least I didn’t notice it), but will double check the next time I get 2 warnings.
Dev tools does not always display exactly the same as in the card.
The card works perfectly fine, it is just a notification on the mobile phone (at least Android)
You can always get rid of extra lines, just use >-
instead of |
If you want to force a new line when you do that, you need to have 2 returns then.
got it - I don’t have an Android phone.
If anyone would like to easily use warnings data in any card I suggest to add attributes data to your region template sensor like below:
- sensor:
- name: "Weather Alerts Oxfordshire"
state: >
{{ state_attr('sensor.weather_alerts','entries')
| map(attribute='summary')
| select('search', 'Manchester')
| list
| count
}}
attributes:
warnings: >-
{%- set data = namespace(warnings=[]) %}
{%- for item in state_attr('sensor.weather_alerts','entries') %}
{%- for type, icon in
[
('extreme heat', 'weather-sunny-alert'),
('fog', 'weather-fog'),
('ice', 'car-traction-control'),
('lightning', 'weather-lightning'),
('rain', 'weather-pouring'),
('rain, wind', 'weather-pouring'),
('snow', 'weather-snowy-heavy'),
('snow, ice', 'weather-snowy-heavy'),
('thunderstorm', 'weather-lightning'),
('thunderstorms', 'weather-lightning-rainy'),
('wind', 'weather-windy')
]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Oxfordshire', ignorecase=True) %}
{%- set summary = item.summary | regex_findall_index('(.*) of (.*) affecting .* valid from (.*) to (.*)', ignorecase=True) %}
{%- set color = item.summary.split(' ')[0] %}
{%- set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{%- set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{%- set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{%- set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{%- set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{%- set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{%- set data.warnings = data.warnings + [
{
"summary": summary[0],
"type": type,
"color": color,
"time_utc_from": time_utc_from,
"time_utc_to": time_utc_to,
"time_local_from": time_local_from,
"time_local_to": time_local_to,
"date_from": date_from,
"date_to": date_to,
"url": item.link,
"icon": "mdi:" + icon
}
]
%}
{%- endfor %}
{%- endfor %}
{{ data.warnings }}
You will get additional list of warnings in sensor attributes with easily accesible data
Thanks for providing this. I’ve just set up a notification automation for my weather alerts. Do you know if It’s possible to include the link URL within the notification, so that you can click on it and go to the specific weather warning on the MET Office website? I can do this successfully on my dashboard using a markdown card for the weather alert, by using:
{% set link = item.link %}
and then
<a href="{{ link }}" target="_blank">
however it doesn’t look like you can template the link in the notify notification in the same way?
Yes, you can.
Here is my version. Just check the link part out.
- type: markdown
content: >
{% if states('sensor.weather_alerts_oxfordshire') != '0' %}
{% for item in state_attr('sensor.weather_alerts','entries') %}
{% for type, icon in
[
('extreme heat', 'weather-sunny-alert'),
('fog', 'weather-fog'),
('ice', 'car-traction-control'),
('lightning', 'weather-lightning'),
('rain', 'weather-pouring'),
('rain, wind', 'weather-pouring'),
('snow', 'weather-snowy-heavy'),
('snow, ice', 'weather-snowy-heavy'),
('thunderstorm', 'weather-lightning'),
('thunderstorms', 'weather-lightning-rainy'),
('wind', 'weather-windy')
]
if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) and item.summary | regex_findall('Oxfordshire', ignorecase=True) %}
{% set color = item.summary.split(' ')[0] %}
{% set summary = item.summary | regex_findall_index('(.*) affecting London & South East England: (.*) valid from (.*) to (.*)', ignorecase=True) %}
{% set link = item.link %}
{% set time_utc_from = summary[2][0:2] ~':'~ summary[2][2:4] %}
{% set time_utc_to = summary[3][0:2] ~':'~ summary[3][2:4] %}
{% set date_from = summary[2][5:8] +'-'+ summary[2][9:11] +'-'+ summary[2][12:] %}
{% set date_to = summary[3][5:8] +'-'+ summary[3][9:11] +'-'+ summary[3][12:] %}
{% set time_local_from = ((now().date() ~ ' ' ~ time_utc_from ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
{% set time_local_to = ((now().date() ~ ' ' ~ time_utc_to ~ "+00:00") | as_datetime | as_local).strftime('%H:%M') %}
| | |
| -: | -- |
| <font color = {%- if 'Yellow' == color %}'gold' {%- elif 'Amber' == color %}'darkorange' {%- else %}'firebrick' {%- endif %}>
<ha-icon icon={{ "'mdi:" + icon + "'" }}>
</ha-icon></font>
| <a href='{{ link }}'>**{{ summary[0] }}** </a>
|
| from: | **{{ time_local_from }}**, {{ date_from }} |
| to: | **{{ time_local_to }}**, {{ date_to }} |
{% endfor %}
<br>
{% endfor %}
{% else %} No warnings at present
{% endif %}
and the sensors. Note the feedparser one include the link…
sensor: #-----------------------------------------------------------------------
- platform: feedparser
name: "Weather Alerts"
feed_url: 'http://metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/se'
scan_interval:
hours: 1
date_format: '%a, %b %d %I:%M %p'
inclusions:
- summary
- link
template: #---------------------------------------------------------------------
- sensor:
- name: "Weather Alerts Oxfordshire" # for conditional card & markdown card as weather_alerts can be !=0 but have no Oxon content
state: >
{{ state_attr('sensor.weather_alerts','entries')
| map(attribute='summary')
| select('search', 'Oxfordshire')
| list
| count
}}