json2reading im Userreading nutzen ohne expandJSON Modul

Begonnen von Tobias, 07 Mai 2024, 09:04:56

Vorheriges Thema - Nächstes Thema

Tobias

Hi,
ich habe jetzt neu einen "Shelly Plus PM Mini" am laufen. Dieser liefert alle Werte zusammen in einem JSON. Alle meine vielen anderen "alten" Shellies liefern jeden Einzelwert in einem eigenen Topic. Das stellt mich vor die Herausforderung jetzt noch zusätzlich das JSON parsen zu müssen um jeden Wert in einem einzelnen Reading zu haben.
Dazu habe ich mich bzgl json2reading schon schlau gemacht. Ist eigentlich genau das was ich brauche. Ich habe auch das Modul ExpandJson gefunden, möchte es aber nicht einsetzen da es wieder ein neues Modul ist und für jedes MQTT Device mit JSON-NAchrichten ein ExpandJson MOdul dazu gestellt werden muss.

Wie auch immer, ich habe alles so vorbereitet:
defmod PM_KG_Waschmaschine MQTT_DEVICE
attr PM_KG_Waschmaschine IODev mqtt
attr PM_KG_Waschmaschine subscribeReading_data shelly_kg_waschmaschine/status/pm1:0
attr PM_KG_Waschmaschine userReadings dummy {json2reading($defs{$name},ReadingsVal($name, "data", "{}"),"",undef,"","apower")}

Im Data Reading steht folgendes drin:
{"id":0, "voltage":235.4, "current":0.000, "apower":0.0 ,"freq":50.0,"aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259},"ret_aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259}}
Der json2reading Aufruf funktioniert bestens in der Commandline, im Userreading kommt aber folgdener Fehler:
Error evaluating PM_KG_Waschmaschine userReading dummy: syntax error at (eval 300068076) line 1, at EOF
Missing right curly or square bracket at (eval 300068076) line 1, at end of line

Ich habe keine Ahnung wo da eine schließende Klammer fehlen soll. Kann mir jemand einen Tipp geben? Oder kann man "json2reading" eventuell besser im MQTT-Device einbauen?
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Beta-User

Hmmm, warum es direkt klappt, und in der userReadings-Variante nicht, kann ich auch nicht genau sagen, aber uU. macht das "Redaing-update im Reading-update" Probleme? (Kann vielleicht Rudi besser beantworten, wenn ein Blick in die trigger- und update-Funktionen von fhem.pl nicht weiter hilft).

Prinzipielle Anmerkungen:
- ExpandJson kann afaik auch mehrere Devices auspacken, allerdings ist es uU. halt etwas komplexer, wenn man arg filtern will.
- U.a. wegen dieser ganzen Probleme mit JSON hat Rudi die MQTT2-Module gebaut. In dem Rahmen ist afaik auch json2reading() entstanden. Es wäre uU. einfacher, zumindest die neuen Shelly-Devices (mit ihrer sehr speziellen MQTT-Schnittstelle....) mit MQTT2-Methoden zu verarbeiten (oder das Shelly-Modul zu bemühen).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

betateilchen

Was ist denn die eigentliche Aufgabe?

Du willst aus dem eingehenden json ein reading erzeugen, das den Wert aus "apower":0.0 enthält?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

ZitatIch habe keine Ahnung wo da eine schließende Klammer fehlen soll.

Can of worms.

