Der selbständige HomeKit Multitasking Wecker – Das Ende launenhafter HomeKit-Zeitschaltungen
HomeKit funktioniert nach meinen Erfahrungen umso zuverlässiger, je weniger (komplexe) Automationen über diverse Steuerzentralen ausgeführt werden müssen. In den Jahren hatte ich wiederholt Probleme mit zeitbasierten Automationen, die ich inzwischen nahezu vollständig aus HomeKit herausgenommen habe.
Im Folgenden werde ich anhand eines praktischen Beispiels einer zeitbasierten Heizungssteuerung eine alternative Zeitschaltungmöglichkeit im RavenSystem erläutern.
In HomeKit gibt es bekanntermaßen Zeitautomationen nach folgenden Prinzipien:
- Schalte beliebige Geräte/Szenen ab Datum um Uhrzeit Stunde:Minute und wiederhole diese Zeitautomation wahlweise wöchentlich, täglich, stündlich, minütlich oder nie.
- Führe beliebige Automationen statisch innerhalb einer Zeitdauer zwischen Stunde:Minute und Stunde:Minute aus.
- Führe beliebige Automationen dynamisch vor, zwischen oder nach der örtlichen Sonnenauf-/untergangszeit wahlweise inklusive wählbarem Zeitversatz aus.
Das ist zwar ausreichend gut über die Home App und diverse Drittanbieterlösungen einzurichten, jedoch wurden in meinem Fall manche Automationen willkürlich auch gerne mal von HomeKit unterschlagen, was mitunter sehr ärgerliche Konsequenzen besonders zu nachtschlafender Zeit haben kann.
In RavenSystem haben wir ja bereits frei konfigurierbare Timer kennengelernt, die nach beliebiger Zeit in den Grundzustand zurückschalten und damit schonmal eine Zeitdauer definieren können. Zudem erlaubt RavenSystem sogenannte "Timetable Actions", durch die konkrete statische Datums-, Wochentags- und/oder Uhrzeit-Angaben beliebige Schaltzustände bei beliebigen internen Service Types auslösen können.
ESPs verfügen "ab Werk" zwar über keine batteriegepufferte Uhr (RTC), jedoch können sie vordefinierte sogenannte NTP (Network Time Protocol) Server nach der Uhrzeit fragen. Wir kennen das u.a. aus unseren Computern, bei deren Einstellungsoption "Datum und Uhrzeit automatisch einstellen" die Eingabe einer Serveradresse wie bspw. time.apple.com möglich ist.
Beim ESP ist das nicht anders. Wir brauchen diesem in dessen optionaler "General Configuration" lediglich per NTP Server Key "ntp" eine Serveradresse nach unserer Wahl und zudem die korrekte Zeitzone per Key "tz" mitteilen und schon weiß der ESP, was die Stunde schlägt. Das sieht dann ausschnittweise so aus:
Hierzu sei erwähnt, dass auch ganz ohne Angabe eines NTP Servers standardmäßig bereits ein Solcher in Raven vorgegeben ist. Über pool.ntp.org kann jeder Raven ESP also bereits nach dem ersten Booten mit der Zeit gehen. Der Vorteil einer selbst gewählten Adresse ist eine integrierte Fallback-Funktion: Sollte der im Beispiel genannte Apple Server mal nicht erreichbar sein, lässt der ESP sich automatisch von seinem Standardserver die Zeit flüstern.
Die Zeitzonenangabe sieht zugegebenermaßen ordentlich kryptisch aus. Es handelt sich beim benötigten Format um eine sogenannte POSIX Zeitangabe, die wir für unseren Standort nicht selbst erstellen müssen, sondern sehr leicht über https://github.com/nayarsystem…_db/blob/master/zones.csv ermitteln und per Copy/Paste nach oben dargestelltem Prinzip einsetzen können. Somit weiß der ESP die korrekte Uhrzeit für unseren Standort.
Das besagte Beispiel einer einfachen Heizautomation geht von 3 Schaltzuständen aus (Weitere sind natürlich möglich):
- Tägliche Standby-Temperatur
- Tägliche Nachtabsenkung
- Temperaturanhebung nur werktags
Hierfür sollen zwei einfache Schalter "Nachtabsenkung" und "Morgenanhebung" entsprechende Heizungsszenen in HomeKit durch simple Automationen schalten.
- Wenn Nachtabsenkung AN -> Heizungsszene Nachttemperaturen
- Wenn Nachtabsenkung AUS -> Heizungsszene Standby-Temperaturen
- Wenn Morgenanhebung AN -> Heizungsszene Morgentemperaturen
- Wenn Morgenanhebung AUS -> Heizungsszene Standby-Temperaturen
Die Schalter selbst sind bekanntermaßen simpelst für HomeKit im ESP wie folgt anzulegen. Zusammen mit der anfangs vordefinierten "General Configuration" ergibt das:
Der komplette Zeitplan soll nun im ESP festgelegt und von diesem ausgeführt werden. Die folgenden Anforderungen sollen dabei umgesetzt werden:
- Die Nachtabsenkung soll täglich zwischen 23:45 bis 6:30 ausgeführt werden.
- Die Morgenanhebung soll werktags zwischen 7:45 bis 9:15 ausgeführt werden.
Hierfür müssen wir dem ESP innerhalb seiner "General Configuration" also noch mitteilen, welche Aktionen wann ausgeführt werden sollen.
Ich beginne mit den "Device Actions", von denen bereits einige in RavenSystem zwischen "0" und "7" vordefiniert sind. Diese wollen wir allerdings nicht nutzen, sondern statt dessen einfache "Service Notifications" zum Ein- und Ausschalten der besagten Schalter "Nachtabsenkung" und "Morgenanhebung" selbst definieren. Das ist ohne Weiteres möglich, da für Timetable Actions bis zur Zahl "50" eigene Definitionen vorgenommen werden können. Es bleiben abzüglich der besagten vordefinierten 7 Device Action immerhin noch 43 freie Definitionen übrig.
Im Beispiel benötigen wir allerdings weitaus weniger, denn besagte zwei Schalter sollen jeweils Ein- und Ausgeschaltet werden, weshalb hierfür 4 Definitionen reichen. Das korrekte Format solcher Actions kennen wir bereits aus meinen vorherigen Projektbeschreibungen. Für das heutige Beispiel werden also 4 Actions diesmal in die "General Configuration" eingetragen, die die zwei besagten virtuellen Temperaturschalter schalten sollen:
// TimeTable Action Nachtabsenkung (Schalter 1) aktivieren
"10":{"m":[[1,1]]},
// TimeTable Action Nachtabsenkung (Schalter 1) deaktivieren
"11":{"m":[[1,0]]},
// TimeTable Action Morgenanhebung (Schalter 2) aktivieren
"12":{"m":[[2,1]]},
// TimeTable Action Morgenanhebung (Schalter 2) deaktivieren
"13":{"m":[[2,0]]},
Fehlen noch die Schaltzeiten, die durch besagte "Timetable Actions" ebenfalls in der "General Configuration" eingetragen werden müssen. Hierfür stehen verschiedene Optionen zur Verfügung. Wie erwähnt soll die Nachtabsenkung jeden Tag zu festen Zeiten ein- und wieder ausschalten. Dazu benötigen wir also ausschließlich eine Uhrzeitangabe und können auf Wochentags- und Datumsangaben verzichten. Das Format für die Timetable Actions ist bestimmt durch die Nummer der einleitenden Aktion, die wir im vorherigen Schritt bereits definiert haben. Für das Einschalten der Nachtabsenkung beginnen wir also mit einer 10, gefolgt von der Stundenangabe 23 Uhr, gefolgt von der Minutenangabe 45 Minuten, das Ganze kommagetrennt:
Ausschalten soll die Absenkung um 6:30:
Weiter geht’s mit der Morgenanhebung. Hier soll zusätzlich der Wochentag berücksichtigt werden. Unter der Annahme, dass am Wochenende die Anhebung zu unterschiedlichen Zeiten manuell ausgeführt wird, soll also nur von Montag bis Freitag die Zeitschaltung erfolgen und am Wochenende ruhen. Nach dem vorherigen Prinzip brauchen wir also noch eine Wochentagsangabe, die ganz einfach an die Uhrzeit angehängt wird. Dabei beginnt die Woche mit dem Montag = 1. Schalter 2 für die Anhebung soll hierbei täglich werktags um 7:45 eingeschaltet werden:
// Morgenanhebung aktivieren um 7:45 Montags
[12,7,45,1],
// Morgenanhebung aktivieren um 7:45 Dienstags
[12,7,45,2],
// Morgenanhebung aktivieren um 7:45 Mittwochs
[12,7,45,3],
// Morgenanhebung aktivieren um 7:45 Donnerstags
[12,7,45,4],
// Morgenanhebung aktivieren um 7:45 Freitags
[12,7,45,5]
Das erneute Herunterregeln erfolgt an denselben Wochentagen jeweils um 9:15. Den nachfolgenden Codeschnipsel könnten wir uns im Falle der gleichen Zeiträume auch sparen und den Morgenanhebungsschalter kurzerhand zum Timer umdefinierten, der sich dann seinerseits nach 90 Minuten selbsttätig abschaltet. Nichtsdestotrotz soll diesmal eine Uhrzeit ausschalten, wodurch wir bei Bedarf verschiedene Schaltzeiten und Schaltdauern pro Wochentag realisieren könnten:
// Morgenanhebung deaktivieren um 9:15 Montags
[13,9,15,1],
// Morgenanhebung deaktivieren um 9:15 Dienstags
[13,9,15,2],
// Morgenanhebung deaktivieren um 9:15 Mittwochs
[13,9,15,3],
// Morgenanhebung deaktivieren um 9:15 Donnerstags
[13,9,15,4],
// Morgenanhebung deaktivieren um 9:15 Freitags
[13,9,15,5]
Fertig ist die ESP basierte Heizungs-Zeitschaltung:
{"c":
{"z":0,
// NTP Server
"ntp":"time.apple.com",
// POSIX Zeitzone Europe/Berlin
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
"tz":"CET-1CEST,M3.5.0,M10.5.0/3",
// TimeTable Action Nachtabsenkung (Schalter 1) aktivieren
"10":{"m":[[1,1]]},
// TimeTable Action Nachtabsenkung (Schalter 1) deaktivieren
"11":{"m":[[1,0]]},
// TimeTable Action Morgenanhebung (Schalter 2) aktivieren
"12":{"m":[[2,1]]},
// TimeTable Action Morgenanhebung (Schalter 2) deaktivieren
"13":{"m":[[2,0]]},
// Anfang der Timetable-Zeitschaltungen
"tt":[
// Nachtabsenkung aktivieren um 23:45
[10,23,45],
// Nachtabsenkung deaktivieren um 6:30
[11,6,30],
// Morgenanhebung aktivieren um 7:45 Montags
[12,7,45,1],
// Morgenanhebung aktivieren um 7:45 Dienstags
[12,7,45,2],
// Morgenanhebung aktivieren um 7:45 Mittwochs
[12,7,45,3],
// Morgenanhebung aktivieren um 7:45 Donnerstags
[12,7,45,4],
// Morgenanhebung aktivieren um 7:45 Freitags
[12,7,45,5],
// Morgenanhebung deaktivieren um 9:15 Montags
[13,9,15,1],
// Morgenanhebung deaktivieren um 9:15 Dienstags
[13,9,15,2],
// Morgenanhebung deaktivieren um 9:15 Mittwochs
[13,9,15,3],
// Morgenanhebung deaktivieren um 9:15 Donnerstags
[13,9,15,4],
// Morgenanhebung deaktivieren um 9:15 Freitags
[13,9,15,5]
]
},
"a":[
// Schalter Nachtabsenkung (1)
{"t":1,
"0":{"m":[
[7001,-10001]
]},
"1":{"m":[
[7001,0],
[7001,-10000],
]}},
// Schalter Morgenanhebung (2)
{"t":1}
]
}
Alles anzeigen
Oder komprimiert und damit Speicheroptmiert:
{"c":{"z":0,"ntp":"time.apple.com","tz":"CET-1CEST,M3.5.0,M10.5.0/3","10":{"m":[[1,1]]},"11":{"m":[[1,0]]},"12":{"m":[[2,1]]},"13":{"m":[[2,0]]},"tt":[[10,23,45],[11,6,30],[12,7,45,1],[12,7,45,2],[12,7,45,3],[12,7,45,4],[12,7,45,5],[13,9,15,1],[13,9,15,2],[13,9,15,3],[13,9,15,4],[13,9,15,5]]},"a":[{"t":1,"0":{"m":[[7001,-10001]]},"1":{"m":[[7001,0],[7001,-10000],]}},{"t":1}]}
Hinzugefügt wurde für die Nachtabsenkung noch eine bereits beim Blink-Generator eingesetzte Option, den Schalter für die Morgenanhebung auszuschalten und komplett zu deaktivieren, um versehentliches Schaltens desselben während der Nachtabsenkung auszuschließen.
Ich sehe spätestens an dieser Stelle meines Beitrag einige Forumsteilnehmende bereits wieder mit dem Kopf schütteln, weil all die beschriebenen Zeitschaltungen viel "einfacher" in der Home App als Automationen angelegt werden können oder weil diverse Heizthermostat-Anbieter in ihren Apps noch schönere grafische Zeitautomationstabellen zur Verfügung stellen. Die Gründe für ein angestrebtes Outsourcing diverser Automationen aus HomeKit sind jedoch vielfältig und von den persönlichen Erfahrungen abhängig. Ich zumindest bin seit Monaten beeindruckt vom schweizerischen Timing meiner ESP-Zeitschaltungen im Vergleich zu den vorher durch HomeKit ausgeführten Automationen. Ich erahne außerdem durch die "Automationsentlastung" von HomeKit eine insgesamte verbesserte Stabilität meines gesamten Systems.
Einer geht noch:
Das obige Beispiel folgt in seiner Einfachheit einer starren Zeitlogik, die nicht unbedingt immer lebensnah ist. Wenn mein Heim mal mehrere Tage verwaist, sollten die Automationen natürlich ausgesetzt werden. Ich könnte nun wieder in HomeKit die oben genannten, bewusst einfachst gehaltenen Heizungsszenen-Automationen durch Bedingungen erweitern, also wenn loonypac nicht daheim -> dann schalte nicht die Morgenanhebungs-Szene, jedoch wäre es schöner, wenn ich bei Bedarf manuell die Zeitautomationen deaktivieren könnte – im optimalen Fall per zusätzlicher HomeKit Schalter für alle Wochentage samt der Nachtabsenkung.
In der Tat habe ich eine solche Schaltmöglichkeit ergänzt, was es nun möglich macht, dass ich für die verschiedensten Bedürfnisse beliebige Tagesautomationen zu ebenso beliebigen Zeiten de-/aktiveren kann, was die Schaltoberfläche laut Abbildung zu Anfang des Beitrags wiederspiegelt.
// Multitasking Wecker in HomeKit wählbar
{"c":
{"z":0,
// NTP Server
"ntp":"time.apple.com",
// POSIX Zeitzone Europe/Berlin
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
"tz":"CET-1CEST,M3.5.0,M10.5.0/3",
// TimeTable Actions Morgenanhebung Mo bis So aktivieren
"11":{"m":[[1,2],[1,1]]},
"12":{"m":[[2,2],[2,1]]},
"13":{"m":[[3,2],[3,1]]},
"14":{"m":[[4,2],[4,1]]},
"15":{"m":[[5,2],[5,1]]},
"16":{"m":[[6,2],[6,1]]},
"17":{"m":[[7,2],[7,1]]},
// TimeTable Actions Morgenanhebung Mo bis So deaktivieren
"21":{"m":[[1,3],[1,0]]},
"22":{"m":[[2,3],[2,0]]},
"23":{"m":[[3,3],[3,0]]},
"24":{"m":[[4,3],[4,0]]},
"25":{"m":[[5,3],[5,0]]},
"26":{"m":[[6,3],[6,0]]},
"27":{"m":[[7,3],[7,0]]},
// TimeTable Action Nachtabsenkung aktivieren
"30":{"m":[[8,2],[8,1]]},
// TimeTable Action Nachtabsenkung deaktivieren
"31":{"m":[[8,3],[8,0]]},
// Anfang der Timetable-Zeitschaltungen
"tt":[
// Morgenanhebung aktivieren um 7:45 Montags
[11,7,45,1],
// Morgenanhebung aktivieren um 7:45 Dienstags
[12,7,45,2],
// Morgenanhebung aktivieren um 7:45 Mittwochs
[13,7,45,3],
// Morgenanhebung aktivieren um 7:45 Donnerstags
[14,7,45,4],
// Morgenanhebung aktivieren um 7:45 Freitags
[15,7,45,5],
// Morgenanhebung aktivieren um 9:45 Samstags
[16,9,45,6],
// Morgenanhebung aktivieren um 9:45 Sonntags
[17,9,45,7],
// Morgenanhebung deaktivieren um 9:15 Montags
[21,9,15,1],
// Morgenanhebung deaktivieren um 9:15 Dienstags
[22,9,15,2],
// Morgenanhebung deaktivieren um 9:15 Mittwochs
[23,9,15,3],
// Morgenanhebung deaktivieren um 9:15 Donnerstags
[24,9,15,4],
// Morgenanhebung deaktivieren um 9:15 Freitags
[25,9,15,5],
// Morgenanhebung deaktivieren um 11:15 Samstags
[26,11,15,6],
// Morgenanhebung deaktivieren um 11:15 Sonntags
[27,11,15,7],
// Nachtabsenkung aktivieren täglich um 23:45
[30,23,45],
// Nachtabsenkung deaktivieren täglich um 6:30
[31,6,30]
]
},
"a":[
// Unsichtbarer Auslöser Morgenanhebung Mo bis So
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},
// Unsichtbarer Auslöser Nachtabsenkung
{"h":0,"0":{"m":[[18,0]]},"1":{"m":[[18,1]]}},
// Einzelautomationen Morgenanhebung Mo bis So
{"xa":0,"s":1,"0":{"m":[[1,-10000]]},"1":{"m":[[1,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[2,-10000]]},"1":{"m":[[2,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[3,-10000]]},"1":{"m":[[3,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[4,-10000]]},"1":{"m":[[4,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[5,-10000]]},"1":{"m":[[5,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[6,-10000]]},"1":{"m":[[6,-10001]]}},
{"xa":0,"s":1,"0":{"m":[[7,-10000]]},"1":{"m":[[7,-10001]]}},
// Einzelautomationen Nachtabsenkung
{"xa":0,"s":1,"0":{"m":[[8,-10000]]},"1":{"m":[[8,-10001]]}},
// Schalter Morgenanhebung (17)
{"t":1},
// Schalter Nachtabsenkung (18)
{"0":{"m":[[-1,-10001]]},"1":{"m":[[-1,0],[-1,-10000],]}}
]
}
Alles anzeigen
Oder komprimiert:
{"c":{"z":0,"ntp":"time.apple.com","tz":"CET-1CEST,M3.5.0,M10.5.0/3","11":{"m":[[1,2],[1,1]]},"12":{"m":[[2,2],[2,1]]},"13":{"m":[[3,2],[3,1]]},"14":{"m":[[4,2],[4,1]]},"15":{"m":[[5,2],[5,1]]},"16":{"m":[[6,2],[6,1]]},"17":{"m":[[7,2],[7,1]]},"21":{"m":[[1,3],[1,0]]},"22":{"m":[[2,3],[2,0]]},"23":{"m":[[3,3],[3,0]]},"24":{"m":[[4,3],[4,0]]},"25":{"m":[[5,3],[5,0]]},"26":{"m":[[6,3],[6,0]]},"27":{"m":[[7,3],[7,0]]},"30":{"m":[[8,2],[8,1]]},"31":{"m":[[8,3],[8,0]]},"tt":[[11,7,45,1],[12,7,45,2],[13,7,45,3],[14,7,45,4],[15,7,45,5],[16,9,45,6],[17,9,45,7],[21,9,15,1],[22,9,15,2],[23,9,15,3],[24,9,15,4],[25,9,15,5],[26,11,15,6],[27,11,15,7],[30,23,45],[31,6,30]]},"a":[{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[17,0]]},"1":{"m":[[17,1]]}},{"h":0,"0":{"m":[[18,0]]},"1":{"m":[[18,1]]}},{"xa":0,"s":1,"0":{"m":[[1,-10000]]},"1":{"m":[[1,-10001]]}},{"xa":0,"s":1,"0":{"m":[[2,-10000]]},"1":{"m":[[2,-10001]]}},{"xa":0,"s":1,"0":{"m":[[3,-10000]]},"1":{"m":[[3,-10001]]}},{"xa":0,"s":1,"0":{"m":[[4,-10000]]},"1":{"m":[[4,-10001]]}},{"xa":0,"s":1,"0":{"m":[[5,-10000]]},"1":{"m":[[5,-10001]]}},{"xa":0,"s":1,"0":{"m":[[6,-10000]]},"1":{"m":[[6,-10001]]}},{"xa":0,"s":1,"0":{"m":[[7,-10000]]},"1":{"m":[[7,-10001]]}},{"xa":0,"s":1,"0":{"m":[[8,-10000]]},"1":{"m":[[8,-10001]]}},{"t":1},{"0":{"m":[[-1,-10001]]},"1":{"m":[[-1,0],[-1,-10000],]}}]}