json2nameValue - array's

Begonnen von RalfP, 19 Februar 2025, 15:57:09

Vorheriges Thema - Nächstes Thema

RalfP

Hallo,

innerhalb eines JSON strings kommen Daten, wie zum Beispiel
"packData":[{"power":311,"sn":"CO4HMDGME502856"},{"power":61,"sn":"CO4FHMGHM332446"}]Aufgeschlüsselt wird dies mit json2nameValue:
packData_1_sn = CO4HMDGME502856
packData_1_power = 311

packData_2_sn = CO4FHMGHM332446
packData_2_power = 61
Wenn das Array aber nur Anzahl 1 hat oder die Reihenfolge sich ändert, wird mir immer packData_1 überschrieben. Wie bekomme ich es hin, das ich immer eine eindeutige Zuordnung zur sn hätte? 
z.B.
packData_CO4HMDGME502856_sn = CO4HMDGME502856
packData_CO4HMDGME502856_power = 311

packData_CO4FHMGHM332446_sn = CO4FHMGHM332446
packData_CO4FHMGHM332446_power = 61
o.ä.

Bekommt man dies mit json2nameValue hin?

Vielen Dank für einen Tipp
Ralf

betateilchen

Sowas würde ich nicht mit json2nameValue() lösen, sondern mit einer simplen json-Auswertung in einem Stück perl code oder mit einem JsonMod-device.

  • warum willst Du überhaupt das "packData_" davor haben?
  • warum brauchst Du ein reading packData_<SN>, in dem als Wert nochmal <SN> steht?
  • würde es nicht reichen, einfach ein reading "CO4HMDGME502856_power" zu bekommen, das den Wert 311 hat?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

RalfP

Das "packData_" muss nicht sein, auch die SN muss nicht nochmals als Wert vorhanden sein, ein reading "CO4HMDGME502856_power" zu bekommen, mit dem Wert 311, wäre ausreichend. Natürlich gib es noch ein paar andere Werte in dem hash. Die eindeutige Zuordnung ist mir wichtig.

betateilchen

Zitat von: betateilchen am 19 Februar 2025, 16:14:39oder mit einem JsonMod-device.

defmod test JsonMod file:///tmp/test.json
attr test readingList multi(jsonPath('$.packData.[*]'), concat('packData_',property('sn'),'_sn'), property('sn'));;\
multi(jsonPath('$.packData.[*]'), concat('packData_',property('sn'),'_power'), property('power'));;

erzeugt folgende readings:

setstate test 2025-02-19 16:28:34 packData_CO4FHMGHM332446_power 61
setstate test 2025-02-19 16:28:34 packData_CO4FHMGHM332446_sn CO4FHMGHM332446
setstate test 2025-02-19 16:28:34 packData_CO4HMDGME502856_power 311
setstate test 2025-02-19 16:28:34 packData_CO4HMDGME502856_sn CO4HMDGME502856

In /tmp/test.json steht Dein json-String (korrekt formatiert!):

{"packData":[{"power":311,"sn":"CO4HMDGME502856"},{"power":61,"sn":"CO4FHMGHM332446"}]}
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#4
Zitat von: RalfP am 19 Februar 2025, 16:21:21ein reading "CO4HMDGME502856_power" zu bekommen, mit dem Wert 311, wäre ausreichend.

Dann lass die erste multi() Zeile in readingList einfach weg und passe das concat() in der verbleibenden Zeile an.

multi(jsonPath('$.packData.[*]'), concat(property('sn'),'_power'), property('power'))

setstate test 2025-02-19 16:36:20 CO4FHMGHM332446_power 61
setstate test 2025-02-19 16:36:20 CO4HMDGME502856_power 311

Zitat von: RalfP am 19 Februar 2025, 16:21:21Natürlich gib es noch ein paar andere Werte in dem hash. Die eindeutige Zuordnung ist mir wichtig.

Für weitere Werte wäre das Vorgehen identisch, solange die Werte im Array im gleichen Element stehen.

(Und ein hash ist was völlig anderes)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Fuer aehnliche Zwecke gibt es ein hashKeyRename in fhem.pl:
{ my $in='{"packData":[{"power":311,"sn":"CO4HMDGME502856"},{"power":61,"sn":"CO4FHMGHM332446"}]}';;\
  my $h=json2nameValue($in);;\
  $h = hashKeyRename($h, "packData_(.*)_sn:(.*)", "packData_(.*)_power");;\
  join("\n", map {"$_=$h->{$_}" } keys %{$h}) }
erzeugt:
CO4FHMGHM332446=61
CO4HMDGME502856=311

Falls man das letzte Argument fuer hashKeyRename als "(\\d+)" schreibt, dann kriegt man
packData_CO4FHMGHM332446_power=61
packData_CO4HMDGME502856_power=311
packData_CO4FHMGHM332446_sn=CO4FHMGHM332446
packData_CO4HMDGME502856_sn=CO4HMDGME502856
Das ist problematisch, falls mehrere Arrays im JSON vorkommen.

RalfP

Also, ich würde sagen, es erfüllt seinen Zweck. Das readingList im MQTT2-Device sieht jetzt so aus:
.*/xxxxxx/xxxxxx/properties/report:.* { json2nameValue($EVENT, '', $JSONMAP, undef, 'packData') }
.*/xxxxxx/xxxxxx/properties/report:.* { my $h = json2nameValue($EVENT, undef, undef, 'packData', undef); $h = hashKeyRename($h,'packData_(.*)_sn:(.*)','(\\d+)'); return $h; }
Damit habe ich alle Daten und die "packData" werden gesondert behandelt. Die Readings werden so erzeugt (z.B):
packData_CO4FHMGHM332446_power
packData_CO4FHMGHM332446_socLevel
...
packData_CO4HMDGME502856_power
packData_CO4HMDGME502856_socLevel
Das join musste ich weglassen, da eine Warnung entstand: PERL WARNING: Useless use of join or string in void context at...

Ich gestehe, so 100%'ig verstehe ich es noch nicht, aber das Ergebnis spricht für sich. Ich kann mich nur bedanken.

Einen schönen Abend wünsche ich Euch.
Ralf

rudolfkoenig

.*/xxxxxx/xxxxxx/properties/report:.* { my $h = json2nameValue($EVENT, undef, undef, 'packData', undef); $h = hashKeyRename($h,'packData_(.*)_sn:(.*)','(\\d+)'); return $h; }

Das duerfte Equivalent sein mit

.*/xxxxxx/xxxxxx/properties/report:.* { hashKeyRename(json2nameValue($EVENT,undef,undef,'packData'),'packData_(.*)_sn:(.*)','(\\d+)') }

RalfP

...sieht gut aus, funktioniert. Vielen Dank
Ralf

FHEMAN

Ich notiere hier mal Zendure dran, damit man das auch über die Suche findet. Danke für die Lösung!
NUC7i5 | PROXMOX | FHEM 6.2 | 1 HMLAND | 2 UART | HM | LMS | HIFIBERRY | DOORBIRD | BLINK | BUDERUS | HUE | ALEXA | MILIGHT | LUFTDATENINFO | MQTT| ZIGBEE2MQTT | INDEGO | ROBOROCK | SMA | APC | OPENWB

RalfP

Hab es jetzt auch in meinem Projekt https://github.com/RP-Develop/Zendure mit eigepflegt.

Grüße
Ralf