Home Assistant Blueprint

Weather — Forecast TTS (AI Optional)

TV-style forecasts by schedule, sensor, webhook, or voice. Uses daily + hourly data, calls out the first likely precip window with time and %, optional AI rephrase that preserves facts.

Overview

Fetches daily + hourly forecasts, crafts a concise message, optional AI rephrase that preserves facts, then speaks on selected speakers with a pre-roll delay.
Precipitation callouts require hourly precipitation_probability. If missing, the precip line is skipped by design.

Requirements

  • weather entity supporting weather.get_forecasts (daily + hourly).
  • tts engine and at least one media_player.
  • Optional: an ai_task entity for rephrasing; Conversation integration for voice.

Inputs overview

GroupKey(s)Description
Weatherweather_entitySource of current, daily, hourly.
TTStts_engine, speakers, voice, volume_level, preroll_msEngine, targets, voice, volume, wake-up delay.
AIai_task_entity, use_ai_rewrite, ai_rewrite_promptOptional AI pass with strict no-fact-change rules.
Timeenable_time_based, hour_pattern, minute_offset, start_time, end_time, days_of_weekSchedule and windowing.
Sensorenable_sensor_triggered, presence_sensorsAnnounce when sensors turn on.
Webhookenable_alarm_announce, webhook_id, personal_name, alarm_volume_levelOn-demand personal report.
Changeenable_current_change_announce, current_change_volume_level, enable_upcoming_change_announce, upcoming_change_volume_level, minutes_before_announceReal-time and impending alerts.
Precipprecip_threshold, hours_aheadThreshold and search window.
Voiceenable_voice_satellite, conversation_commandConversation trigger phrases.

Automation Editor Mock

Automation from blueprint: Weather — Forecast TTS
Mode: queued Max: 4
Time patternid: time_based
Hours: !input hour_pattern • Minutes: !input minute_offset
Runs only between !input start_time!input end_time on chosen !input days_of_week when enabled.
State (presence sensors)id: sensor_trigger
Entity: !input presence_sensorson
Great for “arrive home and speak forecast.”
State (weather entity change)id: current_change
Entity: !input weather_entity
Speaks when condition changes, e.g., “It’s now 45° and cloudy.”
Time pattern (upcoming change poll)id: upcoming_change
Minutes: /5
Find next precip start within !input minutes_before_announce if not precipitating now.
Webhookid: alarm_webhook
URL: http://homeassistant.local:8123/api/webhook/<!input webhook_id> • Methods: POST, PUT, GET, HEAD • Local only
Conversationid: voice_satellite
Commands: lines in !input conversation_command
Master OR across scenarios
  • Time-based: between !input start_time!input end_time, !input enable_time_based true, and day ∈ !input days_of_week.
  • Sensor-triggered: !input enable_sensor_triggered true.
  • Current change: !input enable_current_change_announce true.
  • Upcoming change: !input enable_upcoming_change_announce true.
  • Alarm webhook: !input enable_alarm_announce true.
  • Voice satellite: !input enable_voice_satellite true.

If any branch is true, its Actions sequence runs.

Time-based / Sensor-triggered
  1. Call weather.get_forecasts daily → d; hourly → h.
  2. Compose message with greeting, “Right now,” “Today,” and first precip window within !input hours_ahead if ≥ !input precip_threshold.
  3. Optional AI pass via ai_task.generate_data when !input use_ai_rewrite and !input ai_task_entity set.
  4. media_player.volume_set to !input volume_level.
  5. For each !input speakers: delay !input preroll_ms ms, then tts.speak with options.voice = !input voice.
Current change
  1. On weather state change → msg “It’s now <temp>° and <cond>.”
  2. Optional AI pass; set volume to !input current_change_volume_level; per-speaker delay + speak.
Upcoming change
  1. Hourly fetch → find next precip start in ≤ !input minutes_before_announce if not precipitating now.
  2. Msg “<rain/snow> in about <minutes> minutes.” → set volume to !input upcoming_change_volume_level → per-speaker delay + speak.
Alarm webhook
  1. Daily + hourly fetch → personalized greeting with !input personal_name.
  2. Optional AI pass; set volume to !input alarm_volume_level; per-speaker delay + speak.
