UK MET Office Severe Weather Warnings

In last year’s bad weather I cobbled together a markdown card to show severe weather warnings from the UK Met Office. But I’m redoing my lovelace interface now and have taken the time to tidy it up. Posting in case it helps give anyone ideas. The icons change type and colour according to the type and severity of the warning(s).

(it’s just test data currently)

The top section is this custom card https://github.com/Yevgenium/lovelace-weather-card-chart. The bottom is a markdown card both are wrapped in a stack-in-card https://github.com/custom-cards/stack-in-card.

I use a simple flow in node-red to grab the RSS feed with any items, convert to JSON and write it to an attribute in a sensor. Then I parse it into a table in the markdown card. I’ve also styles the weather card a bit to make them work better together.

Node-red config

[{"id":"32ad5b17.730c84","type":"xml","z":"df31568f.39e0d8","name":"","property":"payload","attr":"","chr":"","x":610,"y":580,"wires":[["cfaf461c.029f98"]]},{"id":"96430af9.396928","type":"http request","z":"df31568f.39e0d8","name":"get warnings","method":"GET","ret":"txt","paytoqs":false,"url":"http://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/yh","tls":"","persist":false,"proxy":"","authType":"","x":410,"y":580,"wires":[["32ad5b17.730c84"]]},{"id":"fda8626.3c450a","type":"inject","z":"df31568f.39e0d8","name":"","topic":"","payload":"","payloadType":"date","repeat":"3600","crontab":"","once":true,"onceDelay":0.1,"x":210,"y":580,"wires":[["96430af9.396928"]]},{"id":"cfaf461c.029f98","type":"ha-entity","z":"df31568f.39e0d8","name":"weather_warnings","server":"cc436e5e.bbf7e","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"weather_warnings"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"","stateType":"date","attributes":[{"property":"items","value":"payload.rss.channel[0].item","valueType":"msg"}],"resend":true,"outputLocation":"","outputLocationType":"none","x":870,"y":580,"wires":[[]]},{"id":"cc436e5e.bbf7e","type":"server","z":"","name":"Home Assistant","legacy":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":false}]

Lovelace config:

type: custom:stack-in-card
cards:

  - type: custom:weather-card-chart
    title: Weather
    weather: weather.openweathermap
    style: |
      ha-card {
        --iron-icon-width: 35px;
        --iron-icon-height: 35px;
      }

      .attributes div {
        text-align: left;
      }

      .main {
        font-size: 20pt;
      }

      .main sup {
        font-size: 12pt;
      }

      .main ha-icon {
        --iron-icon-width: 55px;
        --iron-icon-height: 55px;
      }

  - type: markdown
    style: |
      ha-card {
        --iron-icon-width: 50px;
        --iron-icon-height: 50px;
      }
    content: |
      {% if state_attr('sensor.weather_warnings','items') != None %}
        {% for item in state_attr('sensor.weather_warnings','items') %}
          {% for type, icon in [('RAIN', 'weather-pouring'), ('THUNDERSTORMS', 'weather-lightning-rainy'),
                                ('WIND', 'weather-windy'), ('SNOW', 'weather-snowy-heavy'), 
                                ('LIGHTNING', 'weather-lightning'), ('ICE', 'snowflake-alert'),
                                ('FOG', 'weather-fog')] if type == item['metadata:warningType']|trim("[]'") %}
      ---

      | | | |
      | --- | --- | --- |
      | <font color = {%- if 'Yellow' in item.description|trim("'[]'") %}'gold'
                      {%- elif 'Amber' in item.description|trim("'[]'") %}'darkorange'
                      {%- else %}'firebrick'
                      {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | {{ item.description|trim("'[]'") }}  |
 
          {% endfor %}
        {% endfor %}
      {% endif %}

Hopefully, this will be of some use to people when the winter weather comes back.

1 Like

Nice.
I have something similar but nowhere near as nice as yours. I don’t use NodeRed but the markdown card looks very nice. (As does the weather card)

Thanks.

How do you get the RSS feed? Or do you get the data a different way? I went straight to Node-red as I’m familiar with it. I’d be interested in updating this to work purely in home assistant.

I use a Feedparser sensor by @iantrich:

There is a core RSS Reader but I didn’t discover it until after I’d started using Feedparser. I keep meaning to see if I could substitute it in as it always seems to make sense to me to keep to as few custom components as possible.

But you know what it’s like when something works…

Anyway, here is my config.

  - platform: feedparser
    name: Met Office RSS Feed South East Weather Warnings
    feed_url: 'http://metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/se'
    date_format: '%a, %b %d %I:%M %p'

Which I then template out a count just for my area within the region:

  - platform: template
    sensors:
      #==========================================================
      #=== Number of weather warnings affecting 'MY AREA'
      #==========================================================
      met_office_london_weather_warnings:
        entity_id: sensor.met_office_rss_feed_south_east_weather_warnings
        value_template: >
          {% set ns = namespace(warning_count = 0) %}
          {% for entries in state_attr('sensor.met_office_rss_feed_south_east_weather_warnings', 'entries') %}
            {% if 'MY AREA' in states.sensor.met_office_rss_feed_south_east_weather_warnings.attributes.entries[loop.index - 1].summary %}
              {% set ns.warning_count = ns.warning_count + 1 %}
            {% endif %}
          {% endfor %}

          {{ ns.warning_count }}

I then have an overcomplicated automation triggered by a state change to the sensor that converts the warnings to natural language for use in my morning announcement. And a markdown card, but it is nothing like as pretty as yours.

Yet :wink:

1 Like

I did look at the core RSS integration, but it seems (I may be wrong) that it only generates events and doesn’t populate a sensor. I’m not sure whether it’s possible to create and populate sensors from automations triggered by the events and it sounds like it could get complicated.

I’ll take a look at Feedparser though, that looks interesting, thanks for the info.

Hi,
Did you had the chance to update the Lovelace Config? I’m curious about it! :slight_smile:
Cheers

not sure what you mean.

they have recently changed their format, I now use this:

- type: markdown
    style: "ha-card { --mdc-icon-size: 60px; }"
    content: |
      {% if state_attr('sensor.weather_warnings','items') != None %}
        {% for item in state_attr('sensor.weather_warnings','items') %}
          {% 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 %}
1 Like

Thanks! It helped me a lot to improve my code! great stuff :slight_smile:

Sorry, not been around for a while. They changed the format a few weeks back, my code now looks very similar to what you’ve posted. I’m sure it will help others, thanks.

I have started a new thread around the new(-ish) Met Office DataHub but maybe someone here has already got the necessary to help me with this.
How do I get the JSON from my python calls into Homeassistant and one of your lovely cards?
Thanks

for any one interested. I’ve got this working with feedparser rather than nodered. Massive props to @eggman as I wouldn’t have been able to do this with their work.

image

- platform: feedparser
  name: Weather Alerts
  feed_url: "https://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/wm"
  date_format: "%a, %b %d %I:%M %p"

lovelace card

type: 'custom:stack-in-card'
cards:
  - type: weather-forecast
    entity: weather.openweathermap
  - type: markdown
    style: |
      ha-card {
          --iron-icon-width: 50px;
          --iron-icon-height: 50px;
        }
    content: >
      {% if state_attr('sensor.weather_alerts','entries') != 0 %}
        {% for item in state_attr('sensor.weather_alerts','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.summary.split(' ')[3]|trim(',') %}
      ---

      | | | |

      | --- | --- | --- |

      | <font color = {%- if 'Yellow' == item.summary.split(' ')[0]|trim(',')
      %}'gold'
                      {%- elif 'Amber' == item.summary.split(' ')[0]|trim(',') %}'darkorange'
                      {%- else %}'firebrick'
                      {%- endif %}><ha-icon icon={{ "'mdi:" + icon + "'" }}></ha-icon></font> | | {{ item.summary|trim("'[]'") }}  |
          {% endfor %}
        {% endfor %}
      {% endif %}

1 Like

I’ve made some improvements to my feedparser version previously posted. This now supports “extream heat” and “thunderstorm” alerts. I’ve also reworked the summary text into something which I can layout a little better. Date time formats can be changed to your liking simply by updating the format codes.

You will also need to update the region in the regex to match your region. I strip it out because I know my region and only interested in the actual places affected.

Sensor

- platform: feedparser
  name: Weather Alerts
  feed_url: "https://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/wm"
  date_format: "%a, %b %d %I:%M %p"

Lovelace Card - needs card_mod

type: custom:stack-in-card
cards:
  - type: weather-forecast
    entity: weather.openweathermap
  - type: conditional
    conditions:
      - entity: sensor.weather_alerts
        state_not: '0'
    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_alerts','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 %}

Hope someone finds this useful

2 Likes

Thank you for this! exactly what I have been looking for

1 Like

You are most welcome. Credit to the OP for coming up with the idea in the first place.

1 Like