#1:
mit userreadings kann man gleich mehrere Readings setzen, der Trenner ist },
Ausgewertet wird damit {json2reading($defs{$name}
Das mit dem Trenner war nicht meine Idee :)
=> Weiter kommt man mit
attr X userReadings dummy {my $dHash=$defs{$name};; json2reading($dHash,ReadingsVal($name, "data", "{}"),"",undef,"","apower")}

#2:
Das "Weiter" bedeutet eine Endlosschleife, weil json2readings erneut die userReadings Auswertung aufruft.
userReadings Filtern hilft nicht, weil data noch in der CHANGED Liste drin ist, weil userReadings die Events erweitern soll, bevor die eigentliche Event-Verarbeitung durch notify/etc anlaeuft.
Mit json2readings im notify gibts zwar keine Endlosschleife, aber auch keine weiteren Events, d.h. apower kann man nicht direkt weiterverwenden.

Ich habe fhem.pl erweitert, damit eine userReading Berechnung aus der gleichen Berechnung nicht erneut aufgerufen werden kann.
Entweder ab sofort aus svn, oder ab morgen per FHEM update.

betateilchen

Zitat von: betateilchen am 07 Mai 2024, 10:54:36Du willst aus dem eingehenden json ein reading erzeugen, das den Wert aus "apower":0.0 enthält?

sub jt {
  my $j = '{"id":0, "voltage":235.4, "current":0.000, "apower":0.0 ,"freq":50.0,"aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259},"ret_aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259}}';
  return (json2nameValue($j))->{apower};
}
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Die "saubere" Methode waere ein apower userReading mit data als trigger zu definieren und den Wert mit betateilechens Methode (s.o) zu berechnen:
attr X userReadings apower:data:.* {json2nameValue($eventValue)->{apower}}

Tobias

Zitat von: rudolfkoenig am 07 Mai 2024, 11:52:00Die "saubere" Methode waere ein apower userReading mit data als trigger zu definieren und den Wert mit betateilechens Methode (s.o) zu berechnen:
attr X userReadings apower:data:.* {json2nameValue($eventValue)->{apower}}

Danke Rudi, genau damit funktioniert es perfekt.

defmod PM_KG_Waschmaschine MQTT_DEVICE
attr PM_KG_Waschmaschine DbLogExclude .*
attr PM_KG_Waschmaschine IODev mqtt
attr PM_KG_Waschmaschine stateFormat power W
attr PM_KG_Waschmaschine subscribeReading_data shelly_kg_waschmaschine/status/pm1:0
attr PM_KG_Waschmaschine userReadings power:data:.* {json2nameValue($eventValue)->{apower}}
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Tobias

Ich frag hier ergänzend nochmal nach.

Ich möchte nun neben dem "apower" auch den "total" Wert von "aenergy" haben. Leider bekomme ich es nicht hin bzw ohne irgendeine Fehlermeldung wird mein "consumption" Feld einfach nicht befüllt.

{"id":0, "voltage":234.1, "current":0.000, "apower":0.0 ,"freq":50.0,"aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1722250739},"ret_aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1722250739}}
attr shelly_pm_klima userReadings power:data:.* {json2nameValue($eventValue)->{apower}}, consumption:data:.* {json2nameValue($eventValue)->{aenergy}{total}}
KÖnnt ihr mir nochmal einen Tipp geben?
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

betateilchen

(json2nameValue($eventValue))->{aenergy_total}
Achtung: das aenergy_total hat nicht mehr viel mit originärem json zu tun, das ist json2nameValue() spezifisch
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: Tobias am 29 Juli 2024, 13:06:03Könnt ihr mir nochmal einen Tipp geben?

Einen hab ich noch...

sub jt {
  use Data::Dumper;
  my $j = '{"id":0, "voltage":235.4, "current":0.000, "apower":0.0 ,"freq":50.0,"aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259},"ret_aenergy":{"total":0.000,"by_minute":[0.000,0.000,0.000],"minute_ts":1715065259}}';
  return Dumper json2nameValue($j);
}

Damit bekommst Du die keys der hash-Elemente raus.

$VAR1 = {
          'ret_aenergy_by_minute_3' => '0.000',
          'ret_aenergy_minute_ts' => '1715065259',
          'freq' => '50.0',
          'aenergy_total' => '0.000',
          'aenergy_by_minute_1' => '0.000',
          'apower' => '0.0',
          'id' => '0',
          'current' => '0.000',
          'ret_aenergy_total' => '0.000',
          'aenergy_by_minute_3' => '0.000',
          'voltage' => '235.4',
          'ret_aenergy_by_minute_1' => '0.000',
          'aenergy_by_minute_2' => '0.000',
          'ret_aenergy_by_minute_2' => '0.000',
          'aenergy_minute_ts' => '1715065259'
        };
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Tobias

tatsächlich funktioniert es so. Auf diese Notation wäre ich nie gekommen..... Steht das irgendwo dokumentiert? Ich hatte leider vorher nichts gefunden dazu
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

betateilchen

Zitat von: Tobias am 29 Juli 2024, 14:26:02Steht das irgendwo dokumentiert? Ich hatte leider vorher nichts gefunden dazu

Zitat von: betateilchen am 29 Juli 2024, 13:32:13das aenergy_total hat nicht mehr viel mit originärem json zu tun, das ist json2nameValue() spezifisch

Wenn man solche FHEM-internen Funktionen verwendet, muss man sich halt mit ihnen beschäftigen - oder einfach ausprobieren, was sie "per default" als Ergebnis liefern.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!