NEWS
mqtt parsen
-
Ich habe hier ein mqtt-Telegram das ich gerne in entsprechende Datenpunkte splitten würde:
{ "Time": "2023-08-09T20:41:37", "SML": { "total_bez": 4XXXX3.1, "total_bez_kwh": 4XXX.6, "total_ein": 0, "total_ein_kwh": 0, "netz_frequenz": 50.2, "aktuelle_wirkleistung": 161, "strom_l1": 0.1, "strom_l2": 1.34, "strom_l3": 0, "spannung_l1": 230.8, "spannung_l2": 230.8, "spannung_l3": 230.7, "delta_phi_I_U_L1": 0, "delta_phi_I_U_L2": -45, "delta_phi_I_U_L3": 0 }, "daily_consumption": 4XXXX73, "daily_feed": 0 }
ich hab mir dieses skript hier irgendwo ausgeborgt (Ich glaube von @paul53 )
const JSPath = '0_userdata.0'; // JS- Pfad const parsedStatesPath = JSPath + ".stromzaehler."; // Pfad fuer geparste States const idJSON = 'mqtt.0.tele.bitshake_smartmeter.SENSOR'; on(idJSON, function (dp) { let JsonObj = JSON.parse(dp.state.val); Object.keys(JsonObj).forEach(function(key) { if(existsState(parsedStatesPath + key)) setState(parsedStatesPath + key, JsonObj[key], true); else createState(parsedStatesPath + key, JsonObj[key], {read: true, write: false, type: typeof JsonObj[key], name: key}); }); });
Funktioniert grundsätzlich, allerdings wird die zweite Ebene nicht aufgesplittet:
Wie bekomme ich die 'SML'-Ebene aufgedröselt?
-
@thomas-braun Ich kann Dir nur meinen NodeRed Flow anbieten.
-
@thomas-braun
ich habe das irgendwo im Forum gefunden und es funktioniert für mich mit der zweiten Ebene.// ############## user config // where the mqtt messages arrive const mqttDatenpunktObjectId = 'mqtt.0.linktap.up_cmd.xxxxxxxxxxxxxxx'; // where the states should appear const userDataFolder = '0_userdata.0.Linktap.xxxxxxxxxxxxxx'; // ############## end user config // receive on(mqttDatenpunktObjectId, (obj) => { const jsonString = obj.state.val; const jsonData = JSON.parse(jsonString); function createObjectsRecursively(parent, data) { for (const key in data) { const obj = data[key]; const stateName = `${parent}.${key}`; if (typeof obj === 'object') { createObjectsRecursively(stateName, obj); } else { let value = obj; // Check if the state already exists. If it does, just update the value. // If it does not exist create the states. if (!existsState(stateName)) { // If the state does not exist, create it and set the value createState(stateName, value, { name: key, type: typeof value, role: "value", read: true, write: true }); log(`Created state ${stateName}`); } else { setState(stateName, value, true); } } } } createObjectsRecursively(userDataFolder, jsonData); });
Vielleicht hat @paul53 eine elegantere Lösung. Ich hoffe ja noch immer auf einen Adapter, wo man Ursprung- und ZielDatenpunkt eingibt und der erledigt alles .
-
Ist aus einem meiner Scripte. Hab das gerade von unnötigem Code gesäubert, sollte laufen wenn ich nicht zuviel oder zuwenig gelöscht habe
id ist der Datenpunkt ab dem gebaut werden soll
result ist das das jsonsetKeys(id, result) async function setKeys(id, result) { if (result === null) return if (typeof(result) === 'object') { if (result.isArray) { for (let a = 0; a<result.length; a++) { setKeys(id+'.'+a, result[a]) } } else { for (let key in result) { setKeys(id+'.'+key, result[key]) } } } else { if (existsState(id)) { setState(id, result, true) } else { let common = {name:'no name', type:typeof(result), write:false, def:result} try { await createStateAsync(id, result,common) } catch(e) {log(e)} } } return Promise.resolve(true); }
-