Node Red Alexa Wecker

Dynamische Weckeranpassung mit Node-RED und Nextcloud-Kalender

In diesem Beitrag zeige ich, wie ein Node-RED-Flow genutzt werden kann, um den Wecker automatisch anzupassen, wenn ein Termin ein früheres Aufstehen erfordert. Die Lösung basiert auf einem Nextcloud-Kalender und passt den Alexa-Wecker entsprechend an, falls ein Termin vor der festgelegten Weckzeit (05:45 Uhr) liegt.

Voraussetzungen

Um diesen Flow nutzen zu können, werden folgende Komponenten benötigt:

  • Nextcloud-Instanz mit aktivierter CalDAV-Integration
  • Alexa-Wecker, der standardmäßig von Montag bis Freitag um 05:45 Uhr gestellt ist
  • Node-RED unter Home Assistant
  • Installierte Node-RED-Palette: node-red-contrib-alexa-remote2-applestrudel
  • CalDAV-Integration, um Termine aus dem Nextcloud-Kalender abrufen zu können

Funktionsweise

Der Flow überprüft den Nextcloud-Kalender auf bevorstehende Termine. Erkennt das System, dass ein Termin eine frühere Weckzeit als 05:45 Uhr erfordert, wird der Alexa-Wecker automatisch angepasst. So wird sichergestellt, dass man rechtzeitig aufwacht, ohne jeden Abend manuell den Wecker umstellen zu müssen.

Mit dieser Automatisierung wird der Alltag nicht nur komfortabler, sondern auch effizienter gestaltet. Kein manuelles Anpassen des Weckers mehr – die Termine bestimmen automatisch, wann der Wecker klingelt.

Gerne gebe ich dir einen Überblick über den Flow sowie das dazugehörige JSON, das du zum Importieren verwenden kannst.

[{"id":"7163fb6aea72c6c8","type":"inject","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 22 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":500,"wires":[["e17ca0122fc0615b"]]},{"id":"e17ca0122fc0615b","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Kalender und Datum ","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n    domain: \"calendar\",  // Calendar ist der Domain für die Kalenderabfragen\n    service: \"get_events\",  // Service, der die Termine abruft\n    data: {\n        entity_id: \"calendar.personlich\",  // Entität ersetzen!    \n        start_date_time: year + \"-\" + month + \"-\" + day + \" 00:00:00+01:00\",\n        end_date_time: year + \"-\" + month + \"-\" + day + \" 23:59:59+01:00\"\n    }\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":500,"wires":[["7c7f7ea65d804e4b"]]},{"id":"7c7f7ea65d804e4b","type":"api-call-service","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","server":"152c2aa.bcea4d5","version":7,"debugenabled":false,"action":"","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"results"}],"queue":"none","blockInputOverrides":false,"domain":"calendar","service":"get_events","x":490,"y":500,"wires":[["778586d24a57fa6e","59f0cceb5525f705"]]},{"id":"778586d24a57fa6e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Erstes Event des Tages","func":"// Hole das Array der Ereignisse\nlet events = msg.payload[\"calendar.personlich\"].events;\n\n// Falls keine Ereignisse vorhanden sind, eine Standardantwort zurückgeben\nif (!events || events.length === 0) {\n    msg.payload = { \"message\": \"Keine Termine gefunden\" };\n    return msg;\n}\n\n// Das früheste Event ohne Sortierung finden\nlet earliestEvent = events.reduce((earliest, event) => {\n    return new Date(event.start) < new Date(earliest.start) ? event : earliest;\n}, events[0]);\n\n// Sicherstellen, dass ein gültiges Startdatum existiert\nif (!earliestEvent || !earliestEvent.start) {\n    msg.payload = { \"message\": \"Fehler: Kein gültiges Startdatum gefunden\" };\n    return msg;\n}\n\n// Startzeit berechnen\nlet startTime = new Date(earliestEvent.start);\n\n// Eine Stunde abziehen\nstartTime.setUTCHours(startTime.getUTCHours() - 1 );\n\n// **Vergleich mit 05:45:00**\nlet checkTime = new Date(startTime);\ncheckTime.setHours(5, 45, 0, 0); // 05:45:00 setzen\n\n// Falls Weckzeit nach 05:45:00 liegt, auf 05:45:00 setzen\nif (startTime > checkTime) {\n    startTime = checkTime;\n}\n\n// Formatierte Ausgabe (lokale Zeit)\nlet year = startTime.getFullYear();\nlet month = (\"0\" + (startTime.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + startTime.getDate()).slice(-2);\nlet hours = (\"0\" + startTime.getHours()).slice(-2);\nlet minutes = (\"0\" + startTime.getMinutes()).slice(-2);\nlet seconds = (\"0\" + startTime.getSeconds()).slice(-2);\n\nmsg.payload = { \n    \"Weckzeit\": `${year}-${month}-${day}T${hours}:${minutes}:${seconds}` \n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":500,"wires":[["871c28861baaf1bd"]]},{"id":"59f0cceb5525f705","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 13","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":460,"wires":[]},{"id":"871c28861baaf1bd","type":"switch","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","property":"payload.message","propertyType":"msg","rules":[{"t":"eq","v":"Keine Termine gefunden","vt":"str"},{"t":"neq","v":"Keine Termine gefunden","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":870,"y":500,"wires":[["cd9ba4bb9eed555e"],["7328ebd9239d43b6"]]},{"id":"7328ebd9239d43b6","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"timestamp","pt":"msg","to":"$toMillis(msg.payload.Weckzeit)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1100,"y":500,"wires":[["4ea98fc36c5f900e"]]},{"id":"cd9ba4bb9eed555e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Kein Termin, Weckzeit 05:45","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n       wakeup_time: year + \"-\" + month + \"-\" + day + \" 05:45:00+01:00\",\n        \n    };\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1700,"y":400,"wires":[["f49346bac151b510"]]},{"id":"4ea98fc36c5f900e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"function 5","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1); // Morgen\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\n// Setze die Weckzeit als 05:45:00\nlet comparisonTime = year + \"-\" + month + \"-\" + day + \"T05:45:00\";\n\nmsg.payload = {\n    comparisonTime: comparisonTime,\n    currentTime: msg.payload\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1300,"y":500,"wires":[["fcc29179a38f7aca"]]},{"id":"f49346bac151b510","type":"alexa-remote-other","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","config":{"option":"changeNotification","value":{"notification":{"type":"str","value":"775ac127-c9dc-33fc-9e5c-1d34933e3d2e"},"label":{"type":"str","value":""},"time":{"type":"msg","value":"payload.wakeup_time"},"status":{"type":"str","value":""},"sound":{"type":"json","value":""}}},"x":2110,"y":440,"wires":[["37cd42ef20bcd167"]]},{"id":"fcc29179a38f7aca","type":"switch","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","property":"payload.currentTime.Weckzeit","propertyType":"msg","rules":[{"t":"gte","v":"payload.comparisonTime","vt":"msg"},{"t":"lt","v":"payload.comparisonTime","vt":"msg"}],"checkall":"true","repair":false,"outputs":2,"x":1450,"y":500,"wires":[["497e4996ccf91008"],["3ba26f5c9ecaadab","f83a0bb657ffeb87"]]},{"id":"497e4996ccf91008","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Tag Morgen und Weckzeit stellen","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n       wakeup_time: msg.payload.currentTime.Weckzeit\n        \n    };\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1720,"y":440,"wires":[["f49346bac151b510"]]},{"id":"37cd42ef20bcd167","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"priority","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"sound","pt":"msg","to":"bike","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"\"Weckzeit: \" & msg.payload.originalTime","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"Weckzeit","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":2350,"y":520,"wires":[["ef8b3e005be0bff7"]]},{"id":"3ba26f5c9ecaadab","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Tag Morgen und Weckzeit stellen","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n       wakeup_time: msg.payload.currentTime.Weckzeit\n            };\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1720,"y":600,"wires":[["3f024e16db6f6c40","108ed85e1ac79f60"]]},{"id":"f83a0bb657ffeb87","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":1670,"y":540,"wires":[["103c800dd6618952"]]},{"id":"3f024e16db6f6c40","type":"alexa-remote-other","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","config":{"option":"changeNotification","value":{"notification":{"type":"str","value":"775ac127-c9dc-33fc-9e5c-1d34933e3d2e"},"label":{"type":"str","value":""},"time":{"type":"msg","value":"payload.wakeup_time"},"status":{"type":"str","value":""},"sound":{"type":"json","value":""}}},"x":2090,"y":600,"wires":[["37cd42ef20bcd167"]]},{"id":"ef8b3e005be0bff7","type":"link out","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"link out Pushover ","mode":"link","links":["5b52c69bf84ce7c3"],"x":2485,"y":520,"wires":[]},{"id":"108ed85e1ac79f60","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 14","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1870,"y":700,"wires":[]},{"id":"103c800dd6618952","type":"template","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Wecker prüfen.","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<speak>    \n<s><voice name=\"Marlene\">Wecker prüfen!</voice></s>\n</speak>","output":"str","x":1880,"y":540,"wires":[["2f17418f09852317"]]},{"id":"2f17418f09852317","type":"alexa-remote-routine","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","routineNode":{"type":"speak","payload":{"type":"ssml","text":{"type":"msg","value":"payload"},"devices":["G0911B05941206GK","90F00818707508K1","G091JJ1314840ABS"]}},"x":2080,"y":540,"wires":[[]]},{"id":"152c2aa.bcea4d5","type":"server","name":"Home Assistant Qli","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false},{"id":"07016f8877dcae6d","type":"alexa-remote-account","name":"","authMethod":"proxy","proxyOwnIp":"192.168.177.2","proxyPort":"3456","cookieFile":"/homeassistant/node-red/alexa/alexa.txt","refreshInterval":"3","alexaServiceHost":"layla.amazon.de","pushDispatchHost":"","amazonPage":"amazon.de","acceptLanguage":"de-DE","onKeywordInLanguage":"on","userAgent":"","usePushConnection":"on","autoInit":"on","autoQueryActivityOnTrigger":"off"}]

Der Flow beginnt mit einem Inject-Node, der jeden Abend zu einer festgelegten Uhrzeit ausgelöst wird. Im Beispiel startet der Flow um 22:00 Uhr.

Mit der folgenden Funktion-Node werden die erforderlichen Daten aufbereitet. Dazu gehören das Datum des kommenden Tages sowie der abzurufende Kalender ("calendar.personlich"). Diese Daten werden in msg.payload gespeichert, sodass der nachfolgende Action-Node ohne zusätzliche Konfiguration verwendet werden kann.

let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);

// Start- und Endzeit für den Folgetag korrekt formatieren
let year = tomorrow.getFullYear();
let month = ("0" + (tomorrow.getMonth() + 1)).slice(-2);
let day = ("0" + tomorrow.getDate()).slice(-2);

msg.payload = {
    domain: "calendar",  // Calendar ist der Domain für die Kalenderabfragen
    service: "get_events",  // Service, der die Termine abruft
    data: {
        entity_id: "calendar.personlich",  // Entität ersetzen!    
        start_date_time: year + "-" + month + "-" + day + " 00:00:00+01:00",
        end_date_time: year + "-" + month + "-" + day + " 23:59:59+01:00"
    }
};

return msg;

Im nachfolgenden Action-Node wird der Output von msg.payload auf results gesetzt. Dadurch enthält die Nachricht die abgerufenen Kalendereinträge für die weitere Verarbeitung im Flow.

Die folgende Funktion-Node bildet das Herzstück des gesamten Flows. Hier wird zunächst der erste Termin des Tages ermittelt. Anschließend wird dessen Startzeit um eine Stunde reduziert (Zeile 25), wodurch die neue Weckzeit bestimmt wird.

Nun erfolgt ein Vergleich:

  • Falls die berechnete Weckzeit vor 05:45 Uhr liegt, wird sie übernommen.
  • Andernfalls bleibt die Weckzeit bei 05:45 Uhr (Anpassung in Zeile 29 möglich).

Die ermittelte Weckzeit wird schließlich in msg.payload.Weckzeit gespeichert und für die weitere Verarbeitung bereitgestellt.

// Hole das Array der Ereignisse
let events = msg.payload["calendar.personlich"].events;

// Falls keine Ereignisse vorhanden sind, eine Standardantwort zurückgeben
if (!events || events.length === 0) {
    msg.payload = { "message": "Keine Termine gefunden" };
    return msg;
}

// Das früheste Event ohne Sortierung finden
let earliestEvent = events.reduce((earliest, event) => {
    return new Date(event.start) < new Date(earliest.start) ? event : earliest;
}, events[0]);

// Sicherstellen, dass ein gültiges Startdatum existiert
if (!earliestEvent || !earliestEvent.start) {
    msg.payload = { "message": "Fehler: Kein gültiges Startdatum gefunden" };
    return msg;
}

// Startzeit berechnen
let startTime = new Date(earliestEvent.start);

// Eine Stunde abziehen
startTime.setUTCHours(startTime.getUTCHours() - 1 );

// **Vergleich mit 05:45:00**
let checkTime = new Date(startTime);
checkTime.setHours(5, 45, 0, 0); // 05:45:00 setzen

// Falls Weckzeit nach 05:45:00 liegt, auf 05:45:00 setzen
if (startTime > checkTime) {
    startTime = checkTime;
}

// Formatierte Ausgabe (lokale Zeit)
let year = startTime.getFullYear();
let month = ("0" + (startTime.getMonth() + 1)).slice(-2);
let day = ("0" + startTime.getDate()).slice(-2);
let hours = ("0" + startTime.getHours()).slice(-2);
let minutes = ("0" + startTime.getMinutes()).slice(-2);
let seconds = ("0" + startTime.getSeconds()).slice(-2);

msg.payload = { 
    "Weckzeit": `${year}-${month}-${day}T${hours}:${minutes}:${seconds}` 
};

return msg;

Der nachfolgende Switch-Node überprüft, ob für den kommenden Tag ein Termin vorhanden ist.

Falls kein Termin vorhanden ist, wird der Wecker auf 05:45 Uhr gestellt, um die Standard-Weckzeit beizubehalten.

Falls ein Termin existiert, wird der Flow fortgesetzt.

Mithilfe eines Change-Node wird die Weckzeit in Millisekunden seit der Epoch (Unix-Zeitstempel) umgewandelt. Dadurch kann sie im passenden Format an den Alexa-Wecker übergeben werden.

JSONata: $toMillis(msg.payload.Weckzeit)

Mit der folgenden Funktion-Node wird die Vergleichszeit für den Wecker berechnet und in msg.payload.comparisonTime gespeichert. Diese Zeit dient später dazu, die neue Weckzeit mit der aktuellen Einstellung des Weckers zu vergleichen.

let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1); // Morgen
let year = tomorrow.getFullYear();
let month = ("0" + (tomorrow.getMonth() + 1)).slice(-2);
let day = ("0" + tomorrow.getDate()).slice(-2);

