How to send notifications for DWD weather warnings

Yeah, complete restart also Done.

Have you checked trace on that automation?


I found this, but I can’t really figure it out from the messages
for this I simply lack the experience regarding the understanding of what was programmed here. If you have time, maybe you can explain it to me.

You are getting error when evaluating input_number. Try to see what is the value of input_number in developer tool of HA.

Hi,
this is what I see. Actual there is no warning from DWD


Can you maybe help me further?

I’ve tried that and got a notification every 15 minutes - can some1 please share a working solution

This is my copy paste of entire code related to DWD weather warning. You can copy paste it, create your sensors in integration and adjust it to your needs. I use Android and receive notifications only when warning conditions are changed. I also added very nice card configuration for that.

It is all working very good, you just need to replace warnwetter_stadt_xxx_current_warning_level and warnwetter_stadt_xxx_advance_warning_level with your DWD sensors. I think that stadt_xxx can be ignored (deleted) it is some obsolete property.

Of course you should also change this part notify.mobile_app_alan_s22 defining your mobile device.
I also added click actions opening my dashboard with all weather information where my card is also located /lovelace/weather, you can adjust it or remove that part.

If you want to cover more cities, just add more triggers in automation, this part:

  - platform: state
    entity_id:
      - sensor.warnwetter_stadt_xxx_current_warning_level
      - sensor.warnwetter_stadt_xxx_advance_warning_level
    id: stadt_xxx

Compared to my previous posts, this code is refactored, tested and dynamic, covering multiple cities. If you want you can remove “advance warning” trigger, if you only want to monitor current weather.

If you restart HA or reboot the machine, warning notification will be repeated. That is because I replaced input_number with input_select and input_select cannot remember options that were added dynamically. I am using input_select to have everything stored in one place and it is now automation based not trigger based.

/homeassistant/configuration.yaml
input_select: !include input_selects.yaml

/homeassistant/input_selects.yaml

automation_notify_weather_warning_notification_state:
  options:
    - None

Automation

alias: "Notify: Weather warning"
description: >-
  Supporting multiple trigger entities. Helper input_select used.
trigger:
  - platform: state
    entity_id:
      - sensor.warnwetter_stadt_xxx_current_warning_level
      - sensor.warnwetter_stadt_xxx_advance_warning_level
    id: stadt_xxx
condition:
  - condition: template
    value_template: "{{ trigger.to_state.state != 'unavailable' }}"
action:
  - variables:
      change: 0
  - if:
      - condition: template
        alias: Anzahl Warnungen prĂŒfen
        value_template: "{{ trigger.to_state.attributes.warning_count|trim |int >= 1}}"
    then:
      - repeat:
          count: "{{ trigger.to_state.attributes.warning_count|trim |int }}"
          sequence:
            - if:
                - condition: template
                  alias: Warnung Ă€nderungen prĂŒfen
                  value_template: >-
                    {{ trigger.from_state.attributes["warning_" ~ repeat.index]
                    != trigger.to_state.attributes["warning_" ~ repeat.index] }}
              then:
                - variables:
                    change: 1
      - if:
          - condition: and
            conditions:
              - condition: template
                alias: Warnungen Anzahl Ă€nderung prĂŒfen
                value_template: >-
                  {{ trigger.to_state.attributes["warning_count"] ==
                  trigger.from_state.attributes["warning_count"] }}
              - condition: template
                value_template: "{{ change == 0 }}"
              - condition: template
                value_template: >-
                  {{
                  state_attr('input_select.automation_notify_weather_warning_notification_state',
                  'options') | select('eq', trigger.entity_id~'_sent') | list |
                  count == 1 }}
        then:
          - stop: No changes in warnings.
      - service: notify.mobile_app_alan_s22
        data:
          message: |-
            {% set count = state_attr(trigger.entity_id, 'warning_count') %}
            {% for i in range(count) %}
              {%- set description = state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_description') %}
              {%- set time_start = (state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_start')|as_timestamp(now()) )|timestamp_custom('%d.%m.%Y, %R', true, 'N/A') %}
              {%- set time_end = (state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_end')|as_timestamp(now()) )|timestamp_custom('%d.%m.%Y, %R', true, 'N/A') %}
              {%- set weekday_start = (state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_start')|as_timestamp(now().timestamp()) )|timestamp_custom('%w', true, now().weekday() )|int %}
              {%- set weekday_end = (state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_end')|as_timestamp(now().timestamp()) )|timestamp_custom('%w', true, now().weekday() )|int %}
              {%- set headline = state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_headline') %}
              {%- set level = state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_level') %}
              {%- set color = state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_color') %}
              <span style="color: {{ color }}">{{ headline|trim }} - Stufe {{ level }}</span>
              {{ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_start-1] ~ ', ' ~ time_start ~ ' - ' ~ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_end-1] ~ ', ' ~ time_end }} {{ description|trim }}
            {% endfor %}
          title: |-
            {% set count = state_attr(trigger.entity_id, 'warning_count') %}
            {% set region_name = state_attr(trigger.entity_id, 'region_name') %}
            DWD {{ region_name }} Wetterwarnung ({{ count }})
          data:
            subtitle: >-
              {%- set headline = state_attr(trigger.entity_id,
              'warning_1_headline') %} {%- set level =
              state_attr(trigger.entity_id, 'warning_1_level') %} {{
              headline|trim }} - Stufe {{ level }}
            subject: >-
              {%- set headline = state_attr(trigger.entity_id,
              'warning_1_headline') %} {%- set level =
              state_attr(trigger.entity_id, 'warning_1_level') %} {{
              headline|trim }} - Level {{ level }}
            url: /lovelace/weather
            clickAction: /lovelace/weather
            tag: weather_warnings_{{ trigger.entity_id }}
            group: >-
              Weather warnings {{ state_attr(trigger.entity_id,
              "region_name")|trim }}
            channel: Weather warning
            notification_icon: mdi:cloud-alert
            color: "{{ state_attr(trigger.entity_id, 'warning_1_color') }}"
            ttl: 0
            priority: high
            sticky: "true"
            persistent: true
            timeout: |-
              {%- set count = state_attr(trigger.entity_id, 'warning_count') %}
              {%- set max_time_end = 0 %}
              {%- set ns = namespace (max_time_end = 0) %} 
              {% for i in range(count) -%}
                {%- set time_end = state_attr(trigger.entity_id, 'warning_' ~ loop.index ~ '_end')|as_timestamp() %}
                {% if ns.max_time_end < time_end -%}
                  {%- set ns.max_time_end = time_end %}
                {%- endif %}
              {% endfor %}
              {{ (ns.max_time_end - as_timestamp(utcnow())) | int }}
      - service: input_select.set_options
        target:
          entity_id: input_select.automation_notify_weather_warning_notification_state
        data:
          options: >-
            {{
            state_attr('input_select.automation_notify_weather_warning_notification_state',
            'options') | reject('contains', trigger.entity_id) | list + 
            [trigger.entity_id~'_sent'] }}
    else:
      - if:
          - condition: template
            value_template: >-
              {{ trigger.to_state.attributes.warning_count !=
              trigger.from_state.attributes.warning_count }}
        then:
          - service: notify.mobile_app_alan_s22
            data:
              message: >-
                Die Wetterlage hat sich wieder normalisiert.
                {{trigger.to_state.attributes.warning_count}}
                {{trigger.from_state.attributes.warning_count}}
              title: >-
                DWD Entwarnung fĂŒr {{ state_attr(trigger.entity_id,
                "region_name")|trim }}
              data:
                url: /lovelace/weather
                clickAction: /lovelace/weather
                tag: weather_warnings_{{ trigger.entity_id }}
                group: >-
                  Weather warnings {{ state_attr(trigger.entity_id,
                  "region_name")|trim }}
                channel: Weather warning
                notification_icon: mdi:cloud-alert
                color: null
                ttl: 0
                priority: high
                timeout: 7200
            enabled: false
          - service: notify.mobile_app_alan_s22
            data:
              message: clear_notification
              data:
                tag: weather_warnings_{{ trigger.entity_id }}
            enabled: true
          - service: input_select.set_options
            target:
              entity_id: >-
                input_select.automation_notify_weather_warning_notification_state
            data:
              options: >-
                {{
                state_attr('input_select.automation_notify_weather_warning_notification_state',
                'options') | reject('contains', trigger.entity_id) | list }}
mode: queued
max: 10

Card for the dashboard

type: custom:vertical-stack-in-card
title: WarnWetter (DWD)
cards:
  - type: markdown
    title: null
    content: >-
      {# Beginn: Letzte Aktualisierung #}  

      {% set sensor_region_name ="warnwetter_stadt_xxx" %}

      {% set current_last_update = state_attr("sensor." ~ sensor_region_name ~
      "_current_warning_level", "last_update") %} {% set weekday_last_update =
      as_timestamp(current_last_update) | timestamp_custom("%w", True) | int %}
      Stand: {{
      ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_last_update-1]
      ~ ", " ~ as_timestamp(current_last_update) | timestamp_custom('%d.%m.%Y -
      %H:%M:%S') }}

      {# Ende: Letzte Aktualisierung #} 

      {# Beginn: 1. Region #}

      {% set sensor_region_name ="warnwetter_stadt_xxx" %}

      {% set current_region_name = state_attr("sensor." ~ sensor_region_name ~
      "_current_warning_level", "region_name") %} {% set current_count =
      state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level",
      "warning_count") %} {% set advance_count = state_attr("sensor." ~
      sensor_region_name ~ "_advance_warning_level", "warning_count") %} 

      ****{{ current_region_name }}****

      {% if ((current_count == 0 or current_count == None) and (advance_count ==
      0 or advance_count == None)) %} <font color=#cccccc>Keine
      Warnungen</font>{% else %}
        {% for i in range(current_count) %}
          {% set headline = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_headline") %}
          {% set description = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_description") %}
          {% set instruction = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_instruction") %}
          {% set level = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_level") %}
          {% set time_start = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_start") %}
          {% set weekday_start = as_timestamp(time_start) | timestamp_custom("%w", True) | int %}
          {% set time_end = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_end") %}
          {% set weekday_end = as_timestamp(time_end) | timestamp_custom("%w", True) | int %}
          {% set color = state_attr("sensor." ~ sensor_region_name ~ "_current_warning_level", "warning_" ~ loop.index ~ "_color") %}
        **<font color={{ color }}>{{ headline }} (Stufe {{ level }})</font>**     
        **{{ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_start-1] ~ ", " ~ as_timestamp(time_start) | timestamp_custom('%H:%M') ~ " Uhr - " ~ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_end-1] ~ ", " ~ as_timestamp(time_end) | timestamp_custom('%H:%M') ~ " Uhr" }}**
        *{{ description|trim }}*
        {% if (instruction|trim != "None") %}
        ****{{ instruction|trim }}****
        {% endif %}
        {% if not loop.last %}***{% endif %}
        {% endfor %}
        {% if ((current_count != 0) and (advance_count != 0)) %}***{% endif %}
        {% for i in range(advance_count) %}
          {% set headline = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_headline") %}
          {% set description = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_description") %}
          {% set instruction = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_instruction") %}
          {% set level = state_attr("sensor.sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_level") %}
          {% set time_start = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_start") %}
          {% set weekday_start = as_timestamp(time_start) | timestamp_custom("%w", True) | int %}
          {% set time_end = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_end") %}
          {% set weekday_end = as_timestamp(time_end) | timestamp_custom("%w", True) | int %}
          {% set color = state_attr("sensor." ~ sensor_region_name ~ "_advance_warning_level", "warning_" ~ loop.index ~ "_color") %}
        **<font color={{ color }}>{{ headline }}</font>**
        **{{ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_start-1] ~ ", " ~ as_timestamp(time_start) | timestamp_custom('%H:%M') ~ " Uhr - " ~ ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'][weekday_end-1] ~ ", " ~ as_timestamp(time_end) | timestamp_custom('%H:%M') ~ " Uhr" }}**
        *{{ description|trim }}*
        {% if (instruction|trim != "None") %}
        ****{{ instruction|trim }}****
        {% endif %}
        {% if not loop.last %}***{% endif %}
        {% endfor %}
      {% endif %}   

      {# Ende: 1. Region #}

Thank you @alanmilinovic . I am trying to find a solution cause my entitiy names are these

  • sensor.dwd_weather_warnings_[IDNUMBER]aktuelle_warnstufe
    -sensor.dwd_weather_warnings
    [IDNUMBER]_vorwarnstufe

so i changed your stuff. lovelace is working.
is your notification only working for companion app?

Welcome.

You can replace my entity names with your names and it should work. Only trigger part of automation is place where change is needed.

Yes I am using notifications from companion apps. Should also work for iPhone, but I never tested it.
More info here: Introduction | Home Assistant Companion Docs

I also found a solution - it’s not the easiest one for sure, but it works and double notifications for one specific topic are very rare. What it basically does is building a “unique ID” based on several information from the warning and checks if something has changed.
The message also shows in which timespan the warning is issued. One example would be:

Von 18:00 Uhr bis morgen 10 Uhr: Es tritt Frost auf ...

In the following code, you just need to adjust the entities in the trigger section (and maybe also the texts from German to English):

# ------------------------------------------------------------
# |                                                          |
# | Sends notifications for DWD weather warnings.            |
# |                                                          |
# ------------------------------------------------------------
- alias: Benachrichtigung bei DWD-Wetterwarnungen
  id: notification_dwd_weather_warnings
  description: Sendet Benachrichtigungen fĂŒr DWD-Wetterwarnungen
  mode: single

  trigger:
    - platform: state
      entity_id: 
        - sensor.dwd_city_current_warning_level
        - sensor.dwd_city_advance_warning_level
      for:
        hours: 0
        minutes: 1
        seconds: 0
      alias: Auslösen, wenn sich das DWD-Warnlevel fĂŒr City Ă€ndert

  condition:
    - condition: state
      entity_id: input_boolean.disable_notification_automation
      state: "off"
      alias: Nicht ausfĂŒhren, wenn Benachrichtigungen deaktiviert wurden

    - condition: state
      entity_id: input_boolean.disable_warning_automations
      state: "off"
      alias: Nicht ausfĂŒhren, wenn Warnungen deaktiviert wurden

    - condition: template
      value_template: >-
        {%- set ns = namespace(warnings = [], new_warnings = 0) -%}
        {%- set old_warning_count = trigger.from_state.attributes['warning_count'] -%}
        {%- for i in range(old_warning_count) -%}
          {%- set warning_index = i + 1 -%}
          {%- set old_warning_id = trigger.from_state.attributes['region_id'] | string -%}
          {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_type'] | string -%}
          {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_level'] | string -%}
          {%- if trigger.from_state.attributes['warning_' + warning_index | string + '_instruction'] -%}
            {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_instruction'] | trim | length | string -%}
          {%- else -%}
            {%- set old_warning_id = old_warning_id + '-0' -%}
          {%- endif -%}
          {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_start'] | string -%}
          {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_end'] | string -%}
          {%- set ns.warnings = ns.warnings + [ old_warning_id ] -%}
        {%- endfor -%}
        {%- set new_warning_count = trigger.to_state.attributes['warning_count'] -%}
        {%- set new_warnings = 0 -%}
        {%- for i in range(new_warning_count) -%}
          {%- set warning_index = i + 1 -%}
          {%- set new_warning_id = trigger.to_state.attributes['region_id'] | string -%}
          {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + warning_index | string + '_type'] | string -%}
          {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + warning_index | string + '_level'] | string -%}
          {%- if trigger.to_state.attributes['warning_' + warning_index | string + '_instruction'] -%}
            {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + warning_index | string + '_instruction'] | trim | length | string -%}
          {%- else -%}
            {%- set new_warning_id = new_warning_id + '-0' -%}
          {%- endif -%}
          {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + warning_index | string + '_start'] | string -%}
          {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + warning_index | string + '_end'] | string -%}
          {%- if not new_warning_id in ns.warnings -%}
            {%- set ns.new_warnings = ns.new_warnings + 1 -%}
          {%- endif -%}
        {%- endfor -%}
        {{- ns.new_warnings >= 1 -}}
      alias: Nicht ausfĂŒhren, wenn es keine Änderungen gab

  action:
    - repeat: 
        count: '{{ state_attr(trigger.entity_id, "warning_count") | trim | int }}'
        sequence:
          - if:
            - condition: template
              value_template: >-
                {%- set ns = namespace(warnings = []) -%}
                {%- set old_warning_count = trigger.from_state.attributes['warning_count'] -%}
                {%- for i in range(old_warning_count) -%}
                  {%- set warning_index = i + 1 -%}
                  {%- set old_warning_id = trigger.from_state.attributes['region_id'] | string -%}
                  {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_type'] | string -%}
                  {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_level'] | string -%}
                  {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_instruction'] | trim | length | string -%}
                  {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_start'] | string -%}
                  {%- set old_warning_id = old_warning_id + '-' + trigger.from_state.attributes['warning_' + warning_index | string + '_end'] | string -%}
                  {%- set ns.warnings = ns.warnings + [ old_warning_id ] -%}
                {%- endfor -%}
                {%- set new_warning_id = trigger.to_state.attributes['region_id'] | string -%}
                {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + repeat.index | string + '_type'] | string -%}
                {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + repeat.index | string + '_level'] | string -%}
                {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + repeat.index | string + '_instruction'] | trim | length | string -%}
                {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + repeat.index | string + '_start'] | string -%}
                {%- set new_warning_id = new_warning_id + '-' + trigger.to_state.attributes['warning_' + repeat.index | string + '_end'] | string -%}
                {{ not new_warning_id in ns.warnings }}
              alias: PrĂŒfen, ob sich Warnung verĂ€ndert hat

            then:
              - service: notify.mobile_app_dominiks_iphone
                data:
                  message: >-
                    {%- set warning_timespan = '' %}
                    {%- set warning_start = trigger.to_state.attributes['warning_' + repeat.index | string + '_start'] | as_local %}
                    {%- set warning_start_day = warning_start.strftime('%Y%m%d') | int %}
                    {%- set warning_end = trigger.to_state.attributes['warning_' + repeat.index | string + '_end'] | as_local %}
                    {%- set warning_end_day = warning_end.strftime('%Y%m%d') | int %}
                    {%- set current_day = now().strftime('%Y%m%d') | int %}
                    {%- if warning_start > now() %}
                      {%- if (warning_start_day - current_day) == 0 %}
                        {%- set warning_timespan = 'Von ' %}
                      {%- elif (warning_start_day - current_day) == 1 %}
                        {%- set warning_timespan = 'Von morgen ' %}
                      {%- elif (warning_start_day - current_day) == 2 %}
                        {%- set warning_timespan = 'Von ĂŒbermorgen ' %}
                      {%- elif (warning_start_day - current_day) >= 3 %}
                        {%- set warning_timespan = 'Von ' + warning_start.strftime('%d.%m.%Y') + ' ' %}
                      {%- endif %}
                      {%- set warning_timespan = warning_timespan + warning_start.strftime('%H:%M') + ' Uhr bis ' %}
                    {%- else %}
                      {%- set warning_timespan = 'Bis ' %}
                    {%- endif %}
                    {%- if (warning_end_day - current_day) == 1 %}
                      {%- set warning_timespan = warning_timespan + 'morgen ' %}
                    {%- elif (warning_end_day - current_day) == 2 %}
                      {%- set warning_timespan = warning_timespan + 'ĂŒbermorgen ' %}
                    {%- elif (warning_end_day - current_day) >= 3 %}
                      {%- set warning_timespan = warning_timespan + warning_end.strftime('%d.%m.%Y') + ' ' %}
                    {%- endif %}
                    {%- set warning_timespan = warning_timespan + warning_end.strftime('%H:%M') + ' Uhr: ' %}
                    {{ warning_timespan }}
                    {{ trigger.to_state.attributes['warning_' + repeat.index | string + '_description'] | string }}
                    {%- if trigger.to_state.attributes['warning_' + repeat.index | string + '_instruction'] %}
                    {{ trigger.to_state.attributes['warning_' + repeat.index | string + '_instruction'] | string }}
                    {%- endif %}
                  title: "{{ trigger.to_state.attributes['warning_' + repeat.index | string + '_headline'] | string }}"
                  data:
                    group: dwd_weather_warnings
                alias: Dominiks App ĂŒber die Wetterwarnung benachrichtigen

Maybe this also helps you :slight_smile:

best regards,
Dominik

@dominik4545 your solution looks also as good as @alanmilinovic .
Difficult to decide

Mine is better. :grinning:

1 Like