MQTT-Daten im JSON-Format mit korrekter Einheit umwandeln

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Jesco
Beiträge: 9
Registriert: 10. Apr 2021 12:16
Answers: 0

MQTT-Daten im JSON-Format mit korrekter Einheit umwandeln

Beitrag von Jesco »

Ich versuche in OpenHAB (v4.2) per MQTT empfangene Daten, die im JSON-Format übertragen werden, als Items mit Datentyp 'Number' abzuspeichern.

Dafür habe ich auf einem Rasperry Pi den MQTT-Broker Mosquitto installiert und in OpenHAB das 'MQTT Binding'. Als Bridge zu Mosquitto habe ich über die GUI folgendes Thing erstellt: 'MQTT Binding' > 'MQTT Broker' (ich bin dieser Anleitung gefolgt).

Ich habe dann ein weiteres Thing erstellt: 'MQTT Binding' > 'Generic MQTT Thing'. Dort habe ich einen Channel hinzugefügt und als 'MQTT State Topic' den String für das zu lesende Topic eingetragen.

Um den JSON-String zu parsen scheint es nun zwei Möglichkeiten zu geben:
  • (a) Im Channel des 'Generic MQTT Thing' unter 'Incoming Value Transformations' die passende Transformation für genau einen gewünschten Datenpunkt eingeben, z.B.:

    Code: Alles auswählen

    JSONPATH:$.total_energy
    Dann muss aber für jeden Datenpunkt ein eigener Channel des 'Generic MQTT Thing' erstellt werden.
  • (b) Daher habe ich das Feld 'Incoming Value Transformations' im Channel des 'Generic MQTT Thing' frei gelassen und füge diese Transformation erst im Item hinzu. Ich habe ein Item vom Typ 'Number' erstellt, als Einheit habe ich 'kWh' gewählt, da dies die einzige Einheit der Energie ist, die sich in der GUI wählen lässt. Unter 'Channel Links' habe ich einen Link zum erstellten Channel des 'Generic MQTT Thing' hinzugefügt. Dort habe ich unter 'Profile' die Option 'JSONPATH' ausgewählt und als Ausdruck eingetragen:

    Code: Alles auswählen

    $.total_energy
Offenbar nimmt OpenHAB dann eine automatische Konvertierung vom gelesenen String zum Datentyp Number vor, jedenfalls wird der Wert korrekt angezeigt. Leider aber in der falschen Einheit, da der Wert nicht in 'kWh' übertragen wird, sondern in 'Wh'.

Ich würde mich freuen einen Tipp zu bekommen, wie ich das korrekt konfigurieren muss. Möglicherweise müssen hier zwei Transformationen verkettet werden, ich habe aber keine Anleitung gefunden, wie das zu definieren ist. Und viele Anleitungen beziehen sich auf die Definition in Textdateien, während in der GUI offenbar eine andere Notation erwartet wird.

Ich habe folgende weitere Fragen:
  • Auch unterhalb des Things 'MQTT Binding' > 'MQTT Broker' lassen sich Channels erstellen. Zu welchem Zweck würde man dort Channels erstellen? Bzw. warum existiert überhaupt das 'Generic MQTT Thing' als eigenes Thing und die Channels werden nicht ausschließlich unterhalb des 'MQTT Broker' erstellt?
  • Ist es tatsächlich sinnvoll die JSON-Transformation erst im Channel Link des Items zu erstellen, oder gibt es Vorteile pro Datenpunkt auch einen eigenen Channel im Generic MQTT Thing zu erstellen (die den Mehraufwand rechtfertigen)?
  • Warum werden außer kWh keine anderen Einheiten zur Auswahl angeboten? Es wäre ja denkbar, dass in anderen Fällen Energie in ganz anderen Größenordnungen zu speichern ist, dann wäre kWh als Einheit unpassend.

Benutzeravatar
udo1toni
Beiträge: 15243
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: MQTT-Daten im JSON-Format mit korrekter Einheit umwandeln

Beitrag von udo1toni »

Also, grundsätzlich kannst Du beide Optionen nutzen, um Daten aus JSON zu extrahieren. Jedoch steht im Profile (die Schnittstelle zwischen Channel und Thing) kein Unit of Measurement zur Verfügung - das ist der Teil mit der Einheit.
Es ist möglich, dass Du mit Angabe der korrekten Einheit als unit (nicht in der Anzeige des Items, sondern in den Metadaten) davon kommst, sauber ist das aber nicht. Dieser Parameter legt fest, in welcher Einheit das Item den Wert intern speichert.

Korrekt legst Du stattdessen für jeden gewünschten Wert einen eigenen number Channel an. number Channel kennen (unter Show Advanced) ebenfalls den Parameter unit, dieser bezieht sich im Channel auf den gelieferten Wert.
Wenn Du hier also korrekt Wh einträgst und anschließend für das Number:Energy Item kWh für die Anzeige (Metadaten->State Description->Pattern: %.1f kWh) einstellst, wird der Wert korrekt angezeigt werden, mehr noch, Du kannst dann jegliche Einheit für Energie eintragen (Joule, Kalorie...) und der Wert wird automatisch korrekt umgerechnet (nur in der Anzeige!).
Es mag lästig sein, mehrere (bis auf JSONPATH und unit identische) Channel hierfür anzulegen, Du kannst Dir aber auch hier die Arbeit erleichtern, indem Du nach dem Anlegen des ersten number Channels in die Code-Ansicht wechselst und dort den entsprechenden Block kopierst und mehrfach einfügst. Anschließend kannst Du den Channels eindeutige Label und IDs verpassen und unit sowie Path anpassen.
Wenn Du danach wieder in die Channel-Ansicht wechselst, hat das Thing wie von Zauberhand die weiteren Channel erhalten :)

Zu den weiteren Fragen:
Das Thing-Modell soll die reale Welt nachbilden. In der realen Welt gibt es den MQTT Broker (auch wenn es sich nur um eine Software handelt) sowie beliebig viele einzelne Geräte. Jedes dieser Geräte sollte aus Sicht von openHAB ein einzelnes Thing sein, alle gehören aber zu dem Broker, über den sie angesprochen werden. Der Broker ist also eine Art Gateway (in openHAB-Sprech Bridge) über das die Kommunikation läuft.
Jedes Device hat gewöhnlich ein LWT Topic ("Last Will and Testament") über das es meldet, dass es Online ist. Der Witz dieses Topics ist aber, dass der Broker, sobald die Kommunikation zum Gerät ausfällt dieses LWT Topic auf einen vorher festgelegten Wert setzt (z.B. offline). Und dieses Topic kannst Du einmal pro Thing als availabilityTopic festlegen und bekommst damit in der Verwaltungsoberfläche von openHAB eine Anzeige, ob das Thing online oder offline ist. In Rules kannst Du auf Zustandsänderungen eines Things reagieren, also z.B. nachdem ein Thing online gekommen ist einen bestimmten Zustand herstellen oder wenn ein Thing offline geht eine Meldung verschicken.
Man kann MQTT als virtuellen Bus betrachten, dann wären alle Topics Teil eines ganzen "Things", aber je nach Anzahl der Devices kann das sehr schnell sehr unübersichtlich werden. Hast Du lediglich zwei WLAN Steckdosen, mag die Abbildung als ein Gerät noch gut funktionieren, ich habe hier mehrere Dutzend Geräte über MQTT verfügbar, darunter z.B. auch mein BEV, welches knapp 180 Topics liefert. Das ist dann nicht mehr sinnvoll als "ein" Gerät.

Unterhalb des Brokers lassen sich meines Wissens nur Channel des Typs Trigger erstellen. Diese Channel sind nur für den reinen Empfang von Topics geeignet. Du kannst ein String Item verlinken, um die empfangene Payload (und auf Wunsch auch das Topic) auswerten zu können. Diese Channel kann man z.B. verwenden, um viele verschiedene Topics, die einem bestimmten Muster entsprechen, direkt an eine Rule zu übergeben, die sich dann um die Auswertung kümmert.

Wie oben erläutert ist es gewöhnlich sinnvoll (mindestens für numerische Werte) einzelne Channel zu erstellen. Hat man hingegen im JSON eventuell mehrere Texte, kann es auch sinnvoll sein, das Profile zu nutzen.
Wichtig zu wissen an dieser Stelle: Profiles stehen in allen Channels zur Verfügung, während die Transformation Patterns nur bei einem kleinen Teil der Addons vorhanden sind.

Was die Einheiten betrifft, so kannst Du jegliche Einheit angeben, die sinnvoll ist, man könnte openHAB auch verwenden, um den bundesweiten Leistungsbedarf anzuzeigen, dann halt in GW :) genau wie Du auch Nanowatt als Einheit angeben könntest, Du musst dies lediglich an der richtigen Stelle tun :)
Wichtig ist nur, sich von der Quelle zur Senke zu bewegen, Quelle: MQTT Number Channel (unit: die Einheit, in der der Wert geliefert wird), Item (unit: die Einheit, in der der Wert im Item gespeichert wird), Item Anzeige, State Description Pattern: Die Einheit, in der der Wert dargestellt wird.
Die erste Unit ist fix und durch das jeweilige Topic vorgegeben, die zweite Unit kannst Du einmalig beliebig festlegen, darfst diese später aber nicht mehr ändern, da auch die Persistence diese Einheit verwendet. Du würdest bei einer Änderung also alle historischen Werte verfälschen.
Die Anzeige kannst Du jederzeit nach Lust und Laune anpassen, da Du das Pattern bei Bedarf auch innerhalb der verschiedenen Widgets überschreiben kannst, kannst Du sogar an unterschiedlichen Stellen unterschiedliche Einheiten anzeigen lassen, für das selbe(!) Item.
Wenn Du QuantityType Items (also solche mit einer Einheit) innerhalb Rules verwendest, um andere Werte zu berechnen, musst Du allerdings genau aufpassen, auch die Einheit mit zu berücksichtigen (auf die eine oder andere Weise).
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Jesco
Beiträge: 9
Registriert: 10. Apr 2021 12:16
Answers: 0

Re: MQTT-Daten im JSON-Format mit korrekter Einheit umwandeln

Beitrag von Jesco »

Herzlichen Dank für die Problemlösung und die sehr ausführlichen weiteren Erläuterungen. Dann war ich bei der Konfiguration also genau falsch abgebogen. Mit dem vorgeschlagenen Weg habe ich es jetzt korrekt konfigurieren können und werde auch die weiteren Datenpunkte als separate Channels anlegen.

Antworten