// Setze die Weckzeit als 05:45:00
let comparisonTime = year + "-" + month + "-" + day + "T05:45:00";

msg.payload = {
    comparisonTime: comparisonTime,
    currentTime: msg.payload
};

return msg;

Der nachfolgende Switch-Node vergleicht die Weckzeit mit der Vergleichszeit. Falls die Weckzeit vor 05:45 Uhr liegt, wird ausgelöst, dass die Alexa Echos in bestimmten Räumen einen Hinweis geben, dass der Wecker umgestellt wurde. Diese Benachrichtigung sorgt dafür, dass der Nutzer informiert wird, wenn eine frühere Weckzeit festgelegt wurde.

Die erste Funktion-Node (Kein Termin, Weckzeit 05:45) stellt die Weckzeit auf 05:45 Uhr, wenn für den folgenden Tag kein Termin im Kalender eingetragen ist. Diese Funktion sorgt dafür, dass der Wecker auf die Standardzeit zurückgesetzt wird, falls keine frühere Weckzeit erforderlich ist. Die zweite und dritte Funktion-Node (Tag Morgen und Weckzeit stellen) sind identisch und konvertieren die Weckzeit in das Format, das der Alexa-Other-Node benötigt. Die Weckzeit wird dabei in msg.payload.currentTime.Weckzeit gespeichert und entsprechend formatiert, damit sie korrekt an die Alexa-Integration weitergegeben werden kann.

