Skip to content

Instantly share code, notes, and snippets.

@StephenBrown2
Last active July 4, 2026 17:25
Show Gist options
  • Select an option

  • Save StephenBrown2/7f32ab4780644f5cfd3ea5abf12ed4c9 to your computer and use it in GitHub Desktop.

Select an option

Save StephenBrown2/7f32ab4780644f5cfd3ea5abf12ed4c9 to your computer and use it in GitHub Desktop.
Rain & High Temp alert
blueprint:
name: Tomorrow's Rain & High Temp Forecast Alert
description: >
Notifies when the precipitation forecast for the next 24 hours changes.
Includes total expected rainfall, the high temperature, and when that
high is expected. Requires an input_text helper to track the last seen
forecast (create one first: Settings > Devices & Services > Helpers >
Text, min length 255).
domain: automation
input:
weather_entity:
name: Weather Entity
description: Your Pirate Weather entity
selector:
entity:
domain: weather
notify_service:
name: Notify Targets
description: One or more legacy notify services, e.g. notify.mobile_app_pixel_9
default: ["notify.mobile_app_pixel_9"]
selector:
text:
multiple: true
last_forecast_helper:
name: Last Forecast Helper
description: input_text helper used to detect forecast changes
selector:
entity:
domain: input_text
icon_sensor:
name: Icon Sensor
description: >
PirateWeather icon sensor for tomorrow, e.g. sensor.pirateweather_icon_0d
selector:
entity:
domain: sensor
check_interval:
name: Check Interval
description: >
Time pattern for how often to check. Use "/30" for every 30 minutes,
"/15" for every 15 minutes, etc.
default: "/30"
selector:
text:
icon_service_url:
name: Icon Service URL
description: >
Base URL of the svg-to-png addon (https://github.com/Netesfiu/hass-addons),
used to render a large icon in the notification. Leave blank to skip.
default: ""
selector:
text:
variables:
weather_entity: !input weather_entity
last_forecast_helper: !input last_forecast_helper
icon_sensor: !input icon_sensor
notify_service: !input notify_service
icon_service_url: !input icon_service_url
trigger:
- platform: time_pattern
minutes: !input check_interval
action:
- service: weather.get_forecasts
target:
entity_id: "{{ weather_entity }}"
data:
type: hourly
response_variable: hourly_forecast
- variables:
cutoff: "{{ (now() + timedelta(hours=24)).isoformat() }}"
upcoming: >
{{ hourly_forecast[weather_entity].forecast
| selectattr('datetime', 'lt', cutoff) | list }}
total_rain: >
{{ upcoming | map(attribute='precipitation') | select('number') | sum | round(2) }}
max_temp_entry: "{{ upcoming | sort(attribute='temperature', reverse=true) | first }}"
max_temp: "{{ max_temp_entry.temperature }}"
max_temp_time: "{{ as_timestamp(max_temp_entry.datetime) | timestamp_custom('%-I %p %a') }}"
max_apparent_entry: "{{ upcoming | sort(attribute='apparent_temperature', reverse=true) | first }}"
max_apparent: "{{ max_apparent_entry.apparent_temperature }}"
max_apparent_time: "{{ as_timestamp(max_apparent_entry.datetime) | timestamp_custom('%-I %p %a') }}"
max_prob_entry: "{{ upcoming | sort(attribute='precipitation_probability', reverse=true) | first }}"
max_prob: "{{ max_prob_entry.precipitation_probability | round | int }}"
max_prob_time: "{{ as_timestamp(max_prob_entry.datetime) | timestamp_custom('%-I %p %a') }}"
values: "{{ upcoming | map(attribute='precipitation') | select('number') | list }}"
sparkline: >
{% set blocks = '▁▂▃▄▅▆▇█' %}
{% set max_v = (values | max) or 1 %}
{%- for v in values -%}{{ blocks[(v / max_v * 7) | round | int] }}{%- endfor -%}
peak_times: >
{% set max_v = values | max %}
{% set ns = namespace(list=[]) %}
{% for i in range(values | length) %}
{% if max_v > 0 and values[i] >= max_v * 0.9 %}
{% set ns.list = ns.list + [values[i] | round(2) ~ 'in @ ' ~ (as_timestamp(upcoming[i].datetime) | timestamp_custom('%-I %p %a'))] %}
{% endif %}
{%- endfor %}
{{- ns.list[:2] | join(', ') }}
icon: >
{{ {
'clear-day': 'mdi:weather-sunny',
'clear-night': 'mdi:weather-night',
'rain': 'mdi:weather-rainy',
'snow': 'mdi:weather-snowy',
'sleet': 'mdi:weather-snowy-rainy',
'wind': 'mdi:weather-windy',
'fog': 'mdi:weather-fog',
'cloudy': 'mdi:weather-cloudy',
'partly-cloudy-day': 'mdi:weather-partly-cloudy',
'partly-cloudy-night': 'mdi:weather-night-partly-cloudy',
'thunderstorm': 'mdi:weather-lightning',
'hail': 'mdi:weather-hail'
}.get(states(icon_sensor), 'mdi:weather-cloudy') }}
signature: "{{ total_rain }}|{{ max_temp }}|{{ max_temp_time }}|{{ max_apparent }}|{{ max_prob }}|{{ max_prob_time }}|{{ peak_times }}"
last_signature: "{{ states(last_forecast_helper) }}"
- condition: template
value_template: "{{ signature != last_signature }}"
- service: input_text.set_value
target:
entity_id: "{{ last_forecast_helper }}"
data:
value: "{{ signature }}"
- repeat:
for_each: "{{ notify_service }}"
sequence:
- service: "{{ repeat.item }}"
data:
title: Forecast update
message: >
{{ total_rain }}in rain expected in the next 24h.<br/>
{{ sparkline }}<br/>
High of {{ max_temp }}° (feels like {{ max_apparent }}°) at {{ max_temp_time }}.<br/>
Peak {{ max_prob }}% chance of rain at {{ max_prob_time }}.
{% if peak_times %}<br/>Rain peaks {{ peak_times }}.{% endif %}
data:
notification_icon: "{{ icon }}"
icon_url: "{{ icon_service_url }}/mdi.png?icon={{ icon }}&size=96"
channel: Forecast Alerts
tag: rain_temp_forecast_update
mode: single
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment