Heterogene Heimautomatisierung mit Node-RED: Ein Erfahrungsbericht

Passende Produkte für die Heimautomatisierung zu finden, ist nicht leicht. Ein Erfahrungsbericht vom Versuch, sie passend zu machen.

Inhaltsverzeichnis

Einleitung

Passende Produkte für die Heimautomatisierung zu finden, ist nicht leicht. Die Menge an Herstellern, Systemen und Apps ist gefühlt endlos. Inzwischen zumindest.

2013 habe ich begonnen, Teilaspekte in den eigenen 4 Wänden zu automatisieren. Zu der Zeit war das Angebot noch recht mager, dafür kam gerade der Raspberry PI ganz groß raus. Ich schrieb Weboberflächen für Thermodrucker und Lichterketten und baute Überwachungskameras mit Bewegungserkennung. Später sammelte ich mithilfe von Arduinos Daten von Temperaturfühlern, um die selbst geschriebene Wetterstation zu füttern und steuerte zum ersten Mal auch Lampen mit 433 MHz Steckern. Alles kam aus einer Hand.

Seitdem hat sich viel getan. Auch an meiner Bereitschaft einen Lötkolben oder ein Steckbrett in die Hand zu nehmen, um etwas zum Laufen zu bringen. Ich feile immer noch gerne an der Heimautomatisierung, aber ich will nicht mehr alles selbst machen. Vor allem, weil es inzwischen viele Lösungen gibt, die Funktionen beherrschen, für die ich viel zu viel Zeit investieren müsste, um sie nachzubauen.

Beispiel Beleuchtung: Mittlerweile gibt es zahlreiche Anbieter für App-gesteuerte Lampen und Leuchten. Phillips Hue zum Beispiel, oder IKEA Tradfri. Beide funktionieren nach dem Prinzip: Anschließen und glücklich sein. Zumindest in der Theorie. In der Praxis möchte ich auch andere Aktoren und Sensoren in meinem smarten Zuhause miteinander verbinden und mit Daten füttern: Bewegungsmelder, Lampen, Temperaturfühler, Heizungssteuerung, Uhren, Schaltsteckdosen, Strommesser, Rauchmelder, Wassermelder, usw. Zur gleichen Zeit möchte ich nicht selbst smarte Glühbirnen herstellen, die das beherrschen.

Integration ist also das brückenschlagende, magische Zauberwort.

Nachdem ich zunächst eine eigene Plattform entwickeln wollte, die das bewerkstelligen kann, habe ich schnell gemerkt, dass die Sache größer ist, als dass ich das alleine könnte. Seit ein paar Jahren setze ich deshalb Node-RED ein. Ein Tool mit einer großen Community, ursprünglich getrieben von IBM und nun Teil der OpenJS Foundation, genau wie node.js oder Electron.

Die Node-RED Webseite bietet einen großen Katalog an Modulen, die von der Community erstellt wurden. Für fast jeden ist etwas dabei. In diesem Beitrag soll es um meine Erfahrungen mit diesen Modulen und auch mit unterschiedlichen smarten Geräten gehen. Ein bisschen Foreshadowing: Alles geht, aber oft nur mit Kompromissen.

Disclaimer: Die Beschäftigung mit den unterschiedlichen Produkten unterschiedlicher Hersteller führt zwangsläufig zum Aufbau von Know-How über die Anbindungsmöglichkeiten und deren Stärken und Schwächen. Im Umkehrschluss kann ich hier nur über die von mir eingesetzten Produkte schreiben. Die Auswahl erfolgt nach eigenem sinnvollen Ermessen und letztlich meiner souveränen Willkür. Die Landschaft an Dingen in meinem Intranet ist historisch gewachsen und spiegelt eine kontinuierliche Entwicklung wieder. Sie erhebt weder Anspruch auf Vollständigkeit oder Perfektion. Vielmehr ist sie Spielwiese, Labor und ab und an – mit etwas Glück – auch Quelle für sinnvolle Ergänzungen meiner Heimtechnik. Die Art und Zusammensetzung soll hier also kein Thema sein, vielmehr die Art und Beschaffenheiten der Integrationen zwischen den einzelnen Bestandteilen.

