LoRaWAN Sensor - JSON Format

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
neuling10
Beiträge: 71
Registriert: 26. Mär 2022 18:15
Answers: 0

LoRaWAN Sensor - JSON Format

Beitrag von neuling10 »

Hallo an die Runde,

ich habe mir kürzlich einen LoRaWAN Multisensor geholt, mit dem ich Zustandsbedingungen (Temperatur, Luftfeuchtigkeit, Bewegung (0 oder 1), Batteriespannung des Sensors) im Keller überwachen möchte (kein WLAN). Über The Things Network bekomme ich via MQTT Schnittstelle bereits ein JSON geliefert. Mit dem JSONPATH Profile und dem JSONPath Ausdruck erhalte ich grundsätzlich die gewünschten Werte :)

Frage 1:
Wenn z.B. der Bewegungssensor von 0 auf 1 schaltet (Bewegung erkannt), wird vom Sensor ein JSON ohne aller weiteren gewünschten Werte übermittelt. Es wird also nur jener Wert im JSON gesendet, der sich ändert. Dies führt dazu, dass alle anderen Items nicht transformiert werden können, da ja im JSON z.B. kein Temperatur Wert steckt => Im Item habe ich nun wieder den gesamten JSON Ausdruck. Gewünscht ist einfach der zuletzt übermittelte Temperaturwert. Wenn im JSON kein Temperatur-Wert steckt, soll sich das Item nicht ändern. Kann man das irgendwie im Channel einstellen oder benötige ich z.B. eine Rule, um mein gewünschtes Vorhaben umzusetzen?
jsonpath_sensor_keller.JPG
Frage 2:
Alle Items habe ich als String eingebunden. Ich würde jedoch gerne alle Messwerte persistieren, was ja mit String logischerweise nicht funktioniert. Muss ich nun die Items z.B. mittels Rule auf einen numerischen Wert umwandeln, der persistiert werden kann?

Danke für Euren Input zu meiner Herausforderung :D

Grüße
neuling10
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

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

Re: LoRaWAN Sensor - JSON Format

Beitrag von udo1toni »

Das ist keine große Herausforderung :) Leider hast Du allerdings versäumt, die Konfiguration Deines Things (als Text!) mitzuliefern.

Zu Frage 1: Du musst die Daten alle in einzelnen Channels zur Verfügung stellen. Du legst passende Channel an und trägst als transformationPattern ein passendes REGEX, verknüpft mit JSONPATH ein. Das geht nicht im Profile, hier kannst Du nur eine Transformation vornehmen (natürlich könntest Du im Profile JS verwenden und innerhalb des Scripts dann die Verknüpfung vornehmen, aber so ist das halt nicht gedacht...)
Zu Frage 2: Du musst den Channeltyp passend und korrekt definieren, nicht als String, sondern (für Zahlenwerte) als Number. Da es sich um ein generic mqtt Thing handelt, solltest Du außerdem die korrekte Einheit (unit) setzen, und zwar die, in der der Wert vom Sensor geliefert wird.
Anschließend kannst Du dann den jeweiligen Channel mit einem passenden Item verlinken.
Wenn Du die aktuelle Konfiguration des Things und ein vollständiges JSON (also mit allen Schlüsselworten) postest, kann ich Dir das am konkreten Beispiel zeigen.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

neuling10
Beiträge: 71
Registriert: 26. Mär 2022 18:15
Answers: 0

Re: LoRaWAN Sensor - JSON Format

Beitrag von neuling10 »

Danke schon mal für die Tipps Udo, auch wenn ichs noch nicht geschafft habe :? . Für deine weitere Hilfe wäre ich sehr dankbar

Wie funktioniert das mit einem REGEX und verknüpften JSONPATH bzw. wie sieht der Ausdruck aus? Schreibe ich da den Ausdruck in den Channel in "Outgoing Value Transformation"? Und für die Temperatur in "Outgoing Value Format" z.B. %.1f °C für die Temperatur in Grad Celsius mit einer Nachkommastelle?
Im Item kann ich dann Profil Standard belassen?


Hier der Code des Things. Einen zweiten Channel mit Typ Number habe ich schon mal angelegt, den ersten String Channel habe ich noch nicht gelöscht.

Code: Alles auswählen

UID: mqtt:topic:5b701a1f9e:c8e9525e6b
label: Sensor Keller
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:5b701a1f9e
channels:
  - id: SensorKeller
    channelTypeUID: mqtt:string
    label: Sensor Keller
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
  - id: Sensor_Keller_Temperatur
    channelTypeUID: mqtt:number
    label: Sensor Keller Temperatur
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up

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

