FHEM Forum

FHEM => Sonstiges => Thema gestartet von: stefan.apetz am 22 November 2022, 11:22:34

Titel: Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 11:22:34
Moin,

ich lese aus einem Dummy Device Daten aus mit http://fhem.fritz.box:8083/fhem?cmd=jsonlist2%20virtualSolar%20&XHR=1

Das Ergebnis ist:

{
  "Arg":"virtualSolar",
  "Results": [
  {
    "Name":"virtualSolar",
    "PossibleSets":" ",
    "PossibleAttrs":"alias comment:textField-long eventMap:textField-long group room suppressReading userattr userReadings:textField-long verbose:0,1,2,3,4,5  disable disabledForIntervals readingList setExtensionsEvent:1,0 setList useSetExtensions event-aggregator event-min-interval event-on-change-reading event-on-update-reading oldreadings stateFormat:textField-long timestamp-on-change-reading DbLogExclude DbLogInclude DbLogValueFn:textField-long cmdIcon devStateIcon devStateIcon:textField-long devStateStyle fm_type icon sortby webCmd webCmdLabel:textField-long widgetOverride",
    "Internals": {
      "FUUID": "637bda7b-f33f-0227-48fa-96b87a9a031773fe",
      "NAME": "virtualSolar",
      "NR": "608",
      "STATE": "OK",
      "TYPE": "dummy",
      "eventCount": "6974"
    },
    "Readings": {
      "battery_power": { "Value":"470", "Time":"2022-11-22 11:16:44" },
      "battery_remain_capacity": { "Value":"19", "Time":"2022-11-22 11:16:44" },
      "grid_feed_in_power": { "Value":"-17", "Time":"2022-11-22 11:16:44" },
      "home_power": { "Value":"396.95", "Time":"2022-11-22 11:16:44" },
      "pv_total_power": { "Value":"937.95", "Time":"2022-11-22 11:16:44" },
      "state": { "Value":"OK", "Time":"2022-11-22 00:12:20" }
    },
    "Attributes": {
      "alias": "virtualSolar (Dummy Device zur Erfassung aller Mengen)",
      "group": "Solaranlage"
    }
  }  ],
  "totalResultsReturned":1
}



Ich brauche aber ein json in folgender Gestalt:

{
    "batteryPower": 724,
    "batteryPercent": 19,
    "powerExported": -45,
    "powerSolar": 947,
    "powerHouse": 228
}


und zwar genau in der Gestalt.

Wie kann man das aus fhem so zurückbekommen bzw. das obige Ergebnis transformieren in untere Gestalt?

Danke :-)
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: JoWiemann am 22 November 2022, 11:31:46
Hallo,

wie sieht denn der use case aus. Vielleicht ergeben sich ja auch andere Möglichkeiten außer JSON List.

Grüße Jörg
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 11:43:08
Es gibt ein wunderbares Widget von hobi, dass den Energiefluss einer Solax Solaranlage visualisiert.

Ich habe eine weitere Anlage, die nicht von Solax ist.

Ein einem Dummy Device errechne ich die Gesamterzeugerwerte und speichere in in namentlich gleichlautenden Readings ab:

defmod SolarPower notify Shelly_Gartenhaus:power:.*|Shelly_Solar_Garage:power:.*|solax:pv_total_power:.*|solax:home_power:.*|solax:battery_remain_capacity:.*|solax:grid_feed_in_power:.* {

   my $power1 = ReadingsVal("Shelly_Gartenhaus","power",0);;
   my $power2 = ReadingsVal("Shelly_Solar_Garage","power",0);;
   my $power3 = ReadingsVal("solax","pv_total_power",0);;
   my $power  = 0;;
   $power = $power1 + $power2 + $power3;;

   my $hausverbrauch1 = ReadingsVal("solax","home_power",0);;
   my $hausverbrauch2 = ReadingsVal("Shelly_Solar_Garage","power",0);;
   my $hausverbrauch3 = ReadingsVal("Shelly_Gartenhaus","power",0);;
   
   my $houseConsumption = 0;;
   
   $houseConsumption = $hausverbrauch1 + $hausverbrauch2 + $hausverbrauch3;;

   my $batteryPower = ReadingsVal("solax","battery_power",0);;
   my $battery_remain_capacity = ReadingsVal("solax","battery_remain_capacity",0);;
   my $inverter_powerexported = ReadingsVal("solax","grid_feed_in_power",0);;
   
   
   
   fhem("setreading virtualSolar home_power $houseConsumption");;
   fhem("setreading virtualSolar pv_total_power $power");;
   fhem("setreading virtualSolar battery_remain_capacity $battery_remain_capacity");;
   fhem("setreading virtualSolar battery_power $batteryPower");;
   fhem("setreading virtualSolar grid_feed_in_power $inverter_powerexported ");;
   }


Das Original Widget von hobi holt sich per get URL (http://fhem.fritz.box:8083/fhem?cmd=get%20solax%20json&fwcsrf=&XHR=1&_=1669113444566) die Daten vom entsprechenden Device. Das Device stellt dabei "GET" auf die Readings zur Verfügung und liefert das zuvor aufgeführte schlanke json.

Ein Dummy Device hat keine "GET" Methode auf die Readings. Da komme ich nur mit jsonlist2 an die Werte ran. Und die Passen halt leider nicht.

hobi wertet in seinem Widget das "schlanke" json wie folgt aus:

var cmd = [ 'get', elem.data('device'), "json" ].join(' ');
                        ftui.log('readingsgroup update', dev, ' - ', cmd);
                        //console.log ( "cmd: " + cmd);
                        ftui.sendFhemCommand(cmd)
                            .done(function (data, dev) {
                            //console.log('cmd: received update : ', data );

                            var obj = JSON.parse(data);

var prefix = elem.data('prefix');
//console.log (prefix);

document.getElementById(prefix + "homePower").innerText = obj.powerHouse + "W";
document.getElementById(prefix + "solarPower").innerText = obj.powerSolar + "W";
document.getElementById(prefix + "exportedPower").innerText = obj.powerExported + "W";
document.getElementById(prefix + "batteryPower").innerText = obj.batteryPower + "W";
document.getElementById(prefix + "batteryPercent").innerText = obj.batteryPercent + "%";


Und genau hier verließen sie mich....

Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: rudolfkoenig am 22 November 2022, 13:26:48
JSON kann man auch anders produzieren:

Folgende Zeilen:
define d dummy
setreading d batteryPower 724
setreading d batteryPercent 19
setreading d powerExported -45
setreading d powerSolar 947
setreading d powerHouse 228
{ toJSON({\
    batteryPower   => ReadingsNum("d", "batteryPower", 0)+0, \
    batteryPercent => ReadingsNum("d", "batteryPercent", 0)+0, \
    powerExported  => ReadingsNum("d", "powerExported", 0)+0, \
    powerSolar     => ReadingsNum("d", "powerSolar", 0)+0, \
    powerHouse     => ReadingsNum("d", "powerHouse", 0)+0 }) }

erzeugen folgenden JSON:

{"batteryPercent":19,"batteryPower":724,"powerExported":-45,"powerHouse":228,"powerSolar":947}
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 13:37:49
Hallo Rudolf,

danke für den Hinweis.

Wo genau baue ich die Syntax in den geschweiften Klammern ein und wie Frage ich dann am Gerät Dummy d die Werte wieder ab?

Sorry: da weiß ich gerade leider nicht weiter..... :-(
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: rudolfkoenig am 22 November 2022, 13:50:05
Bin nicht sicher, dass ich die Fragen verstehe.

Statt "jsonlist2 d" gibt man { toJSON(...) } ein.
Das Ganze wuerde ich in 99_myUtils.pm in eine Funktion packen, dann kann man zivilisierter Rechnen, der Aufruf ist auch kuerzer: { meineFunktion() }
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: TomLee am 22 November 2022, 14:12:46
Darf man mal kurz zwischenrein fragen wozu das +0 ist, es geht auch ohne ?
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 14:18:17
Also so richtig weiter komme ich nicht :-(

in der 99_myUtils.pm habe ich jetzt aufgenommen:

sub createSolarJson ()
{ toJSON({
    batteryPower   => ReadingsNum("virtualSolar", "batteryPower", 0)+0,
    batteryPercent => ReadingsNum("virtualSolar", "batteryPercent", 0)+0,
    powerExported  => ReadingsNum("virtualSolar", "powerExported", 0)+0,
    powerSolar     => ReadingsNum("virtualSolar", "powerSolar", 0)+0,
    powerHouse     => ReadingsNum("virtualSolar", "powerHouse", 0)+0 })
}


Mein Device virtualSolar (Dummy-Device) hat auch die ganzen Readings:

Readings
battery_power -2509 2022-11-22 14:15:21
battery_remain_capacity 36 2022-11-22 14:15:21
grid_feed_in_power -359 2022-11-22 14:15:21
home_power 4081.67 2022-11-22 14:15:21
pv_total_power 1436.67 2022-11-22 14:15:21
state. OK 2022-11-22 00:12:20


Rufe ich nun die URL
http://fhem.fritz.box:8083/fhem?cmd={createSolarJson()}&XHR=1 auf, dann kommt nur ein json mit den default 0 Werten zurück:

{"batteryPercent":0,"batteryPower":0,"powerExported":0,"powerHouse":0,"powerSolar":0}

Sorry, steh etwas auf dem Schlauch....
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: rudolfkoenig am 22 November 2022, 14:26:18
@TomLee: Ohne +0 werden die Werte als String geliefert ("947"), und manche Programme haben damit ein Problem.

@stefan.apetz: bitte die Namen der Readings im ReadingsNum Aufruf entsprechend anpassen, also
batteryPower => ReadingsNum("virtualSolar", "battery_power", 0)+0,

usw.
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: TomLee am 22 November 2022, 14:28:35
Danke.

Das ist schon im ersten Beitrag irgendwie verwirrend, willst du die Readingnamen in dem JSON dann auch noch umbenannt haben ?
Dann musst du den "linken Part" in dem toJSON auch noch anpassen.
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 14:51:13
Sauber, kaum macht mans richtig gehts:

sub createSolarJson ()
{ toJSON({
    batteryPower   => sprintf("%d", ReadingsNum("virtualSolar", "battery_Power", 0)+0),
    batteryPercent => sprintf("%d",ReadingsNum("virtualSolar", "battery_remain_capacity", 0)+0),
    powerExported  => sprintf("%d",ReadingsNum("virtualSolar", "grid_feed_in_power", 0)+0),
    powerSolar     => sprintf("%d",ReadingsNum("virtualSolar", "pv_total_power", 0)+0),
    powerHouse     => sprintf("%d",ReadingsNum("virtualSolar", "home_power", 0)+0) })
}


Ergebnis:
{"batteryPercent":"19","batteryPower":"0","powerExported":"-3981","powerHouse":"4064","powerSolar":"126"}

Und das Ergebnis kann isch meiner Meinung nach sehen lassen :-)

Vielen lieben Dank für die Unterstützung.

Die Vorgehensweisen, die ich hier gelernt habe, machen Lust auf mehr :-)
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: rudolfkoenig am 22 November 2022, 15:23:02
ZitatUnd das Ergebnis kann isch meiner Meinung nach sehen lassen :-)
Ich sehe da nur, dass sprintf mein +0 konterkariert :)
Wozu braucht man sprintf ueberhaupt?
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: stefan.apetz am 22 November 2022, 15:29:31
Ok, mit dem Ergebnis meinte ich die optische Darstellung.

Da wollte ich keine Nachkommastellen, daher das sprintf ;-)
Titel: Antw:Ergebnis aus jsonlist2 transformieren
Beitrag von: TomLee am 22 November 2022, 15:40:13
Geht auch ohne sprintf:

https://fhem.de/commandref_modular_DE.html#perl

ReadingsNum(<devicename>,<reading>, <defaultvalue>,<round>)
Gibt die erste Zahl aus dem Readingswert zurück. Falls <round> spezifiziert ist, wird sie auf diese Anzahl von Dezimalstellen gerundet und ggf. mit 0 aufgefüllt, wenn <round> größer ist als die Anzahl der Dezimalstellen.