Insgesamt befinden sind inzwischen viele Produkte einiger Hersteller in meinem Heimnetz, die mittels unterschiedlicher Technologien und Protokollen miteinander reden. Von MQTT über WLAN, Zigbee und DECT bis hin zu Bluetooth LE ist alles dabei. Lampen wie die von IKEA oder Philips kommunizieren via Zigbee mit ihren Gateways bzw. Bridges. Die Integration mit Node-RED ist hier relativ simpel, weshalb ich nicht im Detail darauf eingehen möchte. Dennoch will ich eine knappe Einführung in Node-RED geben, wonach ich dann die folgenden Anbindungen genauer beleuchten möchte, da sie mehr Zeit gekostet haben, als ich erwartet hätte und sie zudem zeigen, was alles mit Node-RED möglich ist:

Node-RED Basics

Node-RED ist eine simpel gehaltene Low-Code Plattform, die es ermöglicht mit wenigen Klicks auch vergleichbar komplexe Schnittstellen zu bauen. Ein einfacher Flow sieht zum Beispiel so aus:

Der Flow beginnt mit einem MQTT in-Knoten, der nichts anderes tut, als auf neue Nachrichten in einem bestimmten MQTT-Topic zu lauschen. (Voraussetzung dafür ist ein MQTT-Server – auch Broker gennant – z. B. mosquitto.) Hier heißt das Topic sensor_airpressure und wird durch einen meiner Arduinos per WLAN jede Stunde befüllt. Bei jeder neuen Nachricht, wird der Flow gestartet, d.h. die eingehende Nachricht wird im konkreten Beispiel an vier nachfolgende Knoten weitergegeben.

Der erste Knoten ist ein Funktionsknoten. Solche Funktionsknoten akzeptieren Javascript-Code. Im konkreten Beispiel konvertiert er die ankommende Zeichenkette in eine Gleitkommazahl und gibt sie anschließend weiter:

Die Knoten darunter befüllen Elemente auf dem Node-RED Dashboard, welches es ermöglicht, eine grafische Oberfläche für alle in Node-RED verfügbaren Daten zu bauen. Das Ergebnis sieht hier so aus:

Das Dashboard kümmert sich selbstständig um das Sammeln der Daten für das Diagramm und die passende optische Darstellung. Der Date/Time Formatter-Knoten formatiert die aktuelle Zeit für das Dashboard (“Zuletzt aktualisiert”).

Der große Nachteil des Node-RED Dashboards: Die Daten werden nur so lange gesammelt, wie Node-RED aktiv ist. Bei einem Neustart sind die Daten verloren. Um Daten langfristig sammeln zu können bedarf es eines Archivs.

Archivierung mittels InfluxDB und Grafana

Der hellbraune Knoten im Beispiel oben sorgt für die Archivierung der Daten. Es handelt sich um einen InfluxDB Knoten, der wie folgt konfiguriert ist:

Alle ankommenden Gleitkommazahlen werden also an den lokalen InfluxDB Server und die Datenbank home_weather geschickt. Dort landen sie in einer Messung namens airpressure. In Grafana kann ich so auch langfristige Schaubilder für die Messung anzeigen:

AVM FRITZ!DECT 210

Auch AVM ist inzwischen in den Markt der klugen Dinge eingestiegen und bietet Aktoren an, die den DECT-Funkstandard nutzen, um zu kommunizieren. Dieser Funkstandard ist in Europa vor allem durch die Nutzung von kabellosen Telefonen bekannt und benötigt immer auch eine Basisstation, an der die Mobilteile angemeldet werden. Im Falle von AVM ist das immer eine FRITZ!Box. Dort können inzwischen nicht mehr nur Mobilteile angemeldet werden, sondern auch smarte Geräte, wie die Outdoor-Funksteckdose DECT 210.

Zur Steuerung der Steckdose können die Weboberfläche der FRITZ!Box oder eine separate App genutzt werden. Der große Vorteil ist: Ohne das explizit so zu konfigurieren, bleibt die Steckdose im Heimnetz und ist nicht vom Internet aus steuerbar. Zum Zeitpunkt, als ich mir die Steckdose kaufte, war es eine der wenigen, bei der ich das sicherstellen konnte. Viele andere Stecker kommunizieren direkt mit dem Internet und sind auch nur über das Internet steuerbar.

Dennoch war mir natürlich wichtig, die Steckdose zu integrieren. Ich entschied mich zu der Zeit dazu, die Integration selbst durchzuführen und kein fertiges Modul zu nutzen, da ich nicht die TR-064-Schnittstelle nutzen wollte, die ich deaktiviert habe. Dabei bin ich auf ein interessantes Dokument gestoßen, welches den Login-Mechanismus für die FRITZ!Box-HTTP-API beschreibt.