Function Kein Termin, Weckzeit 05:45

let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 2);

// Start- und Endzeit für den Folgetag korrekt formatieren
let year = tomorrow.getFullYear();
let month = ("0" + (tomorrow.getMonth() + 1)).slice(-2);
let day = ("0" + tomorrow.getDate()).slice(-2);

msg.payload = {
       wakeup_time: year + "-" + month + "-" + day + " 05:45:00+01:00",
        
    };

return msg;

Function Tag Morgen und Weckzeit stellen

let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 2);

// Start- und Endzeit für den Folgetag korrekt formatieren
let year = tomorrow.getFullYear();
let month = ("0" + (tomorrow.getMonth() + 1)).slice(-2);
let day = ("0" + tomorrow.getDate()).slice(-2);

msg.payload = {
       wakeup_time: msg.payload.currentTime.Weckzeit
        
    };

return msg;

Der Alexa-Other-Node ist in beiden Fällen identisch. Er passt eine vorhandene Benachrichtigung auf die berechnete Weckzeit an. Dadurch wird sichergestellt, dass die Benachrichtigung zur richtigen Zeit ausgelöst wird, basierend auf der neu festgelegten Weckzeit.

Die Notification ID habe ich mit einem Alexa-Other-Node und der Funktion Get Notification ermittelt. Dabei habe ich alle zurückgegebenen Objekte durchsucht, bis ich den Node mit der passenden Weckzeit (originalTime) gefunden habe. Die ID der Benachrichtigung entspricht dem letzten Teil des notificationIndex. Dieser Index wird genutzt, um die Benachrichtigung für die korrekte Weckzeit zu aktualisieren.

Um über Alexa die Information zu erhalten, dass der Wecker geändert wurde, wird mit einem Change-Node der msg.payload auf Millisekunden seit der Epoch (Unix-Zeitstempel) umgestellt. Anschließend wird eine Funktion „Wecker prüfen“ getriggert, die den aktuellen Status des Weckers überprüft. Die resultierende Information wird dann an den Alexa-Routine-Node übergeben, der die entsprechende Benachrichtigung auslöst, um den Nutzer zu informieren, dass der Wecker geändert wurde.

Function Wecker prüfen

<speak>    
<s><voice name="Marlene">Wecker prüfen!</voice></s>
</speak>

Anschließend übergebe ich mittels eines Change-Nodes einen Parameter zu Testzwecken an PushOver, um die Funktionsweise zu überprüfen. Dieser Schritt ist jedoch für die eigentliche Funktion nicht notwendig, weshalb ich hier nicht näher darauf eingehe.

31.03.2025: Nachdem ich heute Morgen im Urluab automatisch geweckt wurde habe die Funktion „Erstes Event des Tages“ und den nachfolgenden Flow überarbeitet.
Es wird nun auf Tagestermine Urlaub gepürft und der Wecker deaktiviert. Auch kann im Urlaub bei einem Termin vor 10Uhr und in der Terminbeschreibung z.B. „Weckzeit: 08:00“ steht der Wecker entsprechend gestellt werden. Die neue Funktion:

