When the National Weather Service issues a tornado watch for your area, Selora AI gives the household a calm heads-up. When a warning is issued, it sounds the indoor siren and tells everyone which room to move to.
How it works
Selora AI subscribes to the NWS feed for your county and watches for tornado watch and warning codes specifically. Other weather sources roll severe weather alerts together, which makes it hard to act on tornadoes in particular.
A watch is the quiet tier: an announcement on every speaker you picked, plus a push notification, and no siren. A warning is the loud one: the indoor siren turns on, the shelter zone you configured is announced on every speaker, and the same instruction goes to your phone so anyone out of earshot still gets it. You choose the tone of the spoken warning, from calm through terse, when you install the recipe.
Files Selora AI's pipeline reads to install this recipe. The manifest declares roles, inputs, and integrations; the package files are Jinja-templated YAML applied to Home Assistant.
# Tornado Alert — NWS-driven severe weather response recipe.
#
# Subscribes to the US National Weather Service feed for the
# homeowner's METAR station. On a tornado WATCH, sends a calm
# heads-up TTS to every media player. On a tornado WARNING, fires
# the indoor siren and announces the shelter zone on every speaker.
# Both tiers mirror to a push notification.
#
# NOT room-targeted: ``presence_sensors`` and ``door_sensors`` are
# collected below but no package template reads them, so the siren
# fires unconditionally and open doors are never called out. They
# have never been wired in any released version. Either implement
# them or drop the two roles, and keep the copy here honest until
# one of those happens.
#
# Demonstrates the wizard's inline-config-flow path: ``integrations``
# lists ``nws``, and the Match step opens HA's NWS config flow
# directly inside the wizard so the homeowner never has to leave
# the page to wire up the integration.
slug: tornado-alert-pack
version: 1.1.0
title: Tornado Alert Pack
tagline: When the NWS issues a tornado warning, sound the indoor siren and guide everyone to the shelter zone.
description: >-
Watches the US National Weather Service feed for tornado watches
and warnings. On a watch, every media player gets a calm heads-up
and a push notification, and the siren stays silent. On a warning,
the indoor siren fires and a TTS announcement directs the
household to the configured shelter zone, on every speaker and on
their phones. Requires the NWS integration (US-only) — the wizard
walks you through configuring it.
author: Selora AI
released: "2026-05-28"
tags: [safety, weather, alerts]
roles:
# Indoor siren — uses HA's dedicated ``siren`` domain so the
# wizard's candidate list won't surface every switch in the home
# (AC outlets, decorative-light plugs, etc.) as a "siren". Modern
# Z-Wave / zigbee siren integrations register their entity under
# the ``siren.*`` namespace; older devices that report as switches
# will need a manifest update or a homeowner-side template rename.
- id: indoor_siren
title: Indoor siren
kind: siren
min_count: 1
max_count: 1
selection: required
description: >-
Siren entity that fires on a tornado warning. Modern Z-Wave
and zigbee sirens register under the ``siren.*`` namespace in
Home Assistant.
# Occupancy sensors — RESERVED, not yet used. Intended to gate the
# siren to occupied rooms, but no package template reads this role
# and ``indoor_siren`` is capped at one entity, so per-room
# targeting isn't expressible as the roles stand today. Kept so
# existing installs keep their selection; do not describe it to
# homeowners as working until a template consumes it.
- id: presence_sensors
title: Presence / occupancy sensors
kind: binary_sensor
device_class: occupancy
min_count: 0
selection: required
description: >-
Reserved for a planned room-aware release. The current version
does not read these sensors: the siren fires whenever a warning
is issued, whether or not a room is occupied.
# Exterior door sensors — RESERVED, not yet used. Intended to name
# any door still open when a warning fires, but no package template
# reads this role. Same call as presence_sensors above: implement
# it or drop it, and don't advertise it meanwhile.
- id: door_sensors
title: Exterior door sensors
kind: binary_sensor
device_class: door
min_count: 0
selection: required
description: >-
Reserved for a planned release. The current version does not
read these sensors, and the warning announcement does not call
out open doors.
# Where the TTS announcements play. Multi-select so the homeowner
# can fan out across every speaker (a tornado warning isn't
# something you want a single bedroom Echo to handle).
- id: announce_media_players
title: Announcement speakers
kind: media_player
min_count: 1
selection: required
description: >-
Speakers that the TTS watch / warning announcements play on.
Pick every media player you want included — typically every
whole-home speaker in the household.
inputs:
# METAR station identifier (e.g. KOKC). Auto-resolved by the
# ``nws_station_from_location`` resolver from the home's lat/lon
# in HA config — the wizard never shows this field; the homeowner
# doesn't have to look anything up. If the resolver fails
# (location not set, NWS doesn't cover the home, network down)
# the pipeline halts at the validate stage with a punch list
# entry the homeowner can act on.
- id: station_code
type: string
label: NWS station code
description: >-
4-letter METAR identifier for the nearest NWS station. Resolved
automatically from your Home Assistant location via api.weather.gov.
resolver: nws_station_from_location
default: ""
- id: shelter_zone
type: string
label: Shelter location
description: >-
Name of the shelter zone, spoken in announcements. Usually a
windowless interior room — basement, interior bathroom, or
central hallway.
default: "the basement"
- id: warning_message
type: select
label: Warning announcement tone
description: How the warning TTS reads — calm, urgent, or terse.
default: "urgent"
choices:
- "calm"
- "urgent"
- "terse"
# TTS engine entity for the spoken announcements. Auto-resolved by the
# ``tts_engine`` resolver from the home's configured tts.* entities
# (picking whichever TTS engine the home has configured) — the wizard never shows this field. Recipes used to call
# ``tts.cloud_say`` directly, which only exists with a paid Home Assistant
# Cloud subscription, so the announcement silently did nothing on every
# other home. ``tts.speak`` + the resolved engine works everywhere. The
# resolver returns an empty string when the home has no TTS engine at all;
# the templates guard on it and simply skip the announcement (the siren and
# push notification still install). The default below is only used by the
# offline recipe-validation gate, which has no resolver to run; at install
# the resolver always overwrites it.
- id: tts_engine
type: string
label: Text-to-Speech engine
description: >-
Speech engine entity used for spoken announcements. Resolved
automatically from the Text-to-Speech engines configured in Home
Assistant.
resolver: tts_engine
default: "tts.piper"
integrations:
# Recipe sets up NWS hands-off — clicking "Set up" submits the
# config flow with values the recipe and HA already know: a
# placeholder api_key (NWS doesn't enforce keys on its public
# endpoints), the home's lat/lon from HA config, and the nearest
# METAR station resolved from coordinates via api.weather.gov.
# The homeowner never sees the form.
- domain: nws
title: National Weather Service
auto_setup:
values:
api_key: "selora-ai-recipe"
resolved:
latitude: hass_config_latitude
longitude: hass_config_longitude
station: nws_station_from_location
package_files:
- package/automations/warning.yaml.j2
- package/automations/watch.yaml.j2
{# Tornado WARNING automation — fires the siren, announces the
shelter zone. The siren is unconditional: the manifest's
presence_sensors role is not read here (see manifest.yaml).
Triggered on any state change of weather.<station>; the condition
filters down to the "Tornado Warning" string. The NWS HA
integration surfaces severe weather codes as the weather entity's
state value.
``value_template`` is single-quoted so YAML doesn't read the leading
``{{`` as a flow mapping. #}
automation:
- id: selora_recipe_{{ slug | replace('-', '_') }}_warning
alias: "Tornado Alert — warning response"
description: >-
When the NWS feed flips to a tornado warning, fire the indoor
siren and announce the shelter zone.
mode: single
trigger:
- platform: state
entity_id: weather.{{ inputs.station_code | lower }}
condition:
- condition: template
value_template: "{% raw %}{{ 'tornado warning' in trigger.to_state.state | lower }}{% endraw %}"
action:
# 1. Fire the siren, unconditionally. Single role with
# max_count=1 so index 0.
# ``siren.turn_on`` is the HA service for the siren domain;
# most modern Z-Wave / zigbee sirens accept it directly. If the
# homeowner's siren is shimmed as a switch, the manifest will
# need a binding-mode that translates this for them.
- service: siren.turn_on
target:
entity_id: {{ roles.indoor_siren[0] }}
{% if roles.announce_media_players and inputs.tts_engine %}
# 2. Announce on every configured speaker via the resolved TTS engine.
# tts.speak is engine-agnostic (works without Home Assistant Cloud);
# the engine entity is auto-resolved and the speakers are passed as
# media_player_entity_id. Tone copy is picked at render time from the
# homeowner's warning_message input.
- service: tts.speak
target:
entity_id: {{ inputs.tts_engine }}
data:
media_player_entity_id:
{% for player in roles.announce_media_players %}
- {{ player }}
{% endfor %}
{% if inputs.warning_message == 'calm' %}
message: "A tornado warning is in effect for your area. Please move to {{ inputs.shelter_zone }}."
{% elif inputs.warning_message == 'terse' %}
message: "Tornado warning. Move to {{ inputs.shelter_zone }} now."
{% else %}
message: "Tornado warning. Move to {{ inputs.shelter_zone }} immediately."
{% endif %}
{% endif %}
# 3. Push notification mirrors the announcement so anyone away
# from a speaker still gets the alert on their phone.
- service: notify.notify
data:
title: "Tornado warning"
message: "Tornado warning in effect. Move to {{ inputs.shelter_zone }}."
{# Tornado WATCH automation — calmer heads-up. A watch means
conditions are favourable for tornadoes; a warning means one's
been sighted. The watch automation gives the homeowner a moment
to glance at the sky and pre-stage.
``value_template`` is single-quoted so YAML doesn't read the
leading ``{{`` as a flow mapping. #}
automation:
- id: selora_recipe_{{ slug | replace('-', '_') }}_watch
alias: "Tornado Alert — watch heads-up"
description: >-
When the NWS feed signals a tornado watch, send a calm TTS
announcement to every configured speaker. No siren.
mode: single
trigger:
- platform: state
entity_id: weather.{{ inputs.station_code | lower }}
condition:
- condition: template
value_template: "{% raw %}{{ 'tornado watch' in trigger.to_state.state | lower }}{% endraw %}"
action:
{% if roles.announce_media_players and inputs.tts_engine %}
# Announce via the auto-resolved TTS engine. tts.speak works without a
# Home Assistant Cloud subscription; the speakers go in
# media_player_entity_id and the engine entity is the target.
- service: tts.speak
target:
entity_id: {{ inputs.tts_engine }}
data:
media_player_entity_id:
{% for player in roles.announce_media_players %}
- {{ player }}
{% endfor %}
message: "Tornado watch active for your area. Selora is monitoring. If you hear the siren, move to {{ inputs.shelter_zone }}."
{% endif %}
- service: notify.notify
data:
title: "Tornado watch"
message: "Tornado watch active. Conditions favour tornadoes — stay alert."
Author-maintained release notes. Each release of the recipe lists what changed.
Changelog
v1.1.0 - 2026-06-29
- Spoken announcements now use
tts.speakwith an auto-resolved TTS engine instead oftts.cloud_say.tts.cloud_sayonly exists with a paid Home Assistant Cloud (Nabu Casa) subscription, so the watch/warning announcements were silent on every home without it. The engine is detected automatically (Home Assistant Cloud, then Piper, then Google, else the first available); no new question in the wizard. - On a home with no Text-to-Speech engine configured, the announcement is skipped and the siren plus push notification still install.
v1.0.0 - 2026-05-28
Initial release.
- Subscribes to the National Weather Service for the homeowner’s county and watches for tornado watch and warning codes.
- Sounds the indoor siren on a warning. A watch stays quiet: announcement and push notification only.
- Announces the alert on every selected speaker over Text-to-Speech, and mirrors it to a push notification so anyone out of earshot still gets it.
- Routes occupants to a homeowner-configured shelter zone.
Note: this entry previously described occupancy-gated sirens and open-door announcements. Neither shipped in v1.0.0, and neither is implemented in any released version; the wording has been corrected rather than left standing.