UK MET Office Severe Weather Warnings

I’m not sure if this is the answer to your question but I think so…

And as previously stated this was all written ages ago, it’s not great code but it works so I leave it alone.

I allow for up to five warnings at any one time;

#================
#=== Input Texts
#================
input_text:
  weather_warning1:
    min: 0
    max: 255

... etc ...

  weather_warning5:
    min: 0
    max: 255

I have the sensors as my previous post.

And I have this automation that saves the warnings:

  #==============================
  #=== Populate Weather Warnings
  #==============================
  - alias: Weather Populate Weather Warnings
    id: weather_populate_weather_warnings
    trigger:

      - platform: state
        entity_id: sensor.met_office_london_weather_warnings

      - platform: homeassistant
        event: start

    action:
      #=== Empty weather warning input texts
      - service: input_text.set_value
        data:
          entity_id:
            - input_text.weather_warning1
            - input_text.weather_warning2
            - input_text.weather_warning3
            - input_text.weather_warning4
            - input_text.weather_warning5
          value: ""

      #=== Check there are any weather warnings for London
      - condition: numeric_state
        entity_id: sensor.met_office_london_weather_warnings
        above: 0

      #=== Populate the input text for each warning
      - repeat:
          count: >
            {{ states('sensor.met_office_london_weather_warnings') }}
          sequence:
            - service: input_text.set_value
              data:
                entity_id: input_text.weather_warning{{ repeat.index }}
                value: >
                  {% set warning = state_attr('sensor.met_office_london_weather_warnings', 'warnings')[repeat.index-1].warning %}
                  {% set warning = warning.replace('affecting London & South East England)', 'affecting London') + '. ' %}
                  {% set period = state_attr('sensor.met_office_london_weather_warnings', 'warnings')[repeat.index-1].period %}
                  {{ warning + period }}

And this automation that handles the notifications (script.notify is my notification engine):

  #===============================
  #=== Notify of weather warnings
  #===============================
  - alias: Notify Weather Warnings
    id: notify_weather_warnings
    trigger:
      - platform: state
        entity_id: sensor.met_office_london_weather_warnings

      - platform: homeassistant
        event: start

    variables:
      message: >
        {% if states('sensor.met_office_london_weather_warnings') | int > 0 %}
          {% for warning in state_attr('sensor.met_office_london_weather_warnings', 'warnings') %}
            {%- set warning = state_attr('sensor.met_office_london_weather_warnings', 'warnings')[loop.index-1].warning %}
            {%- set warning = warning.replace('affecting London & South East England', 'affecting London') + '. ' %}
            {%- set period = state_attr('sensor.met_office_london_weather_warnings', 'warnings')[loop.index-1].period %}
            {%- set message = warning ~ period %}
            {%- if not loop.last %}
              {% set message = message ~ '<br>' %}
            {% endif %}
            {{- message }}
          {%- endfor %}
        {% endif %}
    action:
      #=== Remove all current notifications
      - service: persistent_notification.dismiss
        data:
          notification_id: weather_warning

      - service: script.notify
        data:
          tell: me
          mobile_app_tag: WEATHER_WARNING
          message: clear_notification

      #=== Continue if there are any weather warnings for London
      - condition: numeric_state
        entity_id: sensor.met_office_london_weather_warnings
        above: 0

      #=== Create HA Persistant notification
      - service: script.notify
        data_template:
          show: True
          notification_id: weather_warning
          title: 🌩️ Met Office Weather Warnings
          message: >
            {%- set message = message | replace('Red','<font color=firebrick>RED</font>') %}
            {%- set message = message | replace('Amber','<font color=DarkOrange>AMBER</font>') %}
            {%- set message = message | replace('Yellow','<font color=yellow>YELLOW</font>') %}

            {{ message }}

      #=== Notify Me
      - choose:
          - conditions: >
              {{ is_state('input_boolean.met_office_weather_warnings_notify_me', 'on') }}
            sequence:
              - service: script.notify
                data:
                  tell: me
                  title: 🌩️ Met Office Weather Warnings
                  mobile_app_tag: WEATHER_WARNING
                  message: >
                    {%- set message = message | replace('Red','<b><span style="color: red">RED</span></b>') %}
                    {%- set message = message | replace('Amber','<b><span style="color: #FF8C00">AMBER</span></b>') %}
                    {%- set message = message | replace('Yellow','<b><span style="color: yellow">YELLOW</span></b>') %}

                    {{ message }}

By way of thanks for this great contribution, just to note that current UK weather warnings seem to be combining “snow, ice” into a single alert, so I needed to add this to the alert dictionary for it to be parsed properly in the markdown card:

            {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'),
                                  ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), 
                                  ('snow, ice', 'weather-snowy-heavy'),
                                  ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'),
                                  ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}

...  rest of code here

           {% endfor %}
5 Likes

