MQTT-Handling in Node-RED

Wie wir bereits in unserem Beispiel, im Kapitel Node-RED als eigenständige Instanz mit dem ioBroker verbinden, gesehen haben, gibt es in Node-RED einen speziellen Node für die Kommunikation über MQTT. Das macht es uns besonders einfach ein- und ausgehende Verbindungen über MQTT zu verwalten. Ist Node-RED nicht als Adapter im ioBroker aktiv, sondern als externe Instanz tätig, kommen wir um die Verwendung von MQTT überhaupt nicht herum. Aber auch wenn wir die Entwicklungsumgebung als Adapter installiert haben, und somit direkt auf die Objekte im ioBroker zugreifen können, ist MQTT ein äußerst hilfreiches Werkzeug um Geräte direkt abzufragen oder weitere Datenverbindungen aufzubauen.

Für eine Hand voll Abfragen ist die direkte Verwendung der Nodes, wie wir es in unserem Beispiel gesehen haben, auch vollkommen ausreichend. Auch wenn wir ein paar wenige Schaltzustände von einzelnen Geräten abrufen wollen passt das so. Doch mit zunehmender Anzahl an Datenpunkten müssen wir uns irgendwann Gedanken um das Handling der MQTT-Verbindungen machen. Sonst sind ioBroker und Node-RED nur noch mit dem Empfangen und Senden der ganzen verschiedenen MQTT-Feeds beschäftigt und die Performance geht gewaltig in die Knie, denn haben wir erst einmal einen Schaltzustand im Broker abonniert, feuert der automatisch jede Änderung, ohne Rücksicht auf Verluste.

Gerade in größeren ioBroker Installationen, wo locker mehrere tausend Schaltzustände und Statuswerte zu übertragen sind, die sich mitunter mehrmals in der Sekunde ändern können und somit jedes Mal eine neue Übertragung auslösen, kann die Netzwerklast schnell rapide in die Höhe schießen. Je mehr Nodes du hast, desto mehr Overhead erzeugt Node-RED bei der Verarbeitung und Verwaltung dieser Verbindungen, was CPU und RAM belastet. Daher macht es Sinn hier einen anderen Lösungsansatz zu verfolgen.

Zentrale Anbindung von MQTT

Neben der Möglichkeit gezielt Werte über MQTT auszulesen und zu schreiben, können wir im MQTT-Node auch Wildcards verwenden um ganze Topics auszulesen. Hierfür verwenden wir als Platzhalter das Satzzeichen #, wie im nachfolgenden Screenshot zu sehen:

Wir verbinden den MQTT-in Node wieder mit unserem ioBroker, nur das wir dieses Mal im Topic keinen speziellen Wert abfragen, sondern uns durch Verwendung von # einfach alles über eine Verbindung liefern lassen. Natürlich ist das ein riesiger Schwall an Daten, doch die ganzen Zustände werden alle nur zu Beginn der Übertragung einmal komplett übertragen, und von da an nur noch bei Änderung.

Dazu kommt das ein Wert, wenn er sich ändert zwar in einer Art Warteschlange zur Übertragung anstellt, doch ändert er sich erneut bevor es zur Übertragung kommt, wird er nicht automatisch zweimal übertragen, sondern immer nur einmal der aktuelle Wert, sobald er dann zur Übertragung dran ist. Dadurch wird die Verbindung nicht so sehr durch schnell ändernde Werte überlastet und es wird längst nicht so viel „veralteter“ Datenmüll übertragen. Dafür kann es unter Umständen aber auch länger dauern bis ein Wert nach Änderung übertragen wird. In meinem Produktivsystem, mit über 15000 Werten, kann es so bis zu einer Sekunde dauern bis ein aktualisierter Wert in Node-RED eintrifft. Eine Sekunde ist zwar, bedenkt man die Menge an Werten, bei weitem nicht viel. Bei Aktualisierung von Verbrauchssummen und Zählerständen ist das vollkommen ausreichend. Bei Schaltaufgaben kann das allerdings schon zu lange sein.

Auf Dauer werden wir die richtige Balance finden müssen. Es spricht nichts dagegen einzelne zeitkritische Werte direkt abzufragen, während wir uns andere, weniger zeitkritische Zustände, über eine globale Wildcard übermitteln lassen. Auch Wildcards innerhalb von Topics sind zulässig. Möchten wir uns zum Beispiel nur den Inhalt der Kategorie 0_userdata per Wildcard übermitteln lassen, können wir im Topic 0_userdata/# verwenden. Oder auch 0_userdata/0/Solar# wäre zulässig und liefert dann alle Einträge, die im genannten Verzeichnis mit Solar beginnen.

Filtern nach Topics in Node-RED

Wenn wir nun mit einer Wildcard arbeiten, bekommen wir auch alles geliefert, egal ob wir es gerade brauchen oder nicht. Jetzt liegt es an uns, die benötigten Informationen herauszufiltern. Zwar könnten wir uns hierfür wieder eine Funktion schreiben, immerhin lässt sich ja alles in Funktionen abbilden, doch es geht auch wesentlich einfacher:

In Node-RED gibt es die switch-Node. Diese filtert Nachrichten nach entsprechenden Kriterien und leitet sie dann entsprechend auf verschiedene Ausgänge weiter.

Unsere MQTT-Wildcard Abfrage liefert eine Vielzahl an Nachrichten, den msg.-Objekten, welche aus dem Ausgang des MQTT-in-Nodes heraus gegeben werden. Wie wir bereits im vorherigen Kapitel Erste Flows und die grundsätzliche Funktionsweise von Node-RED festgestellt haben, hat ein jedes msg.-Objekt mehrere Eigenschaften. Grundsätzlich besteht jede Nachricht, welches aus dem MQTT-in Adapter hinaus geht, mindestens aus der Überschrift und dem Inhalt der Nachricht, also msg.topic und msg.payload. Hinter msg.topic verbirgt sich der MQTT-Name, also eben genau der Name, welchen wir zuvor im Topic der MQTT-Einzelwert-Abfrage abgerufen haben. Möchten wir nun mit dem switch-Node danach filtern, sieht das ganze dann so aus:

Der Name dient der Wiedererkennung im Flow, hat darüber hinaus aber keine Bedeutung. Die Eigenschaft, nach der wir filtern, ist hier msg.topic. Wir könnten theoretisch auch nach msg.payload filtern und uns somit beispielsweise alle Werte liefern lassen die true sind, oder die einen bestimmten Wert haben, und… und… und… Hier möchten wir jedoch nach dem Titel filtern.

Die Titel, die wir suchen, legen wir unten, wie gezeigt, in unserer Ausgangsliste fest. Kommt nun ein msg.-Objekt mit dem Titel 0_userdata/0/Aktoren/AC-PV/Power rein, wird dieses Objekt auf den Ausgang 1 weiter geleitet, ist der Titel modbus/1/holdingRegisters/789_/Yield/Power, dann geht es an Ausgang 2, usw.. Das msg.-Objekt bleibt dabei unverändert, es wird nur weitergeleitet.

Weiterverwendung im Flow

Nun könnten wir direkt dahinter mit unserem Flow fortfahren. Doch das würde mir der Zeit absolut unübersichtlich werden, würden die ganzen Verdrahtungen Kreuz und quer durch den gesamten Flow verlaufen. Daher schlage ich hier die Verwendung von Link-Nodes vor.

Diese Art von Node wird verwendet um Verbindungen zwischen verschiedenen Flows herzustellen. Da wir eine Verdrahtungslinie nicht von einem Flow auf einen anderen durchziehen können, müssen wir den Link-out Node verwenden um einen msg.-Objekt an einen verlinkten Link-in Node weiter zu geben. Dieser Link-in Zielnode kann dabei überall, in jedem beliebigen Flow, auch im gleichen sein. Auch sind Mehrfachverlinkungen möglich. Zur Verwendung dieser Nodes ziehen wir uns den Link-in Node in unseren Flow, verbinden ihn und mit Doppelklick gelangen wir in seine Einstellungen. Hier sollte wir auf jeden Fall einen Namen vergeben, damit wir ihn in den Einstellungen des Link-in Nodes später wiederfinden. Existiert bereits ein Link-in Node, an den wir senden möchten, können wir diesen auch direkt in der Checkboxliste weiter unten auswählen. Ist dieses unser erster Node, von der Art, ist die Liste natürlich noch leer.

Was wir im obrigen Screenshot als Endpunkte sehen, sind out-Nodes, welche die herausgefilterten, relevanten Werte an verknüpfte in-Nodes in anderen Flows weiterleiten. Hier ist also noch lange nicht Schluss. Die Weiterverarbeitung der Daten erfolgt nur an anderer Stelle.

Das geht auch anders herum mit MQTT-out

Was als Wildcard in die eine Richtung geht, sollte auch anderes herum funktionieren. Und so ist es auch. Beim Schreiben geht es sogar noch viel einfacher. Hier müssen wir vorher keinen Filter einbauen. Alles was wir benötigen ist ist der MQTT-out Node, wo wir lediglich den Server festlegen. Lassen wir die Zeile Topic leer, nimmt er automatisch den Topic, der im msg.-Objekt mitgeliefert wird. So lässt sich alles über eine einzige MQTT-out Node zurück in den ioBroker übertragen. Und der Übersichtlichkeit halber verwenden wir auch hier wieder Link-Nodes.

Sollte msg.topic nicht dem Zielpunkt entsprechen, können wir den Change-Node verwenden und vorschalten um msg.topic entsprechen zu ändern. So landet der empfangene Wert dann auch sicher an der richtigen Stelle im ioBroker.

Zusammenfassung

Wir können also festhalten, das Handling von MQTT ist mit Node-RED extrem einfach. Einzelne Datenpunkte können spielend leicht direkt abgefragt werden. Mit zunehmender Zahl an Datenpunkten macht es aber Sinn das Handling von MQTT-Abfragen zentral zu managen um die CPU- und RAM-Auslastung gering zu halten. Hier muss jeder für sich selbst ausprobieren und entscheiden was die richtige Balance zwischen Einzelabfragen, für zeitkritische Wertänderungen, und einer Wildcard Abfrage zur Entlastung des Systems ist.

Als nächstes werden wir uns hier mit dem Addieren von Werten befassen. Eine unverzichtbare Funktion, wenn es darum geht Stromverbräuche und Zählerstande zu addieren:

Addieren mit Node-RED

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.

WordPress Appliance - Powered by TurnKey Linux