Re: LoRaWAN Sensor - JSON Format

Beitrag von udo1toni »

Jeder Channel bietet grundsätzlich zwei Richtungen, kommend und gehend, oder auf englisch incomming und outgoing.
Hier hast Du ausschließlich kommende Daten.
Leider fehlt noch das JSON, ohne das wird's nichts werden :), wobei Du natürlich auch die jeweiligen Zeilen aus den Profiles kopieren und hier einfügen kannst.
Aber als Beispiel:

Code: Alles auswählen

UID: mqtt:topic:5b701a1f9e:c8e9525e6b
label: Sensor Keller
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:5b701a1f9e
channels:
  - id: SensorKeller
    channelTypeUID: mqtt:string
    label: Sensor Keller json
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
  - id: Sensor_Keller_Temperatur
    channelTypeUID: mqtt:number
    label: Sensor Keller Temperatur
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
      transformationPattern: REGEX:(.*temperature.*)∩JSONPATH:$.blah.bli.blub.temperature
      unit: d°C
transformationPattern ist die "incomming Transformation".
REGEX ist die erste Transformation. der Wert in Klammern wird weitergegeben, hier also der gesamte String, allerdings nur, sofern er die Zeichenfolge "temperature" enthält. das Zeichen heißt im englischen Intersection und ist in Windows in der Zeichentabelle falsch mit Durchschnitt übersetzt worden (korrekt wäre Schnittmenge).
Du kannst das Zeichen aber auch einfach aus dem zugehörigen Hilfetext in der UI kopieren :)
Das Ergebnis der ersten Transformation wird nun also an die zweite Transformation weitergereicht, das ist entweder das komplette JSON (sofern eben das Schlüsselwort auftaucht) oder eine leere Zeichenkette.
JSONPATH sucht dann den passenden Wert aus dem JSON Objekt heraus, im Beispiel im Pfad blah.bli.blub.temperature (den echten Path hast Du ja schon im Profile stehen).
Da der Channel vom Typ number ist, steht außerdem noch der Parameter unit zur Verfügung, hier mit d°C (Dezigrad Celsius), der Wert 217 entspräche damit 21,7 °C. Wird der Wert anders dargestellt, kannst Du die Einheit natürlich auch anders angeben, also z.B. °F, K oder eben °C :)
Das dazu passende Item wäre dann vom Typ Number:Temperature und auch dort solltest Du in den Metadaten den Parameter unit gezielt auf etwas Sinnvolles setzen, z.B. °C. In dieser Einheit speichert openHAB dann den Wert im Item (und somit auch in den verknüpften Persistences).
Die unit im Channel ist abhängig von der Hardware, bzw. wie der Wert angeliefert wird. Die unit im Item kannst Du komplett frei wählen, soweit sie zur gelieferten Einheit passt, hier also eine Temperatur-Einheit, egal welche. Aber Obacht! Du darfst diese unit nur einmal setzen! (Du kannst sie natürlich auch später ändern, aber das hat dann Auswirkungen...) Insofern ist es sinnvoll, hier nicht zu experimentieren (allenfalls mit Items, die Du später wieder entsorgst).
Wie der Wert später angezeigt wird, kannst Du dann - unabhängig von den beiden bisherigen Angaben - über die Metadaten des Items (State Description - Pattern) festlegen, z.B. so:

Code: Alles auswählen

%.1f °C
Bedeutet: Der Wert (vertreten durch %) mit einer Nachkommastelle (.1), als Float (f) in der Einheit °C.
Dabei ist es, wie erwähnt, gleichgültig, in welcher Einheit der Wert aus dem Channel kommt oder auch im Item gespeichert wird, openHAB rechnet vollautomatisch um.
Die State Description wirkt übrigens nicht in der Itemliste, dort wird immer der "Rohwert" angezeigt (und das mit voller Absicht!), ansonsten wird aber für die Anzeige immer die State Description herangezogen, soweit das möglich ist (Nicht möglich wäre es z.B. für ungültige Werte UNDEF oder NULL).
Im Unterschied zu den beiden units von oben kannst Du die State Description jederzeit und beliebig oft ändern.

Ganz wichtig (weil es schon falsch gemacht wurde...) ist, dass nun im Link das Standard Profile (= keinerlei Beeinflussung) gesetzt wird, denn nun kommt ja kein JSON Objekt mehr an, sondern ein diskreter einheitenbehafteter Wert.

