Home Assistant Morgen-Briefing — TTS mit Kalender, Wetter und Strompreis
Wie ich ein tägliches 06:00-Uhr-Sprachbriefing in Home Assistant mit Google AI TTS (Gemini), calendar.get_events über drei Familienkalender, EV-Ladestatus, Waze-Pendelverkehr, Live-Strompreis und Müllabfuhr-Countdown gebaut habe.
Jeden Morgen öffnete ich die Home Assistant App, um den Tageskalender zu prüfen, einen Blick auf das Wetter zu werfen und den Strompreis für die Nacht zu beurteilen. Drei separate Abfragen vor dem Kaffee.
Die Morgen-Briefing-Automation hat das alles ersetzt. Um 06:00 Uhr liest der Küchenlautsprecher die heutigen Termine aus drei Familienkalendern vor, nennt die Außentemperatur, warnt vor der morgigen Müllabfuhr und gibt den aktuellen Stromspot-Preis an. Das Ganze dauert etwa 15 Sekunden.
Das Kernmuster: calendar.get_events mit response_variable
Die meisten Home Assistant Automations-Tutorials stoppen beim Auslösen durch ein Kalenderereignis. Diese Automation verfolgt einen anderen Ansatz: Sie fragt den Kalender aktiv nach den heutigen Ereignissen ab und verwendet die Antwort in einem Template.
Die calendar.get_events-Aktion gibt eine strukturierte Antwort zurück, die in einer Variable gespeichert werden kann:
- action: calendar.get_events
target:
entity_id: calendar.rolf_szimnau_dk
data:
start_date_time: "{{ today_at('00:00') }}"
end_date_time: "{{ today_at('23:59') }}"
response_variable: kalender
Die Antwort ist ein Dict mit der Entitäts-ID als Schlüssel. Auf die Ereignisliste wird so zugegriffen:
{% set events = kalender['calendar.rolf_szimnau_dk']['events'] %}
Mehrere Kalender zusammenführen
Für jeden Kalender eine separate calendar.get_events-Aktion mit eigenem response_variable ausführen, dann die Listen im Template kombinieren:
{% set events = events_rolf + events_annette + events_louise %}
Die vollständige Automation
alias: "Morgen-Briefing: TTS um 06:00"
mode: single
trigger:
- platform: time
at: "06:00:00"
action:
- action: calendar.get_events
target:
entity_id: calendar.rolf_szimnau_dk
data:
start_date_time: "{{ today_at('00:00') }}"
end_date_time: "{{ today_at('23:59') }}"
response_variable: kalender
- action: calendar.get_events
target:
entity_id: calendar.annette_familie
data:
start_date_time: "{{ today_at('00:00') }}"
end_date_time: "{{ today_at('23:59') }}"
response_variable: kalender_annette
- action: calendar.get_events
target:
entity_id: calendar.louise_familie
data:
start_date_time: "{{ today_at('00:00') }}"
end_date_time: "{{ today_at('23:59') }}"
response_variable: kalender_louise
- action: tts.speak
target:
entity_id: tts.google_ai_tts
data:
media_player_entity_id: media_player.hojtaler_kokken
language: da-DK
message: >-
{% set dage = ['mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag', 'søndag'] %}
{% set dag = dage[now().weekday()] %}
{% set events_rolf = kalender['calendar.rolf_szimnau_dk']['events'] %}
{% set events_annette = kalender_annette['calendar.annette_familie']['events'] %}
{% set events_louise = kalender_louise['calendar.louise_familie']['events'] %}
{% set events = events_rolf + events_annette + events_louise %}
{% set temp = state_attr('weather.forecast_home', 'temperature') %}
{% set affald = states('sensor.affalddk_bytoften_1_naeste_afhentning') | int(99) %}
{% set elpris = states('sensor.energi_data_service') | float(0) | round(2) %}
{% set km = states('sensor.skoda_elroq_range') | int(0) %}
{% set bat = states('sensor.skoda_elroq_battery_percentage') | int(0) %}
{% set maal = states('sensor.skoda_elroq_target_battery_percentage') | int(80) %}
{% set lader = states('sensor.skoda_elroq_charging_state') %}
{% set ac = states('climate.skoda_elroq_air_conditioning') %}
{% set rejsetid = states('sensor.rejsetid_vejle_travel_time') | float(0) | round(0) | int %}
God morgen! I dag er det {{ dag }}.
Temperaturen ude er {{ temp }} grader.
{% if events | length > 0 %}
Du har {{ events | length }} aftale{% if events | length > 1 %}r{% endif %} i dag:
{% for event in events %}{{ event.summary }}{% if not loop.last %}, {% endif %}{% endfor %}.
{% else %}Ingen aftaler i dag.
{% endif %}
{% if affald <= 1 %}Husk: affald hentes i dag!
{% elif affald <= 2 %}Husk: affald hentes i morgen.
{% endif %}
{% if km > 0 and km < 100 %}Elroq har kun {{ km }} kilometer tilbage.
{% endif %}
{% if lader == 'charging' %}Elroq lader: {{ bat }}% ud af {{ maal }}%.
{% elif bat < maal %}Elroq er {{ bat }}% – har ikke nået målet på {{ maal }}%.
{% endif %}
{% if ac != 'off' %}Elroq varmer op.
{% endif %}
{% if now().weekday() < 5 and rejsetid > 0 %}
{% if rejsetid > 40 %}Trafik til arbejde: {{ rejsetid }} minutter – forvent forsinkelse.
{% else %}Kørsel til arbejde: {{ rejsetid }} minutter.
{% endif %}{% endif %}
Elprisen er {{ elpris }} kroner per kilowattime.
Anpassung
Nur Werktage — Bedingung über den Aktionen hinzufügen:
condition:
- condition: time
weekday: [mon, tue, wed, thu, fri]
Anderer Lautsprecher — media_player.hojtaler_kokken durch eine beliebige HA Media Player-Entität ersetzen.
Andere TTS-Engine — tts.google_ai_tts durch tts.google_translate_en_com für die kostenlose Option ersetzen.
EV-Ladestatus und Vorklimatisierung hinzufügen
Zwei Sensoren der MyŠkoda-Integration (oder einer anderen EV-Integration) geben Auskunft darüber, ob das Auto für den Tag bereit ist.
Ladestatus — das Briefing spricht nur, wenn Handlungsbedarf besteht. Hat das Auto sein Ziel über Nacht erreicht, wird nichts gesagt.
{% set bat = states('sensor.skoda_elroq_battery_percentage') | int(0) %}
{% set maal = states('sensor.skoda_elroq_target_battery_percentage') | int(80) %}
{% set lader = states('sensor.skoda_elroq_charging_state') %}
{% if lader == 'charging' %}Elroq lader: {{ bat }}% ud af {{ maal }}%.
{% elif bat < maal %}Elroq er {{ bat }}% – har ikke nået målet på {{ maal }}%.
{% endif %}
sensor.skoda_elroq_target_battery_percentage wird in der MyŠkoda-App gesetzt und direkt als HA-Sensor bereitgestellt. Falls die eigene EV-Integration kein Ladeziel kennt, maal durch eine feste Zahl wie 80 ersetzen.
Vorklimatisierungsbestätigung — wenn eine Morgenaufwärmautomation wenige Minuten vor 06:00 Uhr läuft, kann das Briefing bestätigen, dass sie tatsächlich gestartet ist:
{% set ac = states('climate.skoda_elroq_air_conditioning') %}
{% if ac != 'off' %}Elroq varmer op.
{% endif %}
Das funktioniert, weil die Aufwärmautomation um 05:55 Uhr läuft — fünf Minuten vor dem Briefing. Um 06:00 Uhr ist climate.skoda_elroq_air_conditioning entweder aktiv (eine kurze Bestätigungszeile) oder noch off (kein Text — die Aufwärmautomation verwaltet ihren eigenen Fehleralarm separat).
Verkehrsinformationen hinzufügen
Die Waze Travel Time-Integration erstellt einen Sensor mit der aktuellen Fahrtzeit inkl. Live-Verkehr. Kein API-Schlüssel erforderlich — Waze-Daten sind kostenlos.
Installation: Einstellungen → Geräte & Dienste → Integration hinzufügen → Waze Travel Time
Für Herkunft und Ziel GPS-Koordinaten (Breitengrad,Längengrad-Format) statt Adressen verwenden. Waze’s Adress-Parsing ist für dänische Adressen unzuverlässig — Koordinaten sind eindeutig. Die eigenen Koordinaten lassen sich durch Rechtsklick auf einen Ort in Google Maps ermitteln.
Region auf EU und Routentyp auf schnellste setzen. Dem Sensor einen beschreibenden Namen geben, z.B. Pendelzeit Vejle — HA generiert daraus die Entitäts-ID, typischerweise sensor.pendelzeit_vejle_travel_time.
Diesen Block in die Nachrichten-Vorlage einfügen, direkt vor dem Strompreis:
{% set fahrzeit = states('sensor.pendelzeit_vejle_travel_time') | float(0) | round(0) | int %}
{% if now().weekday() < 5 and fahrzeit > 0 %}
{% if fahrzeit > 40 %}Verkehr zur Arbeit: {{ fahrzeit }} Minuten heute – Verzögerungen möglich.
{% else %}Fahrtzeit zur Arbeit: {{ fahrzeit }} Minuten.
{% endif %}
{% endif %}
now().weekday() < 5 überspringt Wochenenden automatisch. Den 40-Minuten-Schwellenwert an die normale Pendelzeit plus einen Puffer anpassen.
Warum tts.speak und nicht der alte Service
Home Assistant 2024+ verwendet tts.speak auf der TTS-Engine-Entität, mit media_player_entity_id als Datenfeld. Der alte tts.google_translate_say-Service funktioniert noch, ist aber veraltet. Das neue Muster trennt Engine und Abspielgerät — beide können unabhängig voneinander ausgetauscht werden.
tts.google_ai_tts wird von der Google Generative AI-Integration bereitgestellt — derselben Integration, die auch den Gemini-Konversationsagenten in Home Assistant antreibt. Sie erfordert einen Google AI Studio API-Schlüssel, erzeugt aber natürlich klingende Sprache im Vergleich zur roboterhaften Ausgabe der kostenlosen Google Translate TTS-Option.