Daraus wird klar ersichtlich, dass die FRITZ!Box Loginpasswörter aller Nutzer im Klartext speichern muss, da sonst die Lösung der Challenge nicht geprüft werden kann. Ein (mildes) Sicherheitsproblem, auch wenn die Dokumentation das Vorgehen als Sicherheitsfeature verkauft. Fakt ist, dass die FRITZ!Box bei geschickter Implementierung des Challenge-Response-Verfahrens die Passwörter nicht im Klartext speichern müsste. Aus welchem Grund darauf verzichtet wurde, ist nicht klar.

Insgesamt ist die Implementierung vergleichsweise aufwändig, da ich mich selbst um die Sitzungsverwaltung kümmern und dann natürlich auch noch die Challenges lösen muss. Der Flow nur zum Einschalten einer Lampe sieht wie folgt aus:

Hier würde ich mir kleine Pfeilchen an den Enden jeder Verbindung in Node-RED wünschen, da es hier nun nicht mehr nur von links nach rechts geht.

Mitunter die wichtigsten Knoten sind hier die mit dem Namen /home/nodered/level.db. Es handelt sich – wie der Name schon vermuten lässt – um eine Datei-basierte lokale Datenbank, in der ich die Sitzungen speichere und wieder abrufe. Ist eine vorhandene Sitzung abgelaufen, wird später eine neue angelegt, ansonsten geht es relativ direkt zu dem Knoten namens on, welcher den Stecker in den Zustand “an” versetzt.

Die bedeutsamsten Knoten im Beispiel sind aber die mit mehreren Ausgängen. Es handelt sich um sogenannte switch-Knoten, mit denen man mittels Bedingungen unterschiedliche Wege einschlagen kann:

Die FRITZ!Box liefert bei einer invaliden oder nicht bestehenden Sitzung eine Sitzungsnummer zurück, die nur aus 0en besteht. Ist das der Fall, muss also eine neue Sitzung erzeugt werden, bevor der Stecker geschalten werden kann. Der switch-Knoten mit dem Namen need new SID? entscheidet deshalb, ob der Flow erst nach oben muss (neue Sitzung erstellen) oder bereits nach unten kann (bestehende Sitzung wiederverwenden).

Auf die Details des Challenge-Response-Verfahrens und der FRITZ!Box-HTTP-API möchte ich an dieser Stelle nicht weiter eingehen, da dies definitiv den Rahmen sprengen würde. Wer mehr wissen möchte, kann sich hier, hier und hier informieren.

Ruuvi Innovations RuuviTags

Ruuvi Innovations ist ein Unternehmen aus Finnland, welches 2016 ein Kickstarter-Projekt für drahtlose Sensoren startete. Das Ziel \$10.000 zu sammeln war schnell erreicht. Insgesamt sammelte das Projekt über \$170.000 ein.

Bei den daraus entstandenen RuuviTags handelt es sich um handflächengroße, batteriebetriebene Sensoren, die als Bluetooth LE Beacon agieren und Daten wie Temperatur, Luftfeuchtigkeit, Luftdruck und Beschleunigung messen. Ich habe drei von den Tags zuhause und wollte mich – wie üblich – nicht auf die mitgelieferte App beschränken lassen. Das Team um den RuuviTag gibt sich große Mühe die Integration zu erleichtern. So existiert bereits ein fertiges Node-RED Modul, welches Beacon-Nachrichten parsen kann, um an die Sensorwerte zu gelangen.

Leider erwartet das Modul Input von einem anderen Modul namens “noble”, welches Bluetooth LE Funktionalitäten bereitstellen soll, aber bereits seit einiger Zeit nicht mehr aktiv gepflegt wird. Mit der Version 8 von node.js funktioniert noble noch gut, zum Zeitpunkt der Veröffentlichung dieses Artikels ist aber bereits Version 13 aktuell und Version 12 LTS. Zwar gibt es Bestrebungen noble mit aktuelleren node.js-Versionen kompatibel zu machen, ich konnte das Modul bei mir allerdings nicht zum Laufen bekommen. Eine Alternative musste her.

Zum Glück hatte ich bereits einen Adafruit HUZZAH32 als Datensammler für Sensoren im Heimnetz. Dieser kann neben WLAN auch gleichzeitig Bluetooth LE. Es war daher eine leichte Übung diesen so umzuprogrammieren, dass er nicht nur regelmäßig Sensorwerte per MQTT schickt, sondern auch alle gefundenen Bluetooth LE Geräte bzw. Beacon-Nachrichten. In Node-RED musste ich dann nur noch auf das entsprechende MQTT-Topic lauschen und die ankommenden Daten in einem Javascript-Funktionsknoten so umbauen, als wären sie von noble gekommen:

var md = /manufacturer data: (.*)$/;
var ad = /Address: (.*?),/;
if(msg.payload.match(md) && msg.payload.match(ad)) {
    msg = {
        "payload": msg.payload,
        "advertisement": {
            "manufacturerData": msg.payload.match(md)[1]
        },
        "peripheralUuid": msg.payload.match(ad)[1].replace(/:/g, "")
    };
    return msg;
}

Im späteren Verlauf kann ich die Daten dann wie üblich nutzen, um die gewohnte Kombination aus Node-RED-Dashboard und InfluxDB zu befüllen:

Jede Minute erwarte ich eine Nachricht vom HUZZAH32. Damit ich auch mitbekomme, wenn diese eine Zeit lang ausbleibt – auch nur von einem RuuviTag – habe ich zusätzliche Vorkehrungen getroffen. Für jeden RuuviTag gibt es einen Timer-Knoten. Dieser fängt an zu laufen, sobald die erste Nachricht eintrifft. Schlägt keine zweite Nachricht innerhalb der festgelegten 30 Minuten auf, wird die erste Nachricht weitergeleitet. Wenn doch eine zweite Nachricht eintrifft, wird der Timer zurückgesetzt und die angekommene Nachricht wieder wie eine erste behandelt, die ursprüngliche erste Nachricht wird verworfen.

Gibt es von einem RuuviTag also 30 Minuten lang keine Rückmeldung, wird ein Pushover-Knoten ausgelöst, welcher eine Benachrichtigung an mein Handy sendet und mich somit direkt alarmiert. Derartige Konstrukte habe ich an vielen Stellen in meine Flows eingebaut:

Beim ersten Knoten handelt es sich um einen Inject-Knoten, der zeitbasiert einmal oder mehrmals, oder auch manuell ausgelöst werden kann. Im konkreten Fall löst er einmal aus, und zwar immer dann, wenn alle Flows neu gestartet werden. Das ist dann der Fall, wenn ich manuell Flows deploye, oder den Node-RED-Server aktiv neustarte. Es passiert aber auch dann, wenn der Server nach einem Stromausfall wieder hochfährt. So kann ich ohne großen technischen Aufwand auch von Unterwegs sehen, ob es einen Stromausfall gab.


Fazit

Kohärente Heimautomatisierung- und überwachung ist anstrengend. Jeder Anbieter von Sensoren und Aktoren hat eine andere Vorstellung davon, wie eine API aussehen muss, oder wie Sitzungen oder Loginmechanismen funktionieren. Ganz zu schweigen vom Kommunikationsprotokoll. Wer momentan Systeme von verschiedenen Herstellern so bedienen möchte, als käme alles aus einer Hand, muss einiges an Arbeit investieren.

Glücklicherweise gibt es Communitybestrebungen wie Node-RED und dessen Module, die vieles vereinfachen. Smarte Lampen wie TRÅDFRI oder Hue sind damit sehr einfach auszulesen und zu steuern. Zwar bedient sich jedes Node-RED Modul unterschiedlich, am Ende fällt aber meist doch ein simples JSON-Objekt über die Kante, mit dem sich leicht arbeiten lässt. Auch über Dinge wie das Lesen von API-Dokumentation oder über die Sitzungsverwaltung nach einem Login, braucht man sich üblicherweise keine Gedanken mehr zu machen, da diese Logik so gut wie immer bereits im Node-RED Modul enthalten ist.

Meine zwei ausgeführten Beispiele sind Extrembeispiele, die zeigen sollen, dass es selbst dann funktioniert, wenn die Module an ihre Grenzen kommen oder deren Einsatz nicht infrage kommt. Natürlich ist das dann mit einem zusätzlichen Aufwand verbunden. Aber manchmal ist der lohnenswert.

Schlussendlich lässt sich mit Node-RED so gut wie alles automatisieren, so lange das zu automatisierende System irgendwie ansprechbar ist – selbst SSH, Telnet oder gar proprietäre Protokolle über TCP oder UDP sind kein Problem, solange es eine Dokumentation gibt, die die Schnittstelle beschreibt und man sie so nachbauen kann. Node-RED kann im Zweifel auch selbst zum Anbieter von APIs werden, indem Flows gebaut werden, die loslaufen, wenn eine bestimme URL (oder ein TCP/UDP-Port) aufgerufen wird. Gleichzeitig gibt es genügend Anbindungen an Datenbanken und eine schier unerschöpfliche Menge an Knoten zum Verarbeiten von Daten, um auch mit jedem Format umgehen zu können.

Bisher bin ich da noch an keine Grenze gestoßen.