Cat Alert: Home Assistant meldet die offene Haustür
Irgendwer hat die Haustür offen gelassen. Nicht weit, nicht lange — aber lange genug. Alfie und Shaniqua sind Wohnungskatzen, draußen ist tabu. Beide waren weg. Zurückgeholt, unverletzt, gut ausgegangen — und trotzdem einer dieser Momente: ein Haus voller Sensoren, und niemand sagt, dass die Tür offen steht. Kein Alarm, keine Rettungsaktion. Nur ein Satz, laut genug.
Der erste Plan: die Ring-Basisstation soll reden
Die Ring-Basisstation steht im Flur, hat einen Lautsprecher und sagt mir jeden Tag “entry delay” ins Gesicht. Naheliegend: die soll auch “Haustür ist offen” sagen.
Geht nicht, auch über ring-mqtt nicht — sichtbar sind Lautstärke und Einbruchssirene, sonst nichts. Kein TTS-Endpunkt, keine Ansage-API, die gesprochenen Sätze sind fixe Firmware-Sounds. Du besitzt die Hardware, sie kann sprechen — und darfst ihr keinen eigenen Satz beibringen.
Plan B: kein Satz, sondern der Chirp, dieses “Ding Dong” beim Öffnen. Geht auch nicht — der Chirp entsteht in der Basisstation als Reaktion auf ein Sensor-Event. select.front_door_chirp_tone darf auswählen, welcher Ton gespielt wird, aber nicht, dass einer gespielt wird. Draufgabe: das Select stand auf “Disabled”, unverändert seit einem ring-mqtt-Neustart.
Der Rest war genauso unbrauchbar: switch.pasching_alarm_siren ist die Einbruchssirene (die hätte die Katzen mindestens so erschreckt wie die offene Tür), switch.entrance_hall_keypad_chirps eine Einstellung statt eines Piepsers, switch.kitchen_siren eine Kamerasirene. Ansager wurden also Geräte, die nie dafür gedacht waren: der Wohnzimmer-Chromecast und ein Lenovo P11 als Wandtablet.
Die Falle mit der falschen Entity
Die erste Version hat auf binary_sensor.front_door getriggert. Heißt “Front Door”, klingt nach Haustür, ist keine: device_class: motion — der Bewegungssensor der Haustürkamera. Der echte Türkontakt heißt binary_sensor.contact_sensor_32232, device_class: door. Die Entity mit dem offensichtlichen Namen ist die falsche, die mit der Seriennummer die richtige.
Das Fiese: es hat trotzdem “funktioniert”. Kein Fehler, nichts im Log — die Automatisierung lief eben, wenn der Postler vorbeiging, statt bei offener Tür. Aufgefallen ist es nur, weil daneben automation.living_room_double_door_open_10s_rene_iphone, die simple 10-Sekunden-Push aufs iPhone, weiter korrekt gefeuert hat. Die hat gemeldet, die Katzenwarnung nicht — da schaust du dann doch in die device_class. Die zweite Tür, binary_sensor.double_door_living_room, kam später dazu.
Die Automatisierung
Der echte Aufbau, automation.front_door_left_open_announce_on_tv, Alias “Door left open – announce”:
triggers:
- trigger: state
entity_id:
- binary_sensor.contact_sensor_32232
- binary_sensor.double_door_living_room
to: "on"
for: "00:00:30"
conditions:
- condition: state
entity_id: timer.cat_alert_snooze
state: idle
variables:
door: "{{ trigger.entity_id }}"
message: "Cat alert! A door is open. Cat alert! A door is open. Cat alert! A door is open."
mode: parallel
max: 2
Dann die Aktionen: scene.create mit scene_id: cat_alert_before und snapshot_entities: [light.wohnzimmer_lampe, media_player.renes_echo_spot], damit Lampe und Echo-Lautstärke am Ende wieder so dastehen wie vorher. Danach drei Kommandos ans Tablet über notify.mobile_app_hatablet: command_screen_on, command_webview auf /dashboard-dashboard/cat-alert und command_volume_level mit media_stream: alarm_stream, command: 10 (Skala 0–15). Plus eine Zeile für den Echo:
- action: media_player.volume_set
target: { entity_id: media_player.renes_echo_spot }
data: { volume_level: 0.6 }
Und dann die eigentliche Schleife:
- repeat:
while:
- condition: template
value_template: "{{ is_state(door, 'on') }}"
- condition: state
entity_id: timer.cat_alert_snooze
state: idle
sequence:
- parallel:
- repeat:
count: 3
sequence:
- action: light.turn_on
target: { entity_id: light.wohnzimmer_lampe }
data: { brightness_pct: 100 }
- delay: { milliseconds: 600 }
- action: light.turn_off
target: { entity_id: light.wohnzimmer_lampe }
- delay: { milliseconds: 600 }
- sequence:
- action: notify.mobile_app_hatablet
data:
message: TTS
data:
tts_text: "{{ message }}"
media_stream: alarm_stream
- if:
- condition: state
entity_id: media_player.living_room_tv
state: "off"
then:
- action: media_player.turn_on
target: { entity_id: media_player.living_room_tv }
- wait_template: "{{ not is_state('media_player.living_room_tv','off') }}"
timeout: "00:00:25"
continue_on_timeout: true
- action: tts.speak
target: { entity_id: tts.google_translate_en_com }
data:
media_player_entity_id: media_player.living_room_tv
message: "{{ message }}"
- action: notify.alexa_media
data:
message: "{{ message }}"
target: [media_player.renes_echo_spot]
data: { type: announce }
- wait_template: "{{ is_state(door,'off') or not is_state('timer.cat_alert_snooze','idle') }}"
timeout: "00:00:20"
continue_on_timeout: true
- action: scene.turn_on
target: { entity_id: scene.cat_alert_before }
Jede Service-Aktion trägt continue_on_error: true (im Listing der Lesbarkeit halber weggelassen) — Tablet offline heißt, Echo und Fernseher reden trotzdem.
Der Echo kam zuletzt — und macht den Job am besten
Der ganze Zirkus oben ist entstanden, weil im Wohnzimmer nichts stand, das einfach reden kann. Jetzt schon: media_player.renes_echo_spot, ein Echo Spot, der ohnehin als Sprachassistent läuft — laut last_called_summary war mein letzter Satz an ihn “wohnzimmer licht aus”.
Die Anbindung ist ein Zweig im parallel-Block: notify.alexa_media mit target: [media_player.renes_echo_spot] und data: { type: announce } — Announcement-Modus, also Gong und danach der gesprochene Text. Kein Aufwecken, kein wait_template, kein Chromecast, der sich besinnen muss — er steht im Raum und sagt den Satz. Gemessen habe ich den Zweig nicht; die einzigen echten Werte bleiben rund eine Sekunde beim Tablet und rund 17 beim kalten Chromecast. Dazu media_player.volume_set auf 0.6, damit die Ansage nicht auf dem Pegel läuft, den zuletzt jemand eingestellt hat (previous_volume: 0.1); dieselbe Lautstärke landet im Snapshot und wird danach zurückgesetzt.
Dazu drei Einschränkungen, ungeschönt. Erstens: scene.cat_alert_before existiert noch gar nicht als Entity — scene.create legt sie zur Laufzeit an, und die Umbenennung ist neuer als der letzte Lauf. Das Wiederherstellen greift also erst ab dem zweiten Durchlauf, und nach einem HA-Neustart hat der erste Alarm nichts, worauf er zurückstellen könnte. Zweitens: Alexa Media Player ist eine HACS-Integration auf einer eingeloggten Amazon-Cloud-Session — funktioniert heute, verifiziert, und hört auf zu funktionieren, wenn Amazon am Login oder an 2FA dreht. Drittens: niemand ist bisher während eines Alarms im Wohnzimmer gestanden, während alle drei gleichzeitig loslegen. Ob das sauber klingt oder wie drei Betrunkene, die denselben Satz aufsagen, weiß ich nicht.
Die Pointe: ein Amazon-Lautsprecher sagt mir jeden beliebigen Satz auf Zuruf. Die Ring-Basisstation im selben Haus — auch Amazon, auch mit Lautsprecher und Sprachausgabe — sagt nur die Sätze, die jemand anderer vorgesehen hat.
Warum die krummen Konstrukte
wait_template statt wait_for_trigger beim Fernseher. Der Chromecast springt oft schon von off auf idle, während media_player.turn_on noch läuft; ein wait_for_trigger, das erst danach scharf wird, verpasst den Übergang und sitzt das volle Timeout ab — das Template ist da längst wahr. Gemessen: vorher rund 25 Sekunden, nachher rund 5.
wait_template statt fixem delay in der Schleife, weil die erste Version stur gewartet und dann nochmal geschrien hat, obwohl die Tür längst zu war — als Template auf door, weil die Tür dynamisch ist. Und alle drei Ansager parallel statt nacheinander, sonst wartet die schnelle Ansage auf die langsamste.
Der Android-Teil, der länger gedauert hat als die Automatisierung
Das Tablet blieb stumm. Die HA-Traces waren eindeutig: alle vier Kommandos gingen innerhalb einer Sekunde nach dem Trigger raus, zweimal hintereinander (08:46:52.7 und 20 Sekunden später). Der Fehler lag komplett auf der Android-Seite — Doze schiebt Firebase-Push im Tiefschlaf auf. Beweis: beim Entsperren feuerte das Tablet alle aufgestauten Ansagen auf einmal ab.
Was stimmen musste, in der Reihenfolge, in der es mich gebissen hat:
- Über anderen Apps anzeigen — brauchen
command_screen_onundcommand_launch_app. - Displaysperre auf “Keine” — mit PIN kommt die App nicht über den Sperrbildschirm, “Wischen” reicht nicht.
- Zugriff auf “Nicht stören” — braucht
command_volume_level, heißt unter Android 15 “Modus-Zugriff”, weshalb das Tablet einen Dialog zeigt, den niemand kennt. - Akku → uneingeschränkt — bei Lenovos ZUI-Android anders benannt, war hier aber nicht das Problem.
- Dauerhafte Verbindung → Immer (HA-App → Einstellungen → Companion App → Benachrichtigungen). Der eigentliche Fix: HA liefert über einen lokalen Websocket statt über Firebase, Doze kann nichts mehr zurückhalten. Kostet eine permanente Benachrichtigung, lässt sich aber per
command_persistent_connection: alwayspluskeep_screen_onaus der Ferne setzen. Gibt es nur im Play-Store-Build; der F-Droid-Build nimmt ohne Firebase sowieso den Websocket.
Lautstärke: alarm_stream_max dreht ohne Berechtigung auf Maximum und stellt den alten Wert wieder her; alarm_stream spielt auf dem Pegel, den du vorher setzt, braucht dafür die “Nicht stören”-Berechtigung. Ich bin bei 10 von 15 gelandet.
Die Snooze, die man nicht vergessen kann
Wenn du an einem Sommerabend die Terrassentür offen lässt, willst du nicht alle 20 Sekunden angeschrien werden. Dafür timer.cat_alert_snooze: 30 Minuten, restore: true, übersteht einen HA-Neustart. Er wirkt oben als Bedingung (gar nicht erst anfangen) und in der while-Bedingung (mittendrin aufhören, spätestens nach 20 Sekunden). Dann läuft er ab und alles ist wieder scharf.
Deshalb ein Timer und kein input_boolean: ein Schalter, den du ausschalten kannst, ist einer, den du wieder einzuschalten vergisst — und dann steht die Tür offen, während die Warnung stumm ist. Dieselbe Logik wie beim Rollladen am Catio: der Schutz darf nicht davon abhängen, dass ich daran denke. Auf dem Dashboard liegt er als Button unter “Türen” und in der Cat-Alert-Ansicht — ruhend “Snooze Cat Alert (30 min)”, laufend “Cat Alert snoozed – tap to resume”.
Die Cat-Alert-Ansicht
/dashboard-dashboard/cat-alert, angelegt als Subview, damit sie die Tab-Leiste nicht vollmüllt. Drin: die Überschrift “Cat alert! A door is open”, ein Bild von Alfie und Shaniqua, eine farbcodierte Statusliste der Türen, der Snooze/Resume-Button und einer zurück aufs Hauptdashboard. Das Tablet wird per command_webview direkt dorthin geschoben — hinschauen, und du weißt, welche Tür offen steht.

