Du hast einen Wecker in Home Assistant. Du gehst in den Urlaub. Du schaltest den Wecker manuell aus. Du vergisst, ihn wieder einzuschalten. Oder du schaltest ihn zu frueh ein und wirst am letzten Urlaubstag geweckt.
Die Loesung: Der Kalender ist die einzige Quelle der Wahrheit. Wenn dort “Urlaub” steht, schweigt der Wecker. Wenn das Event endet, feuert er wieder. Ohne Schalter, ohne Extra-Automation.
TL;DR
- Shell-Script auf dem HA-Server fragt per CalDAV, ob heute ein “urlaub”-Event aktiv ist
command_lineBinary Sensor in HA:on= Urlaub,off= kein Urlaub- Wecker-Automations pruefen
condition: notauf diesen Sensor — fail-open - Drei Pitfalls die euch Zeit sparen: CalDAV Config Flow, deprecated YAML-Platform, BusyBox-
date
Die Architektur
Kalender-Server (CalDAV)
|
v (curl REPORT, alle 15 Min)
HA: check_urlaub.sh
|
v
binary_sensor.urlaub_kalender [on/off]
|
v (condition: not → state: on)
Set_Weekday_Alarm / Set_Weekend_Alarm
Der Binary Sensor pollt alle 15 Minuten den CalDAV-Server. Fuer mehrtaegige Urlaubs-Events ist das mehr als ausreichend.
Das Script: CalDAV-Abfrage
Das Script laeuft direkt im HA-Container und fragt per CalDAV REPORT (RFC 4791) die heutigen Events ab. Wenn ein Event mit “urlaub” im Titel gefunden wird: ON. Sonst: OFF.
#!/bin/bash
# /config/check_urlaub.sh
CALDAV_URL="https://mail.deathstar.lan/dav/calendars/luke.skywalker@rebellion.local/Kalender/"
CALDAV_USER="c3po@rebellion.local"
CALDAV_PASS="<DEIN-CALDAV-PASSWORT>"
START=$(date -u +%Y%m%dT000000Z)
# BusyBox-kompatibel (siehe Pitfall 3)
END=$(date -u -D %s -d $(($(date +%s) + 86400)) +%Y%m%dT000000Z)
RESULT=$(curl -s --max-time 10 -u "$CALDAV_USER:$CALDAV_PASS" \
-X REPORT -H "Depth: 1" -H "Content-Type: application/xml" \
"$CALDAV_URL" \
-d "<?xml version=\"1.0\"?>\
<c:calendar-query xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\
<d:prop><c:calendar-data/></d:prop>\
<c:filter><c:comp-filter name=\"VCALENDAR\">\
<c:comp-filter name=\"VEVENT\">\
<c:time-range start=\"$START\" end=\"$END\"/>\
</c:comp-filter></c:comp-filter></c:filter>\
</c:calendar-query>")
if echo "$RESULT" | grep -qi "urlaub"; then
echo "ON"
else
echo "OFF"
fi
Wichtig: Der CalDAV-User braucht Leserechte auf den Kalender des Ziel-Users. Bei Grommunio:
grommunio-admin exmdb luke.skywalker@rebellion.local folder grant 0x9 \
c3po@rebellion.local foldervisible readany
0x9 ist der Store Root — ohne foldervisible dort sieht SabreDAV die Kalender-Kollektionen im PROPFIND nicht.
HA-Konfiguration
Binary Sensor (configuration.yaml)
command_line:
- binary_sensor:
name: "Urlaub Kalender"
unique_id: urlaub_kalender_caldav
command: "bash /config/check_urlaub.sh"
device_class: occupancy
payload_on: "ON"
payload_off: "OFF"
scan_interval: 900
Automation-Condition (automations.yaml)
Die Urlaubs-Pruefung kommt als erste Condition in den bestehenden Wecker:
- id: 'weekday_alarm'
alias: Set_Weekday_Alarm
triggers:
- at: input_datetime.alarm
trigger: time
conditions: []
actions:
- choose:
- conditions:
# Urlaub? → Wecker aus
- condition: not
conditions:
- condition: state
entity_id: binary_sensor.urlaub_kalender
state: 'on'
# Normaler Wochentag?
- condition: time
weekday: [mon, tue, wed, thu, fri]
# Wecker eingeschaltet?
- condition: state
entity_id: input_boolean.alarm_on_off
state: 'on'
sequence:
# ... Licht, Musik, Kaffeemaschine
Warum condition: not statt state: 'off'?
Fail-open. Wenn der CalDAV-Server nicht erreichbar ist, wird die Entity unavailable:
| Sensor-State | condition: not → on | state: 'off' |
|---|---|---|
on (Urlaub) | Wecker aus | Wecker aus |
off (kein Urlaub) | Wecker an | Wecker an |
unavailable | Wecker an | Wecker aus |
Mit state: 'off' wuerde ein CalDAV-Ausfall den Wecker dauerhaft stumm schalten. condition: not kehrt die Logik um: nur ein explizites on unterdrueckt den Wecker. Alles andere — inklusive Fehler — laesst ihn feuern.
Faustregel: Wenn der Fehlerfall “Wecker klingelt obwohl Urlaub” vs. “Wecker schweigt obwohl Arbeitstag” ist — waehle ersteres.
Die drei Pitfalls
Pitfall 1: CalDAV Config Flow geht nicht fuer Cross-Account
HA hat eine CalDAV-Integration in der UI (Einstellungen → Integrationen → CalDAV). Die funktioniert — aber nur fuer den Kalender des authentifizierten Users.
Wenn User A den Kalender von User B lesen soll (z.B. ein Service-Account liest den Chef-Kalender), folgt die Config Flow trotzdem dem Principal von User A. Die Entity zeigt dann einen leeren Kalender.
Kein Fehler, kein Log-Eintrag. Die Entity existiert, hat 0 Events, und man sucht den Fehler woanders.
Workaround: command_line Binary Sensor mit direktem curl-CalDAV-REPORT auf die URL des Ziel-Kalenders. Umgeht die Discovery komplett.
Pitfall 2: YAML CalDAV-Platform ist deprecated (silent fail)
Die alte YAML-Variante:
calendar:
- platform: caldav
url: https://...
username: ...
password: ...
custom_calendars:
- name: "Urlaub"
calendar: "Kalender"
search: "(?i)urlaub"
wird in aktuellen HA-Versionen ohne Fehlermeldung ignoriert. config/core/check_config meldet valid. Kein Log-Eintrag. Die Entity wird nie erstellt.
Das ist besonders tueckisch, weil die YAML-Platform frueher Features hatte die der Config Flow nicht bietet (custom_calendars mit search-Filter). Man konfiguriert es, startet HA neu, alles sieht OK aus — nur die Entity fehlt.
Pitfall 3: BusyBox-date im HA-Container
Home Assistant OS laeuft auf Alpine Linux. Der Container hat BusyBox statt GNU coreutils. Das betrifft date:
# GNU date (funktioniert auf Debian/Ubuntu):
date -d "+1 day" +%Y%m%dT000000Z
# BusyBox date (HA Container):
date: invalid date '+1 day'
BusyBox-kompatible Alternative:
date -u -D %s -d $(($(date +%s) + 86400)) +%Y%m%dT000000Z
Betrifft alle shell_command und command_line Sensoren in HA OS.
Der Workflow
- Urlaubs-Event im Kalender eintragen (beliebiger Client — Outlook, Thunderbird, Handy)
- Warten bis der naechste 15-Minuten-Poll laeuft
binary_sensor.urlaub_kalenderwechselt aufon- Wecker-Automations pruefen die Condition und schweigen
- Event endet → Sensor geht auf
off→ Wecker feuert wieder
Kein manueller Eingriff. Eine Quelle der Wahrheit.
Lessons Learned
- Fail-open schlaegt fail-closed bei Weckern. Lieber einmal zu viel geweckt als verschlafen.
- CalDAV Config Flow in HA ist nicht CalDAV — sie ist eine opinionated Abstraktion. Fuer Cross-Account-Zugriff braucht man den Rohweg ueber curl.
- Silent deprecation ist schlimmer als ein Breaking Change. Fehlermeldungen helfen. Stilles Ignorieren kostet Stunden.
- Alpine/BusyBox-Kompatibilitaet ist ein Evergreen-Problem. Jedes Shell-Script das im HA-Container laeuft braucht einen Test im Container, nicht auf dem Entwickler-Rechner.
Checkliste
- CalDAV-User hat Leserechte auf den Ziel-Kalender
-
check_urlaub.shim HA-Container getestet (docker exec homeassistant bash /config/check_urlaub.sh) - Binary Sensor in Developer Tools → States sichtbar und mit korrektem State
- Wecker-Automation nutzt
condition: not(fail-open) - Kalender-Event angelegt und Sensor reagiert