Ergebnis aus jsonlist2 transformieren

Begonnen von stefan.apetz, 22 November 2022, 11:22:34

Vorheriges Thema - Nächstes Thema

stefan.apetz

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 :-)

JoWiemann

Hallo,

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

Grüße Jörg
Jörg Wiemann

Slave: RPi B+ mit 512 MB, COC (868 MHz), CUL V3 (433.92MHz SlowRF); FHEMduino, Aktuelles FHEM

Master: CubieTruck; Debian; Aktuelles FHEM

stefan.apetz

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....


rudolfkoenig

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}

stefan.apetz

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..... :-(

rudolfkoenig

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() }

TomLee

Darf man mal kurz zwischenrein fragen wozu das +0 ist, es geht auch ohne ?

stefan.apetz

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....

rudolfkoenig

@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.

TomLee

#9
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.

stefan.apetz

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 :-)

rudolfkoenig

ZitatUnd das Ergebnis kann isch meiner Meinung nach sehen lassen :-)
Ich sehe da nur, dass sprintf mein +0 konterkariert :)
Wozu braucht man sprintf ueberhaupt?

stefan.apetz

Ok, mit dem Ergebnis meinte ich die optische Darstellung.

Da wollte ich keine Nachkommastellen, daher das sprintf ;-)

TomLee

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.