Die Katzenfotos liegen nicht auf dem HA-Host, sondern kommen über die gehashten _astro/…-URLs von diesem Blog. Sollbruchstelle: neue Hashes, Bilder weg.
Ehrlich:
Das hier ist eine Nag-Maschine, kein Sicherheitssystem: Sie meldet im Nachhinein, und eine Katze ist in den 30 Sekunden bis zur ersten Ansage längst draußen. Die Zeit ist ein Kompromiss — kürzer brüllt das Ding jedes Mal, wenn ich Einkäufe reintrage, länger und die Katze ist weg. Abgedeckt sind zwei Türen, andere Türen und sämtliche Fenster nicht. Nicht getestet: was passiert, wenn beide Türen gleichzeitig offen stehen. mode: parallel mit max: 2 steht genau dafür drin, aber der Fall ist real noch nie eingetreten. Ich behaupte nicht, dass es funktioniert — nur, dass ich es vorgesehen habe.
Und der Punkt, den ich vor ein paar Wochen noch anders geschrieben hätte: wenn du einen richtigen Sprachlautsprecher hast, fang dort an. Der Echo-Zweig ist eine Handvoll Zeilen YAML; der Tablet-Zweig hat mich fünf Android-Einstellungen und mehr Zeit als die ganze Automatisierung gekostet, und dass ein Consumer-Tablet wach bleiben muss, ist der schwächste Punkt der Kette.
Was der Echo nicht löst: Er hängt an einer Amazon-Session, die ich nicht kontrolliere — der Tag, an dem sie kippt, ist genau der Tag, an dem das mühsame Tablet der Grund ist, dass trotzdem jemand die Tür zumacht. Und er redet nur in einem Raum; Lampe und Fernseher sind da, weil man eine Ansage auch mal nicht hört. Deshalb fliegt die alte Maschinerie nicht raus — sie ist vom Hauptdarsteller zum Ersatzmann geworden.
Wo ich gelandet bin
Bei einer Automatisierung, die meine Katzen nicht rettet. Sie sagt einen Satz, blinkt mit einer Lampe und hört auf, sobald die Tür zu ist. Sie läuft auf einem Türkontakt, der nach einer Seriennummer heißt, spricht über einen Fernseher, der dafür nicht gebaut wurde, über ein Tablet, dem ich den Schlaf abgewöhnen musste — und seit Kurzem über das einzige Gerät im Aufbau, das dafür gebaut wurde. Im Flur daneben steht die Alarmanlage desselben Konzerns und darf nach wie vor nichts beitragen. Seit das Ding läuft, steht keine Tür mehr eine Minute offen, ohne dass es jemand mitbekommt.