Thanks for the heads up.

I was wondering what the code would be to open the BBC weather warnings site, by clicking on the text that this entity generates. Is that possible at all?

You could include something like this

[BBC Weather Warnings](https://www.bbc.co.uk/weather/warnings/weather)

In the markdown

I managed to use the link that the sensor provides, and change the title of each alert into a clickable link.

Just need to add a couple of things to the content: key of the markdown card.

First, set a ‘link’ variable in the section where the other variables are set (I added it after the time_to variable):

{% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
{% set link = item.link %}  ### NEW LINE HERE

Then in the part where the text is formatted, change this:

**{{ summary[0] | title }}**

To this:

**<a href="{{ link }}" target="_blank">{{ summary[0] | title }}</a>**
2 Likes

Perfect, thanks so much. I’m going to look at how to pass that through to my notification.

I don’t think this is working properly with combo warnings - it seems fine when there are separate warnings for wind and rain, but Met Office can and do issue warnings for multiple elements eg wind and rain in the same warning. One such wind + rain warning has been issued today, but isn’t displaying in the card.

I am seeing multiple warnings for met office. Seems to be working for me

Hi

Great work. Ive used your code and all is coming through brilliantly for the Yorkshire and Humber and I have 2 entities but was wondering.

I know you said it was old script but I was wondering if you have had to update as I cant see a script.notify in scripts ?

I dont use the Marker Card but mainly mushroom, do you have it show on any cards on your dashboard ?

Thanks in advance

Martyn

Hello

Does this still work for anyone else? As I have weather warnings but it doesn’t show on this card anymore

    card:
      type: markdown
      card_mod:
        style:
          .: |
            ha-card {
              --mdc-icon-size: 40px;
            }
          ha-markdown:
            $: |
              td {
                vertical-align: top;
              }
      content: |
        {% if state_attr('sensor.weather_alerts','entries') != 0 %}
          {% for item in state_attr('sensor.weather_alertsne','entries') %}
            {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'),
                                  ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), 
                                  ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'),
                                  ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}
              {% set color = item.summary.split(' ')[0] %}
              {% set summary = item.summary | regex_findall_index('(.*) affecting North East England: (.*) valid from (.*) to (.*)', ignorecase=True) %}
              {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
              {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
        | | | |
        | --- | --- | --- |
        | <font color = {%- if 'Yellow' == color %}'gold'
                        {%- elif 'Amber' == color %}'darkorange'
                        {%- else %}'firebrick'
                        {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | **{{ summary[0] | title }}**<br />{{ time_from }} - {{ time_to }}<br />{{ summary[1] }} |
            {% endfor %}
          {% endfor %}
        {% endif %}

Yes, it’s still working. But you need to insert code that covers the display of compound alerts like “snow, ice” and “rain, wind”. Try overwriting the {% for type, icon ... %} statement with this:

            {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('rain, wind', 'weather-pouring'), 
                                  ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('snow, ice', 'weather-snowy-heavy'),
                                  ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'),
                                  ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}

2 Likes

I’m not sure I understand your question.

I think I previously just posted my sensor here.
I then use that sensor in notifications.

Thanks! This is the piece I was missing for compound warnings.

Im having trouble getting this work - I get:

 Logger: homeassistant.helpers.template_entity
Source: helpers/template_entity.py:385
First occurred: 15:37:17 (8 occurrences)
Last logged: 15:53:39

    TemplateError('IndexError: list index out of range') while processing template 'Template("{% if state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') != None %} {% for item in state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') %} {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'), ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %} {% set color = item.summary.split(' ')[0] %} {% set summary = item.summary | regex_findall_index('(.*) affecting East Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %} {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% endfor %} {% endfor %} {% endif %}")' for attribute 'weather2' in entity 'sensor.template_sidebar'
    TemplateError('IndexError: list index out of range') while processing template 'Template("{% set entity_weather = 'sensor.met_office_rss_south_west_weather_warnings' %} {% if not is_state(entity_weather, 'unknown') %} {% for item in state_attr(entity_weather,'entries') %} {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'), ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %} {% set color = item.summary.split(' ')[0] %} {% set summary = item.summary | regex_findall_index('(.*) affecting East Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %} {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% endfor %} {% endfor %} {% endif %}")' for attribute 'weather2' in entity 'sensor.template_sidebar'
    TemplateError('IndexError: list index out of range') while processing template 'Template("{% set entity_weather = 'sensor.met_office_rss_south_west_weather_warnings' %} {% if not is_state(entity_weather, 'unknown') %} {% for item in state_attr(entity_weather,'entries') %} {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'), ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %} {% set color = item.summary.split(' ')[0] %} {% set summary = item.summary | regex_findall_index('(.*) affecting East Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %} {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% endfor %} {% endfor %} {% else %} Broken, very broken {% endif %}")' for attribute 'battery' in entity 'sensor.template_sidebar'
    TemplateError('UndefinedError: 'dict object' has no attribute 'description'') while processing template 'Template("{% if state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') != None %} {% for item in state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') %} {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'), ('fog', 'weather-fog')] if type == item.description[0].split(' ')[3]|trim(',') %} --- | | | | | --- | --- | --- | | <font color = {%- if 'Yellow' == item.description[0].split(' ')[0]|trim(',') %}'gold' {%- elif 'Amber' == item.description[0].split(' ')[0]|trim(',') %}'darkorange' {%- else %}'firebrick' {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | {{ item.description|trim("'[]'") }} | {% endfor %} {% endfor %} {% endif %}")' for attribute 'battery' in entity 'sensor.template_sidebar'
    TemplateError('IndexError: list index out of range') while processing template 'Template("{% if state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') != 0 %} {% for item in state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') %} {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'), ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'), ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %} {% set color = item.summary.split(' ')[0] %} {% set summary = item.summary | regex_findall_index('(.*) affecting West Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %} {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %} | | | | | --- | --- | --- | | <font color = {%- if 'Yellow' == color %}'gold' {%- elif 'Amber' == color %}'darkorange' {%- else %}'firebrick' {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | **{{ summary[0] | title }}**<br />{{ time_from }} - {{ time_to }}<br />{{ summary[1] }} | {% endfor %} {% endfor %} {% endif %}")' for attribute 'battery' in entity 'sensor.template_sidebar'

The code:

{% if state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') != 0 %}
            {% for item in state_attr('sensor.met_office_rss_south_west_weather_warnings','entries') %}
              {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'),
                                    ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), 
                                    ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'),
                                    ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}
                {% set color = item.summary.split(' ')[0] %}
                {% set summary = item.summary | regex_findall_index('(.*) affecting West Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %}
                {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
                {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
          | | | |
          | --- | --- | --- |
          | <font color = {%- if 'Yellow' == color %}'gold'
                          {%- elif 'Amber' == color %}'darkorange'
                          {%- else %}'firebrick'
                          {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | **{{ summary[0] | title }}**<br />{{ time_from }} - {{ time_to }}<br />{{ summary[1] }} |
              {% endfor %}
            {% endfor %}
          {% endif %}

Note the indendetation has gone all whack since pasting it in here.

Are you using weather alerts for the south west? Then you also need to change the line that refers to the West Midlands to match your region:

{% set summary = item.summary | regex_findall_index('(.*) affecting West Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %}

Oh yes I missed that. No errors now, but nothing it being output. Very strange. I don’t know how to debug from here on.

Are there alerts active in the south west currently? If it’s a compound alert e.g ‘rain, wind’ then you’ll need to amend the code according to this post

This is a really helpful thread, thanks everyone. I’ve created a sensor and card but can’t test it because there are no weather warnings at the moment (doh!), but there is one bit which definitely isn’t work. I’m trying to add an else clause to the first if, to display a default message when there are no warnings. But I can’t make it display, for some reason. Can anyone spot what I’m doing wrong? It’s the penultimate line below.

{% if state_attr('sensor.met_office_rss_east_midlands_weather_warnings','entries') != 0 %}
  {% for item in state_attr('sensor.met_office_rss_east_midlands_weather_warnings','entries') %}
    {% for type, icon in [('rain', 'weather-pouring'), ('thunderstorms', 'weather-lightning-rainy'),
                          ('wind', 'weather-windy'), ('snow', 'weather-snowy-heavy'), 
                          ('snow, ice', 'weather-snowy-heavy'),
                          ('lightning', 'weather-lightning'), ('ice', 'car-traction-control'),
                          ('fog', 'weather-fog'), ('extreme heat', 'weather-sunny-alert'), ('thunderstorm', 'weather-lightning')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}
      {% set color = item.summary.split(' ')[0] %}
      {% set summary = item.summary | regex_findall_index('(.*) affecting East Midlands: (.*) valid from (.*) to (.*)', ignorecase=True) %}
      {% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
      {% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom("%H:%M %d/%m") %}
      {% set link = item.link %}
| | | |
| --- | --- | --- |
| <font color = {%- if 'Yellow' == color %}'gold'
                {%- elif 'Amber' == color %}'darkorange'
                {%- else %}'firebrick'
                {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | **<a href="{{ link }}" target="_blank">{{ summary[0] | title }}</a>**<br />{{ time_from }} - {{ time_to }}<br />{{ summary[1] }} |
    {% endfor %}
  {% endfor %}
{% else %}
  No warnings at present
{% endif %}

Are you using the overall weather card and markdown card code as was posted here?

If so, the markdown card is set within a conditional card that only shows if the alert sensor is above 0. So your ‘no alert’ message would be working, but not showing because the conditional card is off.

Otherwise your code looks fine to me, so can’t see why it wouldn’t work.