/*
Standard Notification:
1. Weckerzeit von Montag bis Freitag ist standardmäßig auf 05:45 Uhr gesetzt.
2. Wenn ein Termin im Kalender vor 06:45 Uhr liegt, wird die Weckzeit auf den Terminbeginn minus 1 Stunde gesetzt.
3. Wenn ein Ganztagstermin mit dem Betreff "Urlaub" vorhanden ist, wird der Wecker deaktiviert.
4. Wenn während des Urlaubs ein Termin vor 10:00 Uhr vorhanden ist und in der Beschreibung eine "Weckzeit: HH:MM" (z.B. "Weckzeit: 07:30") angegeben ist, wird der Wecker auf diese Zeit gesetzt.
5. Falls kein Termin vor 10:00 Uhr im Urlaub vorliegt und keine Weckzeit in der Beschreibung steht, wird der Wecker deaktiviert.
*/

// Hole das Array der Ereignisse
let events = msg.payload["calendar.personlich"].events;

// Falls keine Ereignisse vorhanden sind, eine Standardantwort zurückgeben
if (!events || events.length === 0) {
    msg.payload = { "message": "Keine Termine gefunden" };
    return msg;
}

// Datum für morgen berechnen
let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
let tomorrowStr = tomorrow.toISOString().split("T")[0];

// Prüfen, ob ein Ganztagestermin mit dem Namen "Urlaub" am morgigen Tag existiert (auch mehrtägige)
let hasVacation = events.some(event =>
    !event.start.includes("T") &&
    event.summary.toLowerCase().includes("urlaub") &&
    new Date(event.start) <= tomorrow && new Date(event.end) > tomorrow
);

// Prüfen, ob während des Urlaubs ein Termin vor 10:00 Uhr existiert
let earlyEvent = events.find(event =>
    event.start.includes("T") &&
    new Date(event.start).toISOString().split("T")[0] === tomorrowStr &&
    new Date(event.start).getHours() < 10
);

// Falls ein früher Termin existiert, Weckzeit aus Beschreibung holen (falls vorhanden)
let customWakeTime = null;
if (earlyEvent && earlyEvent.description) {
    let match = earlyEvent.description.match(/Weckzeit[:\s]*(\d{2}:\d{2})/i);
    if (match) {
        customWakeTime = match[1];
    }
}

// Falls es Urlaub ist, aber kein früher Termin mit Weckzeit in der Beschreibung
if (hasVacation && !customWakeTime) {
    msg.payload = { "Weckzeit": "deaktiviert" };
    return msg;
}

// Wenn eine Weckzeit gefunden wurde und diese vor dem Beginn des Termins liegt
if (customWakeTime) {
    let wakeDateTime = new Date(`${tomorrowStr}T${customWakeTime}:00`);
    let eventStartTime = new Date(earlyEvent.start);
    if (wakeDateTime < eventStartTime) {
        msg.payload = { "Weckzeit": `${tomorrowStr}T${customWakeTime}:00` }; // Benutze die Weckzeit aus der Beschreibung
        return msg;
    }
}

// Falls kein Termin vor 10:00 Uhr vorhanden ist, den Wecker auf 05:45 Uhr setzen
if (earlyEvent && !customWakeTime) {
    let defaultWakeTime = new Date(`${tomorrowStr}T05:45:00`);
    msg.payload = { "Weckzeit": defaultWakeTime.toISOString() };
    return msg;
}

// Falls ein Urlaubstag existiert und kein früher Termin vorhanden ist, den Wecker deaktivieren
if (hasVacation && !earlyEvent) {
    msg.payload = { "Weckzeit": "deaktiviert" };
    return msg;
}

// Filtern von Ganztagesterminen (ohne genaue Uhrzeit)
events = events.filter(event => event.start.includes("T"));

// Falls nach dem Filtern keine Ereignisse mehr übrig sind
if (events.length === 0) {
    msg.payload = { "message": "Keine relevanten Termine gefunden" };
    return msg;
}

// Das früheste Event finden
let earliestEvent = events.reduce((earliest, event) => {
    return new Date(event.start) < new Date(earliest.start) ? event : earliest;
}, events[0]);

// Sicherstellen, dass ein gültiges Startdatum existiert
if (!earliestEvent || !earliestEvent.start) {
    msg.payload = { "message": "Fehler: Kein gültiges Startdatum gefunden" };
    return msg;
}

// Startzeit berechnen
let startTime = new Date(earliestEvent.start);

// Eine Stunde abziehen
startTime.setUTCHours(startTime.getUTCHours() - 1);

// **Vergleich mit 05:45:00**
let checkTime = new Date(startTime);
checkTime.setHours(5, 45, 0, 0); // 05:45:00 setzen

// Falls Weckzeit nach 05:45:00 liegt, auf 05:45:00 setzen
if (startTime > checkTime) {
    startTime = checkTime;
}

