NEWS
[gelöst] JSON-Tabelle in Datenobjekte auflösen (Javascript)
-
Hallo Gemeinde,
ich bekomme vom Adapter (ESP32) an meiner Heizung über MQTT einen JSON-String, aus dem ich einzelne Daten-Objekte erzeugen will.
Der String mit ID 'mqtt.0.espaltherma.ATTR', den ich adapterseitig mal auf zwei gesendete Werte (Vorlauf- und Rücklauftemperatur) reduziert habe, sieht so aus:
[{"Leaving":"27.700000","Returning":"24.900000"}]Nach Studium mehrerer Threads hier, habe ich nach "paul53" folgendes Javascript gebastelt:
const idJson = 'mqtt.0.espaltherma.ATTR'; const path = '0_userdata.0.espaltherma'; on(idJson, function(dp){ let obj = JSON.parse(dp.state.val); let id = path + 'Vorlauf'; if(existsState(id)) setState(id, obj['Leaving'], true); else createState(id, obj['Leaving'], {type: 'number', name: 'Vorlauf', role: 'value', unit: '°C'}); id = path + 'Rücklauf'; if(existsState(id)) setState(id, obj['Returning'], true); else createState(id, obj['Returning'], {type: 'number', name: 'Rücklauf', role: 'value', unit: '°C'}); })
Wenn ich das Script laufen lasse kommt folgende Fehlermeldung:
"script.js.Skript_4: setForeignState: undefined is not a valid state value"
Leider habe ich aktuell nur einen sehr begrenzten Durchblick und bitte um Hilfe!
-
@kalanaghtd Du hast da ein Array, nimm obj[0]['Leaving']
-
let obj = JSON.parse(dp.state.val)[0];
-
So?
const idJson = 'mqtt.0.espaltherma.ATTR'; const path = '0_userdata.0.espaltherma'; on(idJson, function(dp){ let obj = JSON.parse(dp.state.val)[0]; let id = path + 'Vorlauf'; if(existsState(id)) setState(id, obj[0]['Leaving'], true); else createState(id, obj[0]['Leaving'], {type: 'number', name: 'Vorlauf', role: 'value', unit: '°C'}); id = path + 'Rücklauf'; if(existsState(id)) setState(id, obj[0]['Returning'], true); else createState(id, obj[0]['Returning'], {type: 'number', name: 'Rücklauf', role: 'value', unit: '°C'}); })
Fehler jetzt:
21:24:52.798 error javascript.0 (6500) at Object.<anonymous> (script.js.Skript_4:7:44) -
@kalanaghtd sagte in JSON-Tabelle in Datenobjekte auflösen (Javascript):
So?
belasse Zeile 5 und in den anderen nimmst du [0] wieder weg.
-
@kalanaghtd sagte: [{"Leaving":"27.700000","Returning":"24.900000"}]
Das Objekt liefert leider keine Zahlen, sondern Strings. Deshalb:
if(existsState(id)) setState(id, parseFloat(obj['Leaving']), true); else createState(id, parseFloat(obj['Leaving']), {type: 'number', name: 'Vorlauf', role: 'value', unit: '°C'}); id = path + 'Rücklauf'; if(existsState(id)) setState(id, parseFloat(obj['Returning']), true); else createState(id, parseFloat(obj['Returning']), {type: 'number', name: 'Rücklauf', role: 'value', unit: '°C'});
-
-
-
Hier nochmal das gesamte Thema auf einen Blick:
Mein Adapter liefert im Objekt 'mqtt.0.espaltherma.ATTR' folgenden JSON-String:
[{"Outdoor air temp.(R1T)":"11.500000","Discharge pipe temp.":"35.000000","Heat exchanger mid-temp.":"8.500000","INV primary current (A)":"1.300000","Voltage (N-phase) (V)":"238.000000","INV frequency (rps)":"12.000000","Fan 2 (step)":"68.000000","Expansion valve (pls)":"207.000000","BUH Step1":"OFF","BUH Step2":"OFF","Leaving water temp. before BUH (R1T)":"25.700000","Leaving water temp. after BUH (R2T)":"26.000000","Refrig. Temp. liquid side (R3T)":"25.700000","Inlet water temp.(R4T)":"23.800000","DHW tank temp. (R5T)":"45.800000","Ext. indoor ambient sensor (R6T)":"10.700000","Flow sensor (l/min)":"14.300000","Water pressure":"0.000000","Water pump signal (0:max-100:stop)":"49.000000","Pressure Sensor":"16.100000"}]
Ich will daraus einzelne Objekte machen, die ich weiter verwenden kann.
Die Experten @paul53 und @fasfoot haben die entscheidenden Hinweise gegeben.
Sehr wichtig war die Erkenntnis, dass das oben gezeigte JSON-Objekt keine Zahlen sondern Strings liefert.Hier als Beispiel das funktionierende Script mit zwei Daten aus dem JSON-String. Es werden die Objekte "Vorlauf" und "Rücklauf" mit ihren jeweiligen Temperaturwerten erzeugt und im Verzeichnis "0_userdata.0" abgelegt:
const idJson = 'mqtt.0.espaltherma.ATTR'; const path = '0_userdata.0.'; on(idJson, function(dp){ let obj = JSON.parse(dp.state.val)[0]; let id = path + 'Vorlauf'; if(existsState(id)) setState(id, parseFloat(obj['Leaving water temp. before BUH (R1T)']), true); else createState(id, parseFloat(obj['Leaving water temp. before BUH (R1T)']), {type: 'number', name: 'Vorlauf', role: 'value', unit: '°C'}); id = path + 'Rücklauf'; if(existsState(id)) setState(id, parseFloat(obj['Inlet water temp.(R4T)']), true); else createState(id, parseFloat(obj['Inlet water temp.(R4T)']), {type: 'number', name: 'Rücklauf', role: 'value', unit: '°C'}); })