Viessmann API und Node-Red - Teil 6b - Influx Diagramme

Um es vorweg zu sagen, ich beschäftige mich in diesem Artikel mit Influx zur Erzeugung von Diagrammen ausschließlich in Node-Red. Es gibt auch andere, leistungsfähigere Diagrammlösungen wie Grafana. Die dabei zu durchlaufende Lernkurve ist allerdings sehr steil und außerdem haben wir anschließend ein weiteres System an der Hand, so dass wir zwischen Diagrammen und Einstellungen immer hin- und herspringen müssen. Ich finde, Analysen und Befehle auf einer einzigen User-Interfaceschicht besser. Auch wenn Node-Red, was Diagramme angeht, nicht so viel kann, für den Hausgebrauch reicht es.  Ein weiterer Vorteil von Node-Red ist, dass die Darstellung auf mobilen Endgeräten besser ist.

Nachteil ist, dass wir die in Influx seriell abgespeicherten Daten erst mit etwas Aufwand in JSON umwandeln müssen. Aber das ist ein lehrreicher Einmalaufwand - siehe weiter unten.

Wie schon im vorigen Kapitel geschrieben, konzentriere ich mich auf Influx Version 1.8 mit dem Command Line Interface.

Das Influx Command Line Interface (CLI) ist richtig old School, Look and Feel erinnert an das selige dBase von vor 40 Jahren. Die Befehle sind auch sehr ähnlich, wer schon einmal SQL Abfragen gebaut hat, wird sich sehr schnell zu Hause fühlen. Alle andere müssen sich jedoch keine Sorgen machen, ich erkäre das im Folgenden.

Erste Schritte

Influx CLI

Der Aufruf erfolgt im RaspbianTerminal ganz einfach mit influx . Falls das nicht klappt, bitte bei meinem Artikel Viessmann API und Node-Red – Teil 6a nachsehen. Da steht, wie man Influx installiert.

Wir legen als nächstes eine Datenbank namens apidata an: create database apidata. Der Name ist natürlich wahlfrei.

In einer einzelnen Datenbank können mehrere verschiedene Tabellen mit Messwerten stecken. z.B. Temperatur, Betriebsdauer, Verbrauch. Diese Tabellen heißen Buckets (Eimer), die dort hineingeschriebenen Messwerte nennt man Measurements (Messungen).

Fake Daten generieren mit Node-Red

Bauen wir uns erst einmal einen kleinen Datenzoo aus Fake-Werten: Dazu brauchen wir einen Inject-, Funktions- und  einen Influx Out-Node. Eventuell sind die Influx Nodes noch nicht vorhanden. Dann müssen wir sie über die Node-Red Palettenverwaltung nachinstallieren.

Der Inject Node sollte so eingestellt werden, dass er alle paar Minuten ein Timestamp losschickt.

Der function node sieht so aus:

Der Influx out Node wird wie folgt eingestellt:

Node-Red nennt hier den (oder die?) Bucket "Measurement", was meines Erachtens etwas doppeldeutig ist.

Will man Temperaturen von mehreren Messstationen in demselben Bucket abspeichern, (z.B. für Nordseite oder Terrasse) dann brauchen wir noch ein so genanntes Tag (Etikett), das dem Wert in der Payload mitgegeben wird. Wird die Payload wie oben dargestellt so mir nichts dir nichts übergeben, bekommt der Wert die Überschrift "value", was bei komlexeren Datenstrukturen nicht gerade aussagekräftig ist. Deshalb sollten wir noch entsprechenden Überschriften für das Tag und den Wert mitliefern. Der Funktionsnode sieht dann so aus:

Die Payload wird hiermit zu einem Objekt.  Das Tag für den Ort ist hier "Nordseite" und die Temperaturwerte bekommen die Überschrift "gradc".

Arbeiten mit echten Daten

Im "echten Leben", also ohne Fake Daten wird der influx in Node direkt mit dem Datenoutput aus unserer API verkabelt.

Fragt man nun die Viessmann Daten alle 90 Sekunden ab, werden über den Tag 960 Werte weggespeichert. Viele davon sind gleich, da sich die Lufttemperatur nicht andauernd ändert sondern über Stunden gleich bleibt. Daher ist es besser, einen Filter einzubauen, damit unsere Datenbank sparsam befüllt wird:

Der Filter Node schickt empfangene Daten nur weiter, wenn sie sich gegenüber dem vorherigen Datum geändert haben. Sehr praktisch!

Daten mit Influx ansehen

Springen wir zurück zu unserer Tabelle mit den gefaketen Werten und lassen den Flow ein paar Minuten oder länger laufen - oder klicken mehrmals auf den Inject Node. Ansehen können wir uns die Rohdaten wieder im Influx CLI mit select * from temperatur

Das wird  allerdings einen Fehler ERR: database name required  produzieren. Wir müssen zuerst die zu verwendende Datenbank mit use apidata  setzen - dann funktioniert's.

Das Ergebnis mit unseren Phantasiewerten sieht ungefähr so aus:

Die Spalte time enthält den Unix Timestamp auf Nanosekunden genau. Eigentlich ein Overkill, aber es ist halt so.  Die Website Unix time stamp ist sehr hilfreich dabei, diese Daten hin oder her zu konvertieren.

Der 19-stellige Nanosekunden genaue Timestamp ist für Node Red etwas zuviel. Damit Node Red mit diesen Timestamps rechnen kann,  müssen wir den Timestamp um 1000 dividieren, d.h. auf Millisekunden kürzen. Das macht man am einfachsten mit der Number()Methode.

Will man die Daten der letzten3 Stunden abfragen, lautet der Befehl:

select time, gradc from temperatur where time > (now() - 3h)

Influxdb 1.8 erlaubt folgende Literale für die Zeitdauer:

  • microseconds:  u  or µ
  • milliseconds: ms
  • seconds: s
  • minutes: m
  • hours: h
  • days: d
  • weeks: w

Inflix 2.x kann da etwas mehr. Bei 1.8 fehlt z.B. 1mo  für einen Monat.

Eine Dokumentation der Influx Abfragesprache findet ihr hier.

Darstellung mit Node-Red

Wie schon beschrieben, muss man die in Influx steckenden seriellen Daten erst in ein JSON Objekt konvertieren, bevor man sie in einem Node-Red Diagramm darstellen kann. Ich habe mich hier von folgender Website inspirieren lassen: https://funprojects.blog/2020/02/01/influxdb-with-node-red/

Der Node Define Query enthält die oben stehende Abfrage für Werte der letzten 3 Stunden wie folgt:

Der influxdb in Node enthält lediglich den Sever und die Datenbank und liefert als Output ein Array der Art

Man könnte die Query auch direkt in den Influxdb in Node schreiben, warum auch immer,  ich finde es besser, die Query sauber getrennt in einem eigenen Knoten unterzubringen.

Der Node make JSON ist etwas komplexer - Erklärung in den Kommentaren:

Heraus kommt ein - in unserem Fall weitgehend sinnloses - Liniendiagramm:

Das Schöne ist, wir können den oben dargestellten make JSON Node beliebig weiterverwenden. Anzupassen sind lediglich der Wert der "Series" Variablen sowie die Variable bei msg.payload[i].gradc .

Mehr Flexibilität

Vielleicht willst du die Zeitspanne, für welche die Daten ausgewertet werden etwas flexibler gestalten. Das geht recht einfach über den dropdown Node des Dashboards.

Das Dropdown kann z.B. wie folgt befüllt werden:

Der Query Node wird geringfügig modifiziert:

Breitere Linien und Schraffuren

Fügt man vor dem return msg;  Kommando des make JSON Nodes noch folgende Befehle ein, kann man die Darstellung der Linie etwas aufhübschen:

borderWidth stellt die Breite in Pixel ein, steht der fill Parameter auf true, wird der Bereich unterhalb der Linie transparent in Linienfarbe schraffiert.

Problem dabei ist, dass sich diese Methode auf sämtliche Linien des Line-Charts auswirkt, bei Multi Value Line-Charts also eher nicht zu empfehlen.

Balkendiagramme

Balkendiagramme sind auch möglich. Allerdings müssen wir hier etwas mehr Mühe in die Label Variablen stecken - beim Line Chart konnten wir die ja beliebig gestalten.

Verbrauch anzeigen

Den Tages-Verbauchswert in kW kannst du (neben anderen Verbrauchswerten) aus der API abgreifen:

Kurz vor 24 Uhr sollte dieser Wert dann in die InfluxDB geschrieben werden, damit wir eine tageweise Auswertung fahren können.

Lange Rede, kurzer Sinn, hier ist das JSON File zum importieren in Node-Red - der Make JSON Funktionsnode ist ausführlich kommentiert:

Hat alles geklappt bekommen wir ein Balkendiagramm dieser Art:

Das Datum "seit Befüllung" wird extra berechnet und ist nicht Bestandteil des obigen JSON Codes.

In meinem Node-Red Setup generiere ich den momentanen und täglichen Gasverbrauch aus Modulation in %  * Zeitdauer * Kesselleistung . Die Modulation wird bei mir alle 90 Sekunden abgefragt: habe ich über den Tag z.B. eine durchschnittliche Modulation von 30%, dann muss ich das nur mit den 19kWh des Kessels multiplizieren und erhalte dann einen Tagesenergieverbrauch von 0,3 * 19kWh * 24 = 136,8 kWh. Das kann ich dann je nach dem spezifischen Energiegehalt des Brennstoffs umrechnen in
z.B. Erdgas 136[kW] / 10,36 [kW/m³] = 13m³ oder
Propangas 136[kW] / 7,3 [kW/Liter] = 18,6 Liter GPL
Klingt zuerst einmal etwas umständlich. Beim Momentanverbrauch ist diese Methode jedoch genauer - Viessmann aktualisiert den kWh Wert nämlich nur jede Stunde.

Aggregierte Werte

Wie jede gute Datenbank bietet Influx auch die Möglichkeit, Werte nach Tagen, Wochen etc. zu aggregieren. Leider kommt uns jetzt der geringere Funktionsumfang der Version 1.8 in die Quere. Monatsweises aggregieren geht in der Datenbank nur mit Klimmzügen, da das Zeitspannenliteral "mo" für Monat erst in 2.x eingeführt wurde.

Wir könnten uns zwar mit 30d behelfen, aber dann wird immer 30 tageweise von heute zurück gezählt. Das wäre bei "mo" aber auch so.

Wir können unsere Datenbank-Abfrage natürlich auch sehr aufwändig vorberechnen, damit sie als Monatswerte brav die Daten vom jeweils 1. bis zum Letzten eines Monats aufsummiert.

Ich bin deshalb etwas anders vorgegangen und habe die monatlichen Werte erst im Nachgang aufsummiert. Hier das JSON dafür:

Daten für Aggregation anreichern

Wenn man vorhat, Daten über bestimmte Zeitspannen zu aggregieren, sollte man immer noch einen Datumswert wie Tag, Monat und/oder Jahr mitgeben.

Der Datensatz wird dazu wie folgt vorbereitet:

Lustigerweise stellt Influx die Tabellenspalten in alphabetischer Reihenfolge dar. Damit Monat und Jahr zusammenbleiben, habe ich die Tags mit einem Unterstrich versehen, das ist natürlich Geschmackssache.

Aggregierte Werte direkt aus Influx

Funktioniert gerade heraus recht einfach mit den Zeitspannen, welche Influx als Zeitliterale versteht. Hat man zum Beispiel viele Messwerte über den Tag hinweg gespeichert, und möchte Tagessummen auswerten, dann geht das mit folgendem Befehl (hier für den Solarertrag):

Heraus kommt das Solarertragsdiagramm weiter oben.

Das Aggregieren, z.B. nach dem Tag "Monat" den wir oben mit abgespeichert haben, geht natürlich genau so.

Null Uhr?

Hat man ein Chart erstellt, das auf mit 1d oder ähnlich aggregierten Werten beruht, wird man feststellen, dass beim Abfahren des Graphen mit dem Cursor keineswegs 0:00 Uhr als Zeitpunkt der Messung angezeigt wird, sondern 1:00 Uhr oder bei Sommerzeit 2:00 Uhr. Das liegt daran, dass Influx intern immer mit Universal Time Coordinated [UTC] arbeitet - früher auch Greenwich Mean Time [GMT] genannt.

Bei Solarerträgen ist das unerheblich, bei anderen Messungen z.B. Stromverbräuchen etc. eher ein Problem, man möchte seine Verbräuche schließlich klar abgrenzen.

Dem hilfst du ab, indem du noch die Zeitzone an die Abfrage hinten anhängst.

Im Command Line Interface zum Beispiel so:

und in der Node Red Query fast genauso. Zusätzlich musst du die einfachen Anführungszeichen bei der Ortsangabe mit einem Backslash "escapen".

Bei Abfrage mit aggregierten Werten, also z.B. _day, musst du derlei Zeitzonen Klimmzüge nicht machen.

Das now() Problem - tageweise Abgrenzung

Der "Jetzt" Wert now()  macht genau das, was der Name bedeutet: er zieht das Datum und die Uhrzeit von gerade eben heran, also z.B. den 20.11.2023 10:15:00

Das ist nicht immer gewünscht, vor allem dann, wenn ich eine genau tageweise Abgrenzung haben will. Mit time > (now() - 1w) liefert mir Influx, unter Zugrundelegung obigen Datums,  Daten vom 13.11.2023 10:15:00 bis heute, 20.11.2023 10:15:00. Der erste Tag ist also unvollständig. Der letzte Tag auch, aber das liegt logischerweise daran, dass heute noch nicht vorbei ist 😉

Bei Influx 1.8 habe ich für das CLI noch keine Möglichkeit gefunden, das Problem mit Influx Hausmitteln zu lösen. Da wir unsere Daten ja sowieso mit Javascript vorbereiten, können wir das dort aber recht einfach lösen:

Im vorgeschalteten Query Setup Node, der die Datenbankabfrage zusammenstellt, müssen wir lediglich einen zuverlässigen Ersatz für now() erzeugen, d.h. Null Uhr des heutigen Tages als Anker, von dem aus wir die Anzahl Tage zurückgehen, über welche die Auswertung laufen soll.

In msg.today steckt jetzt der Startwert - d.h heute früh Null Uhr, erst einmal  auf die MIllisekunde genau. Da Influx (blöderweise) mit Nanosekunden arbeitet, müssen wir noch eine Million dranhängen, d.h. noch 6 Nullen. Das geht problemlos als String; Javascript bzw NR ist in Bezug auf gemischte Zahl- und Stringwerte sehr tolerant.

Der Query String wird jetzt aufgrund der in den String einzufügenden msg.today und msg.payload etwas aufwendiger:

(hourpvprod ist eine Tabelle mit aggregierten Stundenwerten, der Solaranlage)

Mit dieser Abfrage habt ihr eine tagesgenaue Auswertung zur Hand.

Dieser Beitrag wurde inspiriert von https://funprojects.blog/2020/02/01/influxdb-with-node-red/

Schreibe einen Kommentar

Ich freue mich über Lob und Kritik.
Falls du Probleme mit der hier vorgestellten Anleitung hast und nicht weiter kommst:
Bitte das Problem oder die Fehlermeldung(en) möglichst genau beschreiben, auch an welcher Stelle (z.B. in welchem Node oder Befehl) und unter welchen Umständen der Fehler auftritt.
Gerne kannst du mir auch ein Mail schreiben. Die Adresse findest du im Impressum.
Ich gebe mir viel Mühe, meinen Lesern weiterzuhelfen. Je konkreter du bist, desto einfacher und schneller kann ich versuchen zu helfen.
Deine E-Mail-Adresse wird nicht veröffentlicht.
Erforderliche Felder sind mit * markiert