// Formatierte Ausgabe (lokale Zeit)
let year = startTime.getFullYear();
let month = ("0" + (startTime.getMonth() + 1)).slice(-2);
let day = ("0" + startTime.getDate()).slice(-2);
let hours = ("0" + startTime.getHours()).slice(-2);
let minutes = ("0" + startTime.getMinutes()).slice(-2);
let seconds = ("0" + startTime.getSeconds()).slice(-2);

msg.payload = {
    "Weckzeit": `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`
};

return msg;

Dazu sind weitere Anpassungen im Flow notwendig, hier der aktuelle Export des Flows

[{"id":"7163fb6aea72c6c8","type":"inject","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 22 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":500,"wires":[["e17ca0122fc0615b"]]},{"id":"e17ca0122fc0615b","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Kalender und Datum ","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n    domain: \"calendar\",  // Calendar ist der Domain für die Kalenderabfragen\n    service: \"get_events\",  // Service, der die Termine abruft\n    data: {\n        entity_id: \"calendar.personlich\",  // Entität ersetzen!    \n        start_date_time: year + \"-\" + month + \"-\" + day + \" 00:00:00+01:00\",\n        end_date_time: year + \"-\" + month + \"-\" + day + \" 23:59:59+01:00\"\n    }\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":500,"wires":[["7c7f7ea65d804e4b"]]},{"id":"7c7f7ea65d804e4b","type":"api-call-service","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","server":"152c2aa.bcea4d5","version":7,"debugenabled":false,"action":"","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"results"}],"queue":"none","blockInputOverrides":false,"domain":"calendar","service":"get_events","x":490,"y":500,"wires":[["778586d24a57fa6e","a1d0143f4e8bd044"]]},{"id":"778586d24a57fa6e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Erstes Event des Tages","func":"/*\nStandard Notification:\n1. Weckerzeit von Montag bis Freitag ist standardmäßig auf 05:45 Uhr gesetzt.\n2. Wenn ein Termin im Kalender vor 06:45 Uhr liegt, wird die Weckzeit auf den Terminbeginn minus 1 Stunde gesetzt.\n3. Wenn ein Ganztagstermin mit dem Betreff \"Urlaub\" vorhanden ist, wird der Wecker deaktiviert.\n4. Wenn während des Urlaubs ein Termin vor 10:00 Uhr vorhanden ist und in der Beschreibung eine \"Weckzeit: HH:MM\" (z.B. \"Weckzeit: 07:30\") angegeben ist, wird der Wecker auf diese Zeit gesetzt.\n5. Falls kein Termin vor 10:00 Uhr im Urlaub vorliegt und keine Weckzeit in der Beschreibung steht, wird der Wecker deaktiviert.\n*/\n\n// Hole das Array der Ereignisse\nlet events = msg.payload[\"calendar.personlich\"].events;\n\n// Falls keine Ereignisse vorhanden sind, eine Standardantwort zurückgeben\nif (!events || events.length === 0) {\n    msg.payload = { \"message\": \"Keine Termine gefunden\" };\n    return msg;\n}\n\n// Datum für morgen berechnen\nlet tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1);\nlet tomorrowStr = tomorrow.toISOString().split(\"T\")[0];\n\n// Prüfen, ob ein Ganztagestermin mit dem Namen \"Urlaub\" am morgigen Tag existiert (auch mehrtägige)\nlet hasVacation = events.some(event =>\n    !event.start.includes(\"T\") &&\n    event.summary.toLowerCase().includes(\"urlaub\") &&\n    new Date(event.start) <= tomorrow && new Date(event.end) > tomorrow\n);\n\n// Prüfen, ob während des Urlaubs ein Termin vor 10:00 Uhr existiert\nlet earlyEvent = events.find(event =>\n    event.start.includes(\"T\") &&\n    new Date(event.start).toISOString().split(\"T\")[0] === tomorrowStr &&\n    new Date(event.start).getHours() < 10\n);\n\n// Falls ein früher Termin existiert, Weckzeit aus Beschreibung holen (falls vorhanden)\nlet customWakeTime = null;\nif (earlyEvent && earlyEvent.description) {\n    let match = earlyEvent.description.match(/Weckzeit[:\\s]*(\\d{2}:\\d{2})/i);\n    if (match) {\n        customWakeTime = match[1];\n    }\n}\n\n// Falls es Urlaub ist, aber kein früher Termin mit Weckzeit in der Beschreibung\nif (hasVacation && !customWakeTime) {\n    msg.payload = { \"Weckzeit\": \"deaktiviert\" };\n    return msg;\n}\n\n// Wenn eine Weckzeit gefunden wurde und diese vor dem Beginn des Termins liegt\nif (customWakeTime) {\n    let wakeDateTime = new Date(`${tomorrowStr}T${customWakeTime}:00`);\n    let eventStartTime = new Date(earlyEvent.start);\n    if (wakeDateTime < eventStartTime) {\n        msg.payload = { \"Weckzeit\": `${tomorrowStr}T${customWakeTime}:00` }; // Benutze die Weckzeit aus der Beschreibung\n        return msg;\n    }\n}\n\n// Falls kein Termin vor 10:00 Uhr vorhanden ist, den Wecker auf 05:45 Uhr setzen\nif (earlyEvent && !customWakeTime) {\n    let defaultWakeTime = new Date(`${tomorrowStr}T05:45:00`);\n    msg.payload = { \"Weckzeit\": defaultWakeTime.toISOString() };\n    return msg;\n}\n\n// Falls ein Urlaubstag existiert und kein früher Termin vorhanden ist, den Wecker deaktivieren\nif (hasVacation && !earlyEvent) {\n    msg.payload = { \"Weckzeit\": \"deaktiviert\" };\n    return msg;\n}\n\n// Filtern von Ganztagesterminen (ohne genaue Uhrzeit)\nevents = events.filter(event => event.start.includes(\"T\"));\n\n// Falls nach dem Filtern keine Ereignisse mehr übrig sind\nif (events.length === 0) {\n    msg.payload = { \"message\": \"Keine relevanten Termine gefunden\" };\n    return msg;\n}\n\n// Das früheste Event finden\nlet earliestEvent = events.reduce((earliest, event) => {\n    return new Date(event.start) < new Date(earliest.start) ? event : earliest;\n}, events[0]);\n\n// Sicherstellen, dass ein gültiges Startdatum existiert\nif (!earliestEvent || !earliestEvent.start) {\n    msg.payload = { \"message\": \"Fehler: Kein gültiges Startdatum gefunden\" };\n    return msg;\n}\n\n// Startzeit berechnen\nlet startTime = new Date(earliestEvent.start);\n\n// Eine Stunde abziehen\nstartTime.setUTCHours(startTime.getUTCHours() - 1);\n\n// **Vergleich mit 05:45:00**\nlet checkTime = new Date(startTime);\ncheckTime.setHours(5, 45, 0, 0); // 05:45:00 setzen\n\n// Falls Weckzeit nach 05:45:00 liegt, auf 05:45:00 setzen\nif (startTime > checkTime) {\n    startTime = checkTime;\n}\n\n// Formatierte Ausgabe (lokale Zeit)\nlet year = startTime.getFullYear();\nlet month = (\"0\" + (startTime.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + startTime.getDate()).slice(-2);\nlet hours = (\"0\" + startTime.getHours()).slice(-2);\nlet minutes = (\"0\" + startTime.getMinutes()).slice(-2);\nlet seconds = (\"0\" + startTime.getSeconds()).slice(-2);\n\nmsg.payload = {\n    \"Weckzeit\": `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":500,"wires":[["871c28861baaf1bd","b099ce5637e7f69d"]]},{"id":"a1d0143f4e8bd044","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 18","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":500,"y":400,"wires":[]},{"id":"871c28861baaf1bd","type":"switch","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","property":"payload.message","propertyType":"msg","rules":[{"t":"eq","v":"Keine relevanten Termine gefunden","vt":"str"},{"t":"neq","v":"Keine relevanten Termine gefunden","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":870,"y":500,"wires":[["cd9ba4bb9eed555e","6c93245287527dd3"],["14340f4b0520314e","90cbc21770698577"]]},{"id":"b099ce5637e7f69d","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 17","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":400,"wires":[]},{"id":"cd9ba4bb9eed555e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Kein Termin, Weckzeit 05:45","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Lokale Zeitzone berechnen\nlet offset = -tomorrow.getTimezoneOffset() / 60; // Gibt +1 oder +2 zurück\nlet timezone = (offset >= 0 ? \"+\" : \"\") + String(offset).padStart(2, \"0\") + \":00\";\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n    wakeup_time: `${year}-${month}-${day} 05:45:00${timezone}`\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2220,"y":400,"wires":[["f49346bac151b510"]]},{"id":"14340f4b0520314e","type":"switch","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","property":"payload.Weckzeit","propertyType":"msg","rules":[{"t":"neq","v":"deaktiviert","vt":"str"},{"t":"eq","v":"deaktiviert","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1150,"y":500,"wires":[["7328ebd9239d43b6"],["8f6a27c576e35c89"]]},{"id":"90cbc21770698577","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 13","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":560,"wires":[]},{"id":"6c93245287527dd3","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 16","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1010,"y":400,"wires":[]},{"id":"f49346bac151b510","type":"alexa-remote-other","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","config":{"option":"changeNotification","value":{"notification":{"type":"str","value":"775ac127-c9dc-33fc-9e5c-1d34933e3d2e"},"label":{"type":"str","value":""},"time":{"type":"msg","value":"payload.wakeup_time"},"status":{"type":"str","value":"ON"},"sound":{"type":"json","value":""}}},"x":2630,"y":440,"wires":[["37cd42ef20bcd167"]]},{"id":"7328ebd9239d43b6","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"timestamp","pt":"msg","to":"$toMillis(msg.payload.Weckzeit)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1640,"y":500,"wires":[["4ea98fc36c5f900e"]]},{"id":"8f6a27c576e35c89","type":"alexa-remote-other","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","config":{"option":"changeNotification","value":{"notification":{"type":"str","value":"775ac127-c9dc-33fc-9e5c-1d34933e3d2e"},"label":{"type":"str","value":""},"time":{"type":"str","value":""},"status":{"type":"str","value":"OFF"},"sound":{"type":"json","value":""}}},"x":1390,"y":580,"wires":[["dc29d9f56c451de5"]]},{"id":"497e4996ccf91008","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Tag Morgen und Weckzeit stellen","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n       wakeup_time: msg.payload.currentTime.Weckzeit\n        \n    };\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":440,"wires":[["f49346bac151b510"]]},{"id":"37cd42ef20bcd167","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"priority","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"sound","pt":"msg","to":"bike","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"\"Weckzeit: \" & msg.payload.originalTime","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"Weckzeit","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":2870,"y":520,"wires":[["ef8b3e005be0bff7"]]},{"id":"4ea98fc36c5f900e","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"function 5","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1); // Morgen\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\n// Setze die Weckzeit als 05:45:00\nlet comparisonTime = year + \"-\" + month + \"-\" + day + \"T05:45:00\";\n\nmsg.payload = {\n    comparisonTime: comparisonTime,\n    currentTime: msg.payload\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1820,"y":500,"wires":[["fcc29179a38f7aca"]]},{"id":"dc29d9f56c451de5","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 15","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1580,"y":580,"wires":[]},{"id":"fcc29179a38f7aca","type":"switch","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","property":"payload.currentTime.Weckzeit","propertyType":"msg","rules":[{"t":"gte","v":"payload.comparisonTime","vt":"msg"},{"t":"lt","v":"payload.comparisonTime","vt":"msg"}],"checkall":"true","repair":false,"outputs":2,"x":1970,"y":500,"wires":[["497e4996ccf91008"],["3ba26f5c9ecaadab","f83a0bb657ffeb87"]]},{"id":"3f024e16db6f6c40","type":"alexa-remote-other","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","config":{"option":"changeNotification","value":{"notification":{"type":"str","value":"775ac127-c9dc-33fc-9e5c-1d34933e3d2e"},"label":{"type":"str","value":""},"time":{"type":"msg","value":"payload.wakeup_time"},"status":{"type":"str","value":"ON"},"sound":{"type":"json","value":""}}},"x":2610,"y":600,"wires":[["37cd42ef20bcd167"]]},{"id":"ef8b3e005be0bff7","type":"link out","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"link out Pushover ","mode":"link","links":["5b52c69bf84ce7c3"],"x":3005,"y":520,"wires":[]},{"id":"3ba26f5c9ecaadab","type":"function","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Tag Morgen und Weckzeit stellen","func":"let tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 2);\n\n// Start- und Endzeit für den Folgetag korrekt formatieren\nlet year = tomorrow.getFullYear();\nlet month = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet day = (\"0\" + tomorrow.getDate()).slice(-2);\n\nmsg.payload = {\n       wakeup_time: msg.payload.currentTime.Weckzeit\n            };\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":600,"wires":[["3f024e16db6f6c40","108ed85e1ac79f60"]]},{"id":"f83a0bb657ffeb87","type":"change","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":2190,"y":540,"wires":[["103c800dd6618952"]]},{"id":"108ed85e1ac79f60","type":"debug","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"debug 14","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2390,"y":700,"wires":[]},{"id":"103c800dd6618952","type":"template","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"Wecker prüfen.","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<speak>    \n<s><voice name=\"Marlene\">Wecker prüfen!</voice></s>\n</speak>","output":"str","x":2400,"y":540,"wires":[["2f17418f09852317"]]},{"id":"2f17418f09852317","type":"alexa-remote-routine","z":"f1a56049.b84ac","g":"ee8c1d99a9387759","name":"","account":"07016f8877dcae6d","routineNode":{"type":"speak","payload":{"type":"ssml","text":{"type":"msg","value":"payload"},"devices":["G0911B05941206GK","90F00818707508K1","G091JJ1314840ABS"]}},"x":2600,"y":540,"wires":[[]]},{"id":"152c2aa.bcea4d5","type":"server","name":"Home Assistant Qli","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false},{"id":"07016f8877dcae6d","type":"alexa-remote-account","name":"","authMethod":"proxy","proxyOwnIp":"192.168.177.2","proxyPort":"3456","cookieFile":"/homeassistant/node-red/alexa/alexa.txt","refreshInterval":"3","alexaServiceHost":"layla.amazon.de","pushDispatchHost":"","amazonPage":"amazon.de","acceptLanguage":"de-DE","onKeywordInLanguage":"on","userAgent":"","usePushConnection":"on","autoInit":"on","autoQueryActivityOnTrigger":"off"}]
Veröffentlicht am
Kategorisiert in Allgemein

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert