HomeKit lernt abzubiegen – Der flexible HomeKit Blinkgenerator
(Alle Schaltungen werden komplett innerhalb eines ESP ausgeführt. Keine HomeKit-Automationen oder Kurzbefehle!)
*** Wer nicht lange lesen möchte und vorab einfach mal einen ESP mit dem Blink-Generator testen möchte, kann zum Ende dieses Beitrags eine fertige bin-Datei laden und auf seinen ESP flashen. ***
Das klassische Blinken "ab Werk" kann HomeKit bekanntlich bis heute nicht, ohne dass man dazu mehr oder minder große Umwege beschreiten muss. Dabei kann es immer mal wieder durchaus hilfreich sein, um per beliebiger blinkender Lampenauswahl – schließlich hängen in allen Räumen irgendwelche smarten Lampen – auf irgendetwas aufmerksam zu machen, wie z.B. das offene Fenster, sobald man die Haustür öffnet.
Ich selbst habe vor Jahren eine Blinkmöglichkeit vorgestellt, die vollständig innerhalb von HomeKit ausgeführt wird. Die funktioniert zwar mehr oder weniger gut, beansprucht jedoch HomeKit ziemlich, da jeweils 2 Automationen jede Sekunde über einen unbekannten Zeitraum ausgewertet und Schaltungen ausgeführt werden werden müssen.
RavenSystem kann HomeKit spürbar entlasten und die Auswertung der Automationen übernehmen, während HomeKit dann nur noch schalten muss. Baut man sich per RavenSystem gar eine eigene Lampe, kann man sogar das Schalten des Lichts aus HomeKit outsourcen und bekommt ein waschechtes integriertes Blinklicht.
Solch ein HomeKit-Blinkkgenerator in 2-Kanalausführung soll in diesem Beitrag grundlegend Step by Step erklärt werden. Er funktioniert sowohl Standalone, um in HomeKit Lampen und/oder Szenen im Sekundentakt ein- und auszuschalten bzw. irgendetwas hin- und herzuschalten. Das Skript selbst kann allerdings als Codeschnispsel auch in ein Lampenskript integriert werden, um dann die Lampe direkt per ESP blinken zu lassen. Übrigens sollten sich auf diesem Wege auch Lampenschaltende Raven-Shellys um eine Blinkfunktion erweitern lassen.
Die folgende Schaltidee ist identisch mit meiner damaligen HomeKit-Lösung, die ich mithilfe der Geschwister Flip und Flop umgesetzt hatte und deren Namen ich in gebührender ehrfürchtiger Verneigung aus der klassischen Flipflop-Schaltung entliehen habe. Dort ist treffenderweise die Rede von "bistabilen Kippgliedern" (welch großartige Begrifflichkeit!), die wir in RavenSystem perfekt und einfach durch 2 sich gegenseitig schaltende Schalter, genauer gesagt zwei sich gegenseitig schaltende Timerschalter umsetzen können.
Ich beginne also mit einem Ausgangsskript, das 2 inzwischen altbekannte Timer in HomeKit erzeugt, die sich jeweils nach einer Sekunde, nachdem sie eingeschaltet wurden, selbständig wieder ausschalten:
{"a":[{"t":1,"i":1},{"t":1,"i":1}]}
Die Gebrüder Flip und Flop haben soeben das Licht der virtuellen HomeKit-Welt erblickt, allerdings leben sie im derzeitigen Stadium regelrecht aneinander vorbei. Das wollen wir ganz schnell ändern durch die ebenfalls bereits vorgestellten "Service Notifications", die beiden Geschwisterchen eine einfache Kommunikation ermöglichen nach folgendem Drehbuch:
Flip (sich einschaltend) |
Hallo liebe HomeKit-Welt, ich bin Flip und ich schalte mich grad ein, damit ihr irgendwas automatisieren könnt.
Aber seid gewarnt, ich schalte mich grundsätzlich in 1 Sekunde wieder aus! |
Flip (sich ausschaltend) |
Hallo liebe HomeKit-Welt, ich schalte mich grad aus, damit ihr irgendwas automatisieren könnt. Flop, mein Lieber, übernimm du bitte! |
Flop (sich einschaltend) |
Hey Flip, mein Lieber, das mache ich doch gern! Hallo liebe HomeKit-Welt, ich bin Flop und ich schalte mich grad ein, damit ihr irgendwas automatisieren könnt. Aber seid gewarnt, ich schalte mich grundsätzlich in 1 Sekunde wieder aus!
|
Flop (sich ausschaltend) |
Hallo liebe HomeKit-Welt, ich schalte mich grad aus, damit ihr irgendwas automatisieren könnt. Flip, mein Lieber, übernimm du bitte! |
|
(Endlose Dialog-Fortsetzung, bis irgendjemand Einhalt gebietet) |
Dramaturgisch gibt die Unterhaltung zwischen Flip und Flop wenig her und taugt bestenfalls für experimentelles Theater. Das muss uns aber nicht stören, da wir den extrem eintönigen Dialog nicht ertragen müssen, sondern ihn gewinnbringend für unser Schaltvorhaben einsetzen werden. Dazu müssen wir nur Flip, wenn er sich ausschaltet, einen Fingerzeig an Flop senden lassen, damit sich dieser einschaltet. Umgekehrt gilt das gleiche für Flop, der Flip zum Einschalten anstößt, sobald er selbst sich ausschaltet. Wir erinnern uns: Flip und Flop müssen dazu jeweils wissen, an welcher Stelle sie im Skript stehen und sie sollen nur beim Ausschalten dem jeweiligen Gegenüber einen verständlichen Einschaltbefehl mitteilen.
Flip ist die Nummer 1, Flop die Nummer 2. Die Anweisung respektive "Service Notification", die beide vom Range eines Schalters verstehen, sind (u.a.) "0" und "1".
Im Skript ergibt das folgenden Dialog-Codeschnipsel für "Hey mein Lieber, schalte dich ein!"
{"m":{[2,1]}} // sagt Flip zum Zweiten
{"m":{[1,1]}} // sagt Flop zum Ersten
Gleich ein Hinweis für den wahrscheinlichen Fall, dass wir entweder mehrere Geschwisterpärchen haben, weil wir mehrere unabhängige Blinkgeneratoren in einem ESP unterbringen wollen, oder weil die Geschwister nicht unbedingt immer an erster Stelle stehen, da wir noch eine Vielzahl von anderen Service-Types vorgelagert haben:
Die Positionsangaben oder "Target Service Number" für die Service-Notifications kann, wie eben beschrieben, absolut, aber auch relativ erfolgen. Letzteres macht Sinn, wenn wir nicht immer abzählen wollen, an welcher Stelle das jeweilige Device steht, das wir instruieren wollen. Flip und Flop werden sinnigerweise immer nebeneinandergestellt, sodass Flop für Flip der Nächste ist, umgekehrt Flip für Flop der Vorherige. Dadurch wird es auch egal, wo wir das Pärchen hinverfrachten, beim relativen Nummerieren bleiben die Zuordnungen immer erhalten. Genau das kennen wir bereits aus dem Einleitungbeispiel und ersetzen in diesem Sinne den vorherigen Code durch die relative Entsprechung (ohne weitere Erklärung):
{"m":{[7001,1]}} // sagt Flip zum Nächsten
{"m":{[-1,1]}} // sagt Flop zum Vorherigen
… und ergänzen damit das Ausgangsskript mit den noch fehlenden Keys für die ausschließliche Mitteilung im Falle des jeweiligen Ausschaltens, also für Action "0":
{"a":[{"t":1,"0":{"m":[[7001,1]]},"i":1},{"t":1,"0":{"m":[[-1,1]]},"i":1}]}
Fertig ist der Homekit-Blinkgenerator!
Allerdings hat diese verfrühte Version noch einen entscheidenden Nachteil: Einmal angeworfen hört der nie mehr auf, zumindest nicht solange der ESP mit Energie versorgt wird. Das ist natürlich suboptimal, aber kein Beinbruch, denn RavenSystem erlaubt es, jedes beliebige Device über eine weitere Service Notification per "Target Service Value" durch den Wert "-10000" zu deaktivieren.
Da wir weder Flip noch Flop veranlassen können, ihrem Gegenüber und sich selbst gleichzeitig sowohl das Ausschalten als auch das Einschlafen mitzuteilen, brauchen wir eine weitere Protagonistin in unserem Bühnenstück, die ich Mama Blink nenne. Die freundliche Dame ist in unserem Beispiel ebenfalls vom Stande Schalter "t":1 und damit die Dritte im Bunde. Sie wird dem Erstgeborenen Flip bei ihrem Einschalten mitteilen, dass sich dieser ebenfalls einschalten soll. Das kennen wir bereits:
{"m":{[-2,1]}} // sagt Mama Blink als Dritte in der Reihe zu Flip beim Einschalten
Neu ist die Mitteilung, die Mama Blink beim Ausschalten an ihre beiden Kinder sendet, damit diese sofort einschlafen. Vorher jedoch schaltet Mama Blink beide Schalter ordentlich aus, damit nicht versehentlich einer der Bengels womöglich angeschaltet einschläft.
{"m":[[-2,0],[-2,-10000],[-1,0],[-1,-10000]]}
// sagt Mama Blink zu Flip und Flop beim Ausschalten
Sobald also Mama Blink ausgeschaltet wird, schlafen beide Geschwisterchen Flip und Flop direkt nach dem Licht löschen bzw. Ausschalten ohne Verzögerung ein und veranlassen sich ab sofort nicht mehr gegenseitig, sich beim Ausschalten jeweils wieder einzuschalten. Es kehrt also planmäßige Ruhe ein.
Allerdings ist im Moment der Schlaf derart endgültig tief, dass Mama Blink beide Geschwister beim erneuten Einschalten nicht wieder wach bekommt. Sie muss die beiden erst wieder wecken, indem sie sie durch den Wert "-10001 reaktiviert. Erst dann kann sie Flip ausrichten, sich wieder einzuschalten. Insgesamt sieht Mama Blink dann wie folgend aus:
{"t":1,"0":{"m":[[-2,0],[-2,-10000],[-1,0],[-1,-10000]]},"1":{"m":[[-2,-10001],[-2,1],[-1,-10001]]} // Mama Blink Soloansicht
Wichtig ist die Reihenfolge der Anweisungen für Flip: also erst ausschalten und dann einschläfern bzw. erst aufwecken und dann einschalten. Der ESP erledigt diese beiden direkt aufeinanderfolgenden Anweisungen in Millisekunden, und damit gefühlt zeitgleich. Der Blinkgenerator nimmt somit seine voll funktionstüchtige Form wie folgt an und sieht dann so aus wie die Animation zu Anfang des Beitrags:
{
"a":[
{"t":1,"0":{"m":[[7001,1]]},"i":1}, // Flip
{"t":1,"0":{"m":[[-1,1]]},"i":1}, // Flop
{"t":1,"0":{"m":[[-2,0],[-2,-10000],[-1,0],[-1,-10000]]},"1":{"m":[[-2,-10001],[-2,1],[-1,-10001]]} // Mama Blink
}]
}
Nichts ist so gut, dass es nicht noch besser gemacht werden könnte. Wir erinnern uns an die im D1 Mini integrierte LED, die zukünftig die dröge aber rege Unterhaltung zwischen Flip und Flop, sprich das Blinken anzeigen soll. Dafür reicht es, wenn wir z.B. nur Flip mit der LED "verdrahten" und Flop unberücksichtigt lassen. Besagte LED ist über GPIO 2 schaltbar und leuchtet auf, wenn dieser den Status "low" erfüllt. Das hatten wir bereits bei der selbstgebauten HomeKit-LED ausführlicher erklärt, soll also hier nicht weiter vertieft werden. Wir müssen somit Flip neben der bereits vorhandenen Service Notification an Flop die zusätzlichen nötigen Schaltbefehle für die interne LED in folgender Form überreichen:
{"t":1,"0":{"r":[{"g":2,"v":1}],"m":[[7001,1]]},"1":{"r":[{"g":2}]} // Flip
Was zur folgenden Skript-Version führt:
{"a":[{"t":1,"0":{"r":[{"g":2,"v":1}],"m":[[7001,1]]},"1":{"r":[{"g":2}]},"i":1},{"t":1,"0":{"m":[[-1,1]]},"i":1},{"t":1,"0":{"m":[[-2,0],[-2,-10000],[-1,0],[-1,-10000]]},"1":{"m":[[-2,-10001],[-2,1],[-1,-10001]]}}]}
Noch ein letztes Problem werden wir mit dem inzwischen voll funktionstüchtigen HomeKit-Blinkgenerator samt mitblinkender LED haben. RavenSystem sieht standardmäßig vor, dass 8-maliges Toggeln eines Schalters den Setup Mode des ESP aktiviert und diesen damit in HomeKit unerreichbar werden lässt. Der Blinkgenerator wird diese 8-maligen Schaltvorgänge schnell ausgeführt haben. Er wird sich dadurch ungewollt regelmäßig in HomeKit temporär abmelden, was ja nicht unbedingt in unserem Sinne ist.
Natürlich sieht RavenSystem mehrfache Möglichkeiten vor, diesen Standard zu modifizieren – dies u.a. in der bisher noch nicht erwähnten "Accessory Configuration", die an dieser Stelle noch nicht weitergehend erklärt werden soll. Im Beispielskript ergänze ich für diesen Zweck eine weitere Steckdose, die direkt nach Betätigung den Setup Mode auslöst, während ich vorher noch den Standard des 8-maligen Toggles komplett deaktiviere. Das erreiche ich durch den "Setup Mode Toggle Count" Key "z":0 im besagten Konfigurationsteil des Skripts, der dem Accessory-Teil mit dem Key "a" über den Configuration Key "c": vorangestellt ist, was dann den folgenden Zusatz im Skript bringt:
Da wir durch diese Deaktivierung allerdings den Setup Mode des ESP nicht mehr (ohne Weiteres) aktivieren können, erklärt sich die Steckdose, die natürlich auch ein Schalter sein könnte, sich als Steckdose rein visuell aber besser von dem Blinkschalter-Trio absetzt, und über die wir den Setup Mode für unser Beispiel alternativ wieder hinkriegen. Wohlgemerkt, das ist eine von mehreren Möglichkeiten, die nicht genannt sind, um den Beitrag nicht noch mehr ausufern zu lassen.
Die besagte Steckdose tut also nichts anderes als per "System Action" mit dem Key "s" den Setup Mode über Key "a":1 zu aktivieren. Diese Steckdose ist somit mit Vorsicht zu genießen, da sich der ESP beim Einschalten derselben sofort aus HomeKit abmeldet:
{"t":1,"1":{"s":[{"a":1}]}} // Schalter "An" löst Setup Mode des ESP aus
Das nun finale, voll funktionstüchtige und problemfreie Skript sieht so aus:
{"c":{"z":0},"a":[{"t":1,"0":{"r":[{"g":2,"v":1}],"m":[[7001,1]]},"1":{"r":[{"g":2}]},"i":1},{"t":1,"0":{"m":[[-1,1]]},"i":1},{"t":1,"0":{"m":[[-2,0],[-2,-10000],[-1,0],[-1,-10000]]},"1":{"m":[[-2,-10001],[-2,1],[-1,-10001]]}},{"t":2,"1":{"s":[{"a":1}]}}]}
(In der Home App wurde die Steckdose als Lampe umdefiniert und setzt sich dadurch vom Blinkschalter-Trio noch deutlicher ab.
Den Blinkgenerator in Aktion sieht man in der Animation zu Beginn des Beitrags)
Der darin beschriebene Steckdosen- bzw. Lampenschalter wird bei einem D1 Mini womöglich unnötig, da es durch den verfügbaren "Emergency Setup Mode" möglich wird, den Setup Mode durch 2-maliges Drücken des im D1 Mini verbauten Reset-Schalters innerhalb von 2 Sekunden zu aktivieren. Selbst ohne speziell dafür angelegten virtuellen Schalter wird es dennoch nötig, den "Setup Toggle Count" auf 0 zu setzen! Außerdem kann damit der Setup Mode auch "ferngesteuert" ausgelöst werden, ohne den ESP griffbereit haben zu müssen.
Verlassen wir die alleinerziehende Mama samt ihrer beiden Söhne und sehen uns die neue Basis-Schaltgruppe für HomeKit bestehend aus 3 Schaltern (+ Setup Mode Steckdose) für den praktischen Einsatz an. In HomeKit integriert können ab sofort beliebige Automationen das Blinken über Mama Blink sowohl einleiten als auch beenden. Flip und Flop ihrerseits bieten im Sinne einer 2-kanaligen Blinkschaltung diverse Möglichkeiten, das gewünschte Blinken zu "gestalten". Vom einfachen Ein und Aus einzelner Lampen über das 2-kanalige Hin und Her neben-/übereinander positionierter Lampen bishin zum oszillierenden Umschalten von Szenen ist nun alles möglich, um auf diverse Dinge im trauten HomeKit-Heim visuell aufmerksam zu machen – das Ganze, ohne zu Löten, ohne zu Schrauben, ohne zu Verkabeln, ausschließlich mit dem ESP.
Sehr leicht lassen sich nach Bedarf weitere Schalter in das Skript ergänzen, die etwa die identische Funktion von Mama Blink haben mit dem Unterschied, dass diese per einfachem zusätzlichen "i" Key ihrerseits zu Timern umfunktioniert werden. Dadurch lässt sich in HomeKit direkt auswählen, wie oft die Blinkfunktion wiederholt werden soll. Mit "i":6 als Zusatz würde Flip exakt 3x einschalten, um dann von selbst in den Schlaf zu verfallen.
Ein Hinweis zum Blinkzeit-Intervall von 1 Sekunde im Beispielskript: Der ESP kann deutlich höhere Schalt-Frequenzen sauber verarbeiten, jedoch ist dann HomeKit u.U. schnell durch die wachsende Schaltbefehl-Bombardierung überfordert und kommt nicht mehr hinterher. Jeder kann bei Interesse gern mal die "i" Key Werte von Flip und Flop verkleinern (bspw. "i":0.5 für 1/2 Sekunde), um zu testen, wann HomeKit aufgibt.
In diesem Beitrag wage ich etwas Neues. Angeregt durch Patrick_s Anfrage biete ich das Beispielskript versuchsweise mal als fertige .bin zum direkten flashen eines (wohlgemerkt!) D1 Mini – andere ESPs werden vermutlich nicht funktionieren?! Wer also ohne Installations-Hassle den Blinkgenerator anmeldefertig ausprobieren möchte, lade sich die bin-Datei herunter und flashe seinen D1 Mini per Terminalbefehl:
python3 -m esptool --port /dev/cu.usbserial-14230 write_flash 0 HAA-Blinkgenerator.bin
Vorher sollte der ESP selbstredend gelöscht worden sein:
python3 -m esptool erase_flash
Der ESP erscheint dann nach einiger Zeit als eigener WLAN Access Point unter den "Netzwerken in der Nähe" mit seinem Namen bzw. der SSID "HAA-xxxxxx" (wobei x für einen aus der MAC-Adresse des ESP generierten Teil besteht). Dieses Netzwerk muss ausgewählt werden, um dann anschließend im Browser die lokale ESP-Webadresse http://192.168.4.1:4567 einzugeben. Es sollte das (ähnliche) Setup-Fenster aufgebaut werden:
Dort das eigene Netzwerk auswählen, Passwort eingeben und den Button "Save" bestätigen. Danach meldet sich der ESP mit demselben Namen im eigenen Netzwerk mit neuer, vom Router vergebenen IP-Adresse an und kann nun in HomeKit unter "Gerät hinzufügen" mit folgendem Code hinzugefügt werden:
bzw.
3 Schalter und 1 Steckdose in Folge werden in HomeKit ergänzt, die dann frei benannt werden können. Wichtig ist nur herauszufinden, wer dabei Flip, Flop und Mama Blink ist. Die Steckdose ist hingegen eindeutig der "gefährliche" Setup Mode Schalter und kann in der Home App besser als Lampe umdefiniert werden. Diese wird dann in eine eigene Lichtquellen Zeile verfrachtet. Voilà!
HAA-Blinkgenerator.bin.zip
Vor dem Flashen bitte erst erst entpacken!