Es versteht sich von selbst, dass neben MQTT und JSONPATH auch REGEX installiert sein muss :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

neuling10
Beiträge: 71
Registriert: 26. Mär 2022 18:15
Answers: 0

Re: LoRaWAN Sensor - JSON Format

Beitrag von neuling10 »

Vielen lieben Dank für die ausgezeichnete Erklärung :D

Die Bewegungserkennung habe ich mit einem Switch gelöst. Ich nehme an das ist so korrekt konfiguriert, wenn der Sensor 0 oder 1 liefert?

Eine Kleinigkeit hab ich nun noch zur Unit:
Das mit den d°C hab ich versucht, dies funktioniert und ich erhalte z.B. 2,1°C ausgegeben (als Dezigrad). Dies habe ich natürlich wieder geändert auf Unit °C, um 21°C angezeigt zu bekommen.
Als Wert für die Batteriespannung erhalte ich vom Sensor Millivolt, also z.B. 1700 für den Wert 1,7V, welchen ich gerne angezeigt hätte. Nun hab ich in der Unit of Measurement im Channel mal "dV" und "mV" eingetragen, es wird jedoch immer "1700" angezeigt. Was ist da falsch bzw wo rechne ich nun korrekterweise um? Die State Description Pattern im Item habe ich auf %.1f V gestellt.

Code: Alles auswählen

UID: mqtt:topic:5b701a1f9e:c8e9525e6b
label: Sensor Keller
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:5b701a1f9e
channels:
  - id: Sensor_Keller_Temperatur
    channelTypeUID: mqtt:number
    label: Sensor Keller Temperatur
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
      transformationPattern:
        - REGEX:(.*TEMP.*)∩JSONPATH:$.uplink_message.decoded_payload.TEMP
      unit: °C
  - id: Sensor_Keller_Luftfeuchtigkeit
    channelTypeUID: mqtt:number
    label: Sensor Keller Luftfeuchtigkeit
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
      transformationPattern:
        - REGEX:(.*RHUM.*)∩JSONPATH:$.uplink_message.decoded_payload.RHUM
      unit: "%"
  - id: Sensor_Keller_Batteriespannung
    channelTypeUID: mqtt:number
    label: Sensor Keller Batteriespannung
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
      transformationPattern:
        - REGEX:(.*VBAT.*)∩JSONPATH:$.uplink_message.decoded_payload.VBAT
      unit: dV
  - id: Sensor_Keller_Bewegung
    channelTypeUID: mqtt:switch
    label: Sensor Keller Bewegung
    description: ""
    configuration:
      stateTopic: v3/b37058d500100000@ttn/devices/whg-sensor-keller/up
      transformationPattern:
        - REGEX:(.*OCCU0_STATE.*)∩JSONPATH:$.uplink_message.decoded_payload.OCCU0_STATE
      off: "0"
      on: "1"
Eine Verständnisfrage noch:
Die "Unit of Measurement" im Channel sorgt mir dafür, die erhaltenen Messwerte samt Einheit korrekt in der Datenbank abzulegen (falls persistiert). Die State Description Pattern im Item könnte dies "überschreiben" - zwar nicht die Rohwerte in der Datenbank, aber wenn ich z.B. die Items auf einer Page visualisiere, erhalte ich sie immer mit den State Description Pattern angezeigt.
Ich hoffe das war halbwegs verständlich formuliert und ich habs nun richtig verstanden :D

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

Re: LoRaWAN Sensor - JSON Format

Beitrag von udo1toni »

neuling10 hat geschrieben: 28. Dez 2024 23:55 Eine Verständnisfrage noch:
Ja (falls ich Dich richtig verstanden habe) :)
UoM sorgt einfach dafür, dass man sich sämtliche Umrechnungen ersparen kann.
Im Channel muss man die Unit angeben, damit openHAB weiß, in welcher Einheit der Wert hereinkommt. das ist natürlich nur bei den Bindings notwendig, die "zu generell" sind und deshalb nicht wissen können, welche Einheit angeliefert wird.
Im Item muss man die Einheit angeben, damit openHAB weiß, in welcher Einheit es den Wert speichern soll - das wirkt auch auf die Persistence, aber z.B. auch auf Rules. Man kann in Rules auch mit QuantityType (das ist der Datentyp hinter UoM) arbeiten, aber oftmals ist es einfacher, die mitgelieferte Einheit zu "strippen" und mit der nackten Zahl weiterzurechnen. Das geht natürlich nur, wenn die Zahl auch passend im Item gespeichert ist.
Und die Anzeige ist halt die Anzeige, die kannst Du nach Belieben einstellen und verändern.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

