Wallbox JSON Daten verarbeiten

Begonnen von ReneR1986, 31 Dezember 2021, 14:24:46

Vorheriges Thema - Nächstes Thema

ReneR1986

Hallo zusammen,

meine Wallbox (Hardy Barth bzw. ecb1) gibt über einen HTTP Request ein entsprechendes JSON Objekt zurück.
http://192.168.1.22/api/v1/chargelogs?from=2021-03-13&to=2021-03-14

{
    "protocol-version": "1.4",
    "logs": [{
            "starttime": "2021-03-13T15:32:47",
            "duration": 707,
            "energy": 1.2170000000000001,
            "counterstop": 1.2190000000000001,
            "socket": 1,
            "uid": "",
            "counterstart": 0.002,
            "stoptime": "2021-03-13T15:44:34",
            "id": 1
        }, {
            "starttime": "2021-03-13T15:45:13",
            "duration": 854,
            "energy": 0.63,
            "counterstop": 1.854,
            "socket": 1,
            "uid": "",
            "counterstart": 1.224,
            "stoptime": "2021-03-13T15:59:27",
            "id": 2
        }, {
            "starttime": "2021-03-13T15:59:43",
            "duration": 607,
            "energy": 0.447,
            "counterstop": 2.302,
            "socket": 1,
            "uid": "",
            "counterstart": 1.854,
            "stoptime": "2021-03-13T16:09:50",
            "id": 3
        }, {
usw..

Ich möchte nun die Werte aller "energy" Attribute addieren, um eine Summe zu erhalten.
Meine Idee war das Über HTTMOD zu lösen. Allerdings bekomme ich es nur hin, entsprechende einzel Readings für jedes Attribut erzeugen zu lassen.

define WallboxLogs HTTPMOD http://192.168.1.22/api/v1/chargelogs?from=2021-03-13&to=2021-03-14 0
attr WallboxLogs getHeader1 Content-Type: application/json
attr WallboxLogs getHeader2 Accept: */*
attr WallboxLogs extractAllJSON

Ich hätte gerne den "Raw" Output von oben in einem Reading, damit ich dann den Inhalt an eine eine Perl Funktion übergeben kann und das ganze dann nach dem Muster:

https://stackoverflow.com/questions/11641954/loop-over-json-using-perl

auslesen kann und wieder in ein Reading schreiben kann.

Hat einer eine Idee, wie ich den Raw JSON Output bekomme oder gibt es noch elegantere Möglichkeiten?

Vielen Dank!

TomLee

#1
Zitatoder gibt es noch elegantere Möglichkeiten?


Hallo,

mit Sicherheit kann man das ganz einfach mit einer HTTMOD-Definition angehen, damit hab ich mich aber bisher zu wenig mit beschäftigt.

Zwei alternative Varianten kann ich aufzeigen, allerdings ohne der Ausgabe des "Raw-Output".

Einmal mit einem ganz simplen AT iVm. der Funktion json2reading:

defmod Demo_at_j2r_jsnmap_sum at +*01:00 {HttpUtils_NonblockingGet({ url=>"http://192.168.1.22/api/v1/chargelogs?from=2021-03-13&to=2021-03-14",callback=>sub($$$){json2reading($defs{Demo_at_j2r_jsnmap_sum},$_[2],"",'my $hf ={logs_1_energy=>"bli_energy",logs_2_energy=>"bla_energy",logs_3_energy=>"blub_energy"}',undef,"energy")}})}
attr Demo_at_j2r_jsnmap_sum alignTime 00:00
attr Demo_at_j2r_jsnmap_sum room Test
attr Demo_at_j2r_jsnmap_sum userReadings Summe:bli_energy.* { my $sum;;\
for ( keys %{$defs{$name}->{READINGS}} ) {\
$sum += ReadingsNum($name, $_, 0, 2) if ($_ =~ 'energy');;\
} return $sum;; }

setstate Demo_at_j2r_jsnmap_sum Next: 11:00:00
setstate Demo_at_j2r_jsnmap_sum 2022-01-01 10:03:17 Summe 2.29
setstate Demo_at_j2r_jsnmap_sum 2022-01-01 10:03:17 bla_energy 0.63
setstate Demo_at_j2r_jsnmap_sum 2022-01-01 10:03:17 bli_energy 1.2170000000000001
setstate Demo_at_j2r_jsnmap_sum 2022-01-01 10:03:17 blub_energy 0.447
setstate Demo_at_j2r_jsnmap_sum 2022-01-01 10:26:48 state Next: 11:00:00


Und einmal ein etwas schräger Ansatz es in Kombination mit einem MQTT2_DEVICE anzugehen (falls schon im Einsatz), dessen Attribute man zum einstellen des Intervalls und mappen der Readingnamen "missbrauchen" kann.

defmod Demo_m2d_j2r_jsnmap_sum MQTT2_DEVICE bliblablub
attr Demo_m2d_j2r_jsnmap_sum jsonMap logs_1_energy:bli_energy logs_2_energy:bla_energy logs_3_energy:blub_energy
attr Demo_m2d_j2r_jsnmap_sum periodicCmd off:60
attr Demo_m2d_j2r_jsnmap_sum room Test
attr Demo_m2d_j2r_jsnmap_sum setList off:noArg {HttpUtils_NonblockingGet({ url=>"http://192.168.1.22/api/v1/chargelogs?from=2021-03-13&to=2021-03-14",callback=>sub($$$){json2reading($defs{Demo_m2d_j2r_jsnmap_sum},$_[2],"",$defs{Demo_m2d_j2r_jsnmap_sum}{JSONMAP},undef,"energy")}})}
attr Demo_m2d_j2r_jsnmap_sum userReadings Summe:bli_energy.* { my $summe;;\
for ( keys %{$defs{$name}->{READINGS}} ) {\
$summe += ReadingsNum($name, $_, 0, 2) if ($_ =~ 'energy');;\
} return $summe;; }

setstate Demo_m2d_j2r_jsnmap_sum on
setstate Demo_m2d_j2r_jsnmap_sum 2021-12-31 22:06:20 IODev mqtt2Cloud
setstate Demo_m2d_j2r_jsnmap_sum 2021-12-31 20:49:43 Summe 2.29
setstate Demo_m2d_j2r_jsnmap_sum 2021-12-31 20:49:43 bla_energy 0.63
setstate Demo_m2d_j2r_jsnmap_sum 2021-12-31 20:49:43 bli_energy 1.2170000000000001
setstate Demo_m2d_j2r_jsnmap_sum 2021-12-31 20:49:43 blub_energy 0.447



Frohes Neues

Thomas

ReneR1986

Hallo Thomas,

ebenfalls ein frohes neues und danke für die Lösungsansätze. Das muss ich mir einmal in Ruhe anschauen, um zu verstehen was genau da passiert. Auf den ersten Blick, sieht es allerdings so aus, als wenn man von vornherein fest vorgeben muss, wie häufig das Attribut Energy vorkommt. Das kann allerdings durchaus unterschiedlich sein.

Vielen Dank

Gruß Rene

TomLee

ZitatAuf den ersten Blick, sieht es allerdings so aus, als wenn man von vornherein fest vorgeben muss, wie häufig das Attribut Energy vorkommt. Das kann allerdings durchaus unterschiedlich sein.

Nein, zu allen Objekten deren Inhalt der Name energy hat wird fortlaufend ein Reading logs_x_energy erstellt.
Was man händisch anpassen muss wären die Namen dieser automatisch angelegten Reading, wenn man das überhaupt braucht/möchte.

Was mich jetzt irritiert ist :
ZitatDas kann allerdings durchaus unterschiedlich sein.

Sind es mal mehr mal weniger Objekte in dem Json ?
Muss man die Summe als Zwischenergebnis sehen und wegspeichern, die Readings immer löschen vor dem nächsten Intervall ?

TomLee

ZitatWas man händisch anpassen muss wären die Namen dieser automatisch angelegten Reading, wenn man das überhaupt braucht/möchte.

Hier eine Definition ohne Mapping der Readingnamen, einfach nur zum Verständnis/nachvollziehen.

Einfach so wie gezeigt die Definition in einen Raw-Editor werfen, anschlissend im Device ein execNow ausführen und es werden zu jedem Objekt die logs_x_energy-Readings angelegt und daraus die Summe mit dem userReadings gebildet.

defmod Demo_at_j2r_nonjsnmap_sum at +*01:00 {HttpUtils_NonblockingGet({ url=>"http://192.168.1.22/api/v1/chargelogs?from=2021-03-13&to=2021-03-14",callback=>sub($$$){json2reading($defs{Demo_at_j2r_nonjsnmap_sum},$_[2],'',undef,undef,"energy")}})}
attr Demo_at_j2r_nonjsnmap_sum room Test
attr Demo_at_j2r_nonjsnmap_sum userReadings Summe:bli_energy.* { my $sum;;\
for ( keys %{$defs{$name}->{READINGS}} ) {\
$sum += ReadingsNum($name, $_, 0) if ($_ =~ 'energy');;\
} return $sum;; }

setstate Demo_at_j2r_nonjsnmap_sum Next: 13:19:12
setstate Demo_at_j2r_nonjsnmap_sum 2022-01-01 12:19:19 logs_1_energy 1.2170000000000001
setstate Demo_at_j2r_nonjsnmap_sum 2022-01-01 12:19:19 logs_2_energy 0.63
setstate Demo_at_j2r_nonjsnmap_sum 2022-01-01 12:19:19 logs_3_energy 0.447
setstate Demo_at_j2r_nonjsnmap_sum 2022-01-01 12:19:12 state Next: 13:19:12



ReneR1986

OK,
das scheint hinzuhauen!

Noch einmal zum Verständnis:
Welche Parameter werden der json2reading Funktion übergeben? Das ist mir nicht ganz klar.
Ich habe, bis auf ein paar andere Foreneinträge, keine Definition für json2reading gefunden.

Was passiert im userReading? Es wird addiert, ist klar aber den Aufbau habe ich noch nicht ganz verstanden:

Summe:bli_energy.* { my $sum;;\
for ( keys %{$defs{$name}->{READINGS}} ) {\
$sum += ReadingsNum($name, $_, 0) if ($_ =~ 'energy');;\
} return $sum;; }

VG

René


TomLee

#6
ZitatWelche Parameter werden der json2reading Funktion übergeben? Das ist mir nicht ganz klar.
Ich habe, bis auf ein paar andere Foreneinträge, keine Definition für json2reading gefunden.
Die Funktion ist nicht dokumentiert, muss man sich anhand des Code in fhem.pl ableiten oder aus den wenigen Beiträgen die es dazu gibt.

Ich versuchs mal zu erklären:

Parameter 1 ist ein "Zeiger" auf einen Hash (Devicename), Parameter 2 der Json selbst, Parameter 3 ein Prefix der jedem Reading vorangestellt wird, Parameter 4 erwartet eine Referenz auf einen Hash (mapping der Readings), Parameter 5 keine Ahnung, Parameter 6 ist ein Filter (nach den Namen in dem Objekt), die Angabe ist ein regexp.

ZitatWas passiert im userReading? Es wird addiert, ist klar aber den Aufbau habe ich noch nicht ganz verstanden:


Summe:bli_energy.* # Das userReadings wird nur ausgeführt bei irgendeiner Änderung am Reading bli_energy

my $sum;; # definiere eine leere Variable (0,undef)

for ( keys %{$defs{$name}->{READINGS}} ) # Schleife über Array welches von keys %{$defs{$name}->{READINGS}} zurückgegeben wird, %{$defs{$name}->{READINGS}} ist die Referenz auf alle Readingnamen des Devices

{$sum += ReadingsNum($name, $_, 0) if ($_ =~ 'energy');;} # addiere bei jedem Schleifendurchlauf den Inhalt des Readings zur Summe, aber nur wenn das Reading energy im Namen enthält, $_ ist die Umlaufvariable der Schleife der Inhalt ist der Schlüssel aus dem Hash (Readingname)

return $sum;; # gib die Endsumme aus

Ich korrigiere gerne wenn ich falsche Begrifflichkeiten verwendet haben sollte, erklären ist nicht so meine Stärke.

rudolfkoenig

ZitatParameter 1 ist ein "Zeiger" auf einen Hash (Devicename), Parameter 2 der Json selbst, Parameter 3 ein Prefix der jedem Reading vorangestellt wird, Parameter 4 erwartet eine Referenz auf einen Hash (mapping der Readings), Parameter 5 keine Ahnung, Parameter 6 ist ein Filter (nach den Namen in dem Objekt), die Angabe ist ein regexp.

json2reading ist ein Wrapper um json2nameValue.
Parameter 5 ermoeglicht die Nachbearbeitung der Werte, im folgenden Beispiel mit hashKeyRename, ebenfalls undokumentiert :)
fhem> define d dummy
fhem> { json2reading($defs{d}, '[{"name":"temperature","value":"12.1"}, {"name":"humidity","value":"50 %"}]', undef, undef, 'hashKeyRename($ret, "^([0-9]+)_name:(.*)","^([0-9]+)_value")') }
fhem> list -r d
define d dummy

setstate d 2022-01-01 15:28:31 humidity 50 %
setstate d 2022-01-01 15:28:31 temperature 12.1

ReneR1986

OK, besten Dank für die Erklärungen!

Ich nehme an, dass userReading muss ich in dem Fall anpassen von:

Summe:bli_energy.* nach
logs_.*

und auch hier:
Zitat{$sum += ReadingsNum($name, $_, 0) if ($_ =~ 'energy');;} # addiere bei jedem Schleifendurchlauf den Inhalt des Readings zur Summe, aber nur wenn das Reading energy im Namen enthält,

~ 'energy' durch logs ersetzen?

?
Zitat$_ ist die Umlaufvariable der Schleife der Inhalt ist der Schlüssel aus dem Hash (Readingname)
Ist das der Wert der in Keys steht?

Wahrscheinlich brauche ich eher Perl Nachhilfe :-)



TomLee

ZitatIch nehme an, dass userReading muss ich in dem Fall anpassen von:

Summe:bli_energy.* nach
logs_.*

Nein, du setzt du den trigger immer nur auf genau ein Reading an, ins Blaue, weil kein List (besser Raw), das könnte bspw. logs_1_energy.* sein wenn du kein Mapping vorgenommen hast.

Zitat~ 'energy' durch logs ersetzen?

In dem Fall ist das Jacke wie Hose, Schnurz. Solange du logs nicht im Summe-userReadings verwendest.

ZitatIst das der Wert der in Keys steht?

In der Umlaufvariablen steht der Schlüssel ja.

ReneR1986

Alles klar,
Danke!
Probiere ich aus!

TomLee

ZitatIn der Umlaufvariablen steht der Schlüssel ja.

Vlt. nochmal etwas weiter ausgeholt, weil ich das oben falsch beschrieben hatte und nachträglich korrigiert.

Wenn man es ganz genau nimmt steht in der Umlaufvariable das gerade zu iterierende Element aus dem Array welches von keys %{$defs{$name}->{READINGS}} zurückgegeben wird und der Inhalt des Arrays sind halt die Schlüssel.

Macht man eine Schleife über einen Hash dann kann der Schlüssel auch direkt in der Umlaufvariablen sein, hat nix mit der Sache zu tun, nur so zum Verständnis.

Hoffe habs selbst richtig verstanden und erzähle keinen Blödsinn  ;D


ReneR1986

Alles klar,

danke für die Erklärung!