Rain notification, Based on forecast

I recently made this.

template:
  - trigger:
      - platform: time_pattern
        # every 5 minutes past the hour
        hours: "*"
        minutes: "5"
      - platform: state
        entity_id: weather.openweathermap
    action:
      - service: weather.get_forecasts
        target:
          entity_id: weather.openweathermap
        data:
          type: hourly
        response_variable: hourly
    binary_sensor:
      - name: "Weather Forecast Precipitation Soon"
        unique_id: "949dd25e-35cf-4000-a3f9-f38ab20e112f"
        device_class: moisture
        state: >-
          {% set threshold = 5 %}
          {% set forecast = hourly['weather.openweathermap']['forecast'] %}
          {% set start = utcnow() %}
          {% set end = start + timedelta(hours=12) %}
          {% set precipitation_soon = forecast
             | selectattr('datetime', '>=', start.isoformat())
             | selectattr('datetime', '<=', end.isoformat())
             | map(attribute='precipitation')
             | map('int')
             | select('>=', threshold)
             | list
             | count > 0 %}
          {{ precipitation_soon }}

automation:
  - alias: "Notify When Significant Rain Is Expected"
    id: "aff421a7-d99a-45c2-baa5-710b11d010b9"
    initial_state: true
    variables:
      last_changed: "{{ states.binary_sensor.weather_forecast_precipitation_soon.last_changed }}"
    trigger:
      # id is the number of seconds from the previous time slot
      - platform: time
        at: "06:30:00"
        id: "41400"
      - platform: time
        at: "12:00:00"
        id: "19800"
      - platform: time
        at: "17:30:00"
        id: "19800"
      - platform: time
        at: "19:00:00"
        id: "5400"
    condition:
      - condition: state
        entity_id: binary_sensor.weather_forecast_precipitation_soon
        state: "on"
      # if the sensor changed to on during the last interval
      - condition: template
        value_template: >
          {{ (now() - last_changed | as_datetime).total_seconds() < trigger.id | int(0) }}
      - condition: state
        entity_id: binary_sensor.pieter_present
        state: "on"
    action:
      - service: weather.get_forecasts
        target:
          entity_id: weather.openweathermap
        data:
          type: hourly
        response_variable: hourly
      - service: notify.mobile_app_ceres
        data:
          title: "🌧️ Rain Expected"
          message: >-
            {% set forecast = hourly['weather.openweathermap']['forecast'] %}
            {# must match the sensor's definition #}
            {% set start = utcnow() + timedelta(hours=12) %}
            {% set end = start + timedelta(hours=36) %}
            {% set rain_window = forecast
               | selectattr('datetime', '>=', start.isoformat())
               | selectattr('datetime', '<', end.isoformat())
               | list %}
            {# find first rainy hour #}
            {% set first_rain = rain_window
               | selectattr('precipitation', '>', 0)
               | list
               | first %}
            {% if first_rain %}
              {% set first_rain_local_dt = first_rain.datetime | as_datetime | as_local %}
              {% set rain_time = first_rain_local_dt.strftime('%H:%M') %}
              {# later today → tonight → overnight → early morning → early tomorrow → later tomorrow #}
              {% if first_rain_local_dt.date() == now().date() %}
                {% set time_phrase = "later today" %}
              {% elif first_rain_local_dt.hour < 4 %}
                {% set time_phrase = "overnight" %}
              {% elif first_rain_local_dt.hour < 7 %}
                {% set time_phrase = "early morning" %}
              {% elif first_rain_local_dt.hour < 10 %}
                {% set time_phrase = "early tomorrow" %}
              {% elif first_rain_local_dt.hour < 18 %}
                {% set time_phrase = "later tomorrow" %}
              {% else %}
                {% set time_phrase = "tonight" %}
              {% endif %}
              Rain is expected {{ time_phrase }} around {{ rain_time }}. Plan accordingly.
            {% else %}
              Rain is expected, but timing is uncertain. Check the forecast and plan accordingly.
            {% endif %}
            Rain is expected {{ time_phrase }}. Plan accordingly.
          data:
            url: homeassistant://navigate/lovelace-main/environment
            group: "environment"
1 Like