Variables & example values
VariableSourceMeaningExample
key!input weather_entityPrimary weather entity idweather.openweathermap
d, hweather.get_forecastsDaily/hourly service responses{ forecast: [...] }
now_hournow().hourCurrent hour 0-238
day_nametimestamp_custom('%A')Day of weekSaturday
greetingtemplated from now_hourMorning/Afternoon/EveningGood morning
now_tempstate_attr(key,'temperature')Current temp57
now_humstate_attr(key,'humidity')Relative humidity %62
now_cond_hstates(key) normalizedReadable conditionpartly cloudy
daily_listd[key].forecastArray of daily periods[{ temperature: 63, templow: 49, ... }]
todaydaily_list[0]Today’s daily item{ temperature: 63, templow: 49, condition:'partlycloudy' }
hightoday.temperatureHigh °63
lowtoday.templow/temperature_lowLow °49
hourly_listh[key].forecastArray of next hours[{ datetime:'2025-11-08T09:00:00+00:00', precipitation_probability:40, condition:'rain', ... }]
next_hoursslice of hourly_listHours within !input hours_aheadfirst 24 items
hitsfilter on precipitation_probability ≥ !input precip_thresholdCandidate precip hours[{..40% rain..}, …]
first_hithits[0]Earliest candidate{ datetime:'…09:00…', precipitation_probability:40 }
hit_ppfirst_hit.precipitation_probabilityPrecip %40
hit_clockformat of first_hit.datetime12-hour time9 AM
hit_daypartby hour numberthis morning/afternoon/evening/overnightthis morning
precip_kindcontains “snow/sleet/hail/rain”Human termrain
msgassembled textFinal base stringGood morning! Saturday's forecast. Right now…
spokenAI or baseText actually spokenGood morning! Saturday’s forecast… 40% rain this morning around 9 AM.

Examples assume: clear morning, first precip at 9 AM with 40%.

Logic details

Message assembly

  1. Greeting + day: based on now().hour and timestamp_custom('%A').
  2. Right now: condition → temperature → humidity if present.
  3. Today: “Expect <today_cond_h>” when today’s condition differs from “Right now,” then “High … Low …”.
  4. Precip window: scan hourly_list[:!input hours_ahead]; first hour with precipitation_probability ≥ !input precip_threshold becomes the callout, including daypart and hit_clock.

Upcoming change alert

  • Every 5 minutes: find next hour after now(). If it is precip and current is not precip, and minutes-to-start ≤ !input minutes_before_announce, speak a short alert.

AI rewrite

  • Optional. Only changes wording. Facts, numbers, and order must remain identical; prompt enforces it.
  • If AI is unavailable, the base msg is used.

Webhook alarm: Android & iOS

Canonical URL format

http://homeassistant.local:8123/api/webhook/<WEBHOOK_ID_FROM_INPUT>

Android (Shortcuts / Automate)

  1. Create a shortcut named Weather Alarm.
  2. Add HTTP POST.
  3. URL: the webhook above using your webhook_id.
  4. Headers: none on LAN. For remote, use your external URL.
  5. Body: empty.
  6. Run to trigger the “Alarm webhook” branch.

iOS (Shortcuts)

  1. Shortcuts → “+” → Add Action → “Get Contents of URL”.
  2. Method: POST.
  3. URL: http://homeassistant.local:8123/api/webhook/<ID>
  4. Request Body: None.
  5. Optional: Add “Set Volume” first.
  6. Run to test.

Troubleshooting

  • No audio: Ensure speakers includes at least one media_player. Increase preroll_ms if audio starts late.
  • No precip line: Your hourly data may lack precipitation_probability. This is expected; the line is omitted.
  • Voice not responding: Conversation integration must be enabled. Ensure phrases match lines in conversation_command.
  • AI task fails: Disable use_ai_rewrite to confirm base messaging, then validate the ai_task entity.

FAQ

How do I schedule every 3 hours at minute 3?
Set hour_pattern to /3 and minute_offset to 3.
How do I change the voice?
Set voice to a valid voice for your TTS engine, e.g., en_US-carlin-high.
What’s the correct webhook URL?
Use http://homeassistant.local:8123/api/webhook/<WEBHOOK_ID_FROM_INPUT>. Replace the placeholder with your blueprint input.

Repo layout

  • /weather-forecast.yaml — Production blueprint
  • /backup/ — Snapshots
  • /development/ — Drafts
  • /docs/index.html — This page