neuling10
Beiträge: 71
Registriert: 26. Mär 2022 18:15
Answers: 0

Re: LoRaWAN Sensor - JSON Format

Beitrag von neuling10 »

Ich habe die Infrastruktur meines LoRaWAN Projekts nochmals grundlegend geändert und habe nun leider wieder ein kleines Problem mit der JS-Tranformation.

Kurz zur Änderung: Ich habe die Möglichkeit entdeckt, direkt von meinem LoRaWAN Gateway Sensorwerte zu meinem lokalen MQTT Server zu übertragen. Somit muss ich nicht mehr die Daten ins Internet zu The Things Network senden, was mir auch Konfigurationsvorteile bringt (z.B. Datenübertragung der Sensorwerte mit Spread Factor 12 möglich für höhere Reichweite / Gebäudedurchdringung). Der Nachteil ist, dass das LoRaWAN Gateway nur ein Payload Decoder File für alle Sensoren akzeptiert, d.h. ich musste mir ein Payload File aus zwei separaten von Dragino und Thermokon schnitzen. Dies funktioniert soweit. Alle Sensoren senden somit über das idente MQTT Topic:

Code: Alles auswählen

gateway/uplink
Um die Sensoren unterscheiden zu können, lasse ich mir zu jeder Datenübertragung eines Sensors seinen Device Name mit übertragen. Dies sieht beispielsweise folgendermaßen aus:

Code: Alles auswählen

{
  "TEMP": 10.1,
  "deviceName": "Sensor_Keller",
  "rssi": -119,
  "snr": -15.5,
  "spreadFactor": 11
}


Meine Incoming Value Transformation sieht für die Temperatur folgendermaßen aus

Code: Alles auswählen

REGEX:(.*TEMP.*)∩JSONPATH:$.TEMP
Kann man die Incoming Value Transformation irgendwie erweitern, um den Temperaturwert nur zu aktualisieren, wenn der "deviceName" dem Wert "Sensor_Keller" entspricht und natürlich auch ein TEMP Wert gesendet wurde? Falls ich richtig recherchiert habe, müsste ich mit dem Ausdruck unterhalb abfragen können, ob TEMP und deviceName enthalten sind. Wie kann ich aber die Anfrage auch noch um die Bedingung deviceName entspricht "Sensor_Keller" erweitern?

Code: Alles auswählen

REGEX:(.*TEMP.*)(.*deviceName.*)∩JSONPATH:$.TEMP
Grüße
neuling10

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

Re: LoRaWAN Sensor - JSON Format

Beitrag von udo1toni »

Ja, das ist grundsätzlich kein Problem.Da Du die Sendeseite auch unter voller Kontrolle hast, kannst Du Dich auf die Reihenfolge der übergebenen Werte verlassen, dann sähe ein passender Filter z.B. so aus:

Code: Alles auswählen

REGEX:(.*TEMP.*Sensor_Keller.*)∩JSONPATH:$.TEMP
Es geht nur darum, dass sowohl die Zeichenfolge TEMP als auch die Zeichenfolge Sensor_Keller im übergebenen String in dieser Reihenfolge vorkommen - mit beliebig vielen (*) beliebigen (.) Zeichen zwischen diesen beiden Zeichenfolgen.

Kann die Reihenfolge nicht garantiert werden, ist es besser, zwei REGEX Ausdrücke zu verwenden:

Code: Alles auswählen

REGEX:(.*TEMP.*)∩REGEX:(.*Sensor_Keller.*)∩JSONPATH:$.TEMP
Der erste REGEX Ausdruck gibt den vollständigen String weiter, wenn die Zeichenfole TEMP enthalten ist, der zweite REGEX Ausdruck gibt den vollständigen String weiter, wenn die Zeichenfolge Sensor_Keller enthalten ist - egal in welcher Position zur Zeichenfolge TEMP.
Wie schon bisher, so gilt auch hier: sobald ein REGEX Ausdruck nicht matcht, reicht er einen leeren String weiter. JSONPATH erkennt in diesem Fall, dass es kein Update des Channels (bzw. nachfolgender Transformations) vornehmen darf.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten