Last active
July 4, 2026 17:25
-
-
Save StephenBrown2/7f32ab4780644f5cfd3ea5abf12ed4c9 to your computer and use it in GitHub Desktop.
Rain & High Temp alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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