NEWS
MQTT String generell aufteilen?
-
Ich bekomme vom Raspberry mit zigbee2mqtt folgenden String:
{"battery":86,"voltage":2975,"temperature":28.47,"humidity":30.84,"pressure":993,"linkquality":36}
Diesen würde ich jetzt gerne in einzelne Objekte aufteilen: Batterie, Volt, Temperatur usw...
Ich weiß, dass ich das per Script für jedes Topic machen kann, aber genau das will ich nicht für 50 Geräte machen.Gibt es eine Möglichkeit, den String vom Raspi gleich sauber schicken zu lassen oder generell ankommende Topics auf dieser Broker Instanz aufzuteilen??
Vielen Dank
-
Nun mit einem Script musst Du in jedem Fall arbeiten. Sind es JSON Strings werden die in Java Objekte umgewandelt und über eine Schleife verteilst du es auf die Datenpunkte.
var x; var obj = {"battery":86,"voltage":2975,"temperature":28.47,"humidity":30.84,"pressure":993,"linkquality":36}; // var str =""; for (x in obj) { // str = str + "<br>" + x + obj[x]; //Es müsste also - nach Erstellung beim Schreiben der States in etwa so aussehen. Die Profis können das sicher noch besser. setState(x, obj[x]); log (obj[x]); }
Ich habe einfach mal Dein Objekt genommen. Mit x ermittelst Du den Topic-Namen und weißt welchen Datenpunkt Du erzeugen bzw. modifizieren musst. Mit "obj[x]" greifst Du auf den zugehörigen Wert zu.
Somit ist das ganze generisch und kann auch für viele Geräte generisch erzeugt werden. Vor dem "x" muss halt dann der konstante Pfad für das Gerät stehen.
-
@mickym Danke für deinen Post, aber ganz verstehen tue ich das nicht. So muss doch immer noch für jedes Gerät bzw das dazugehörige Topic ein Script angelegt werden?
-
oder so:
obj = '{"battery":86,"voltage":2975,"temperature":28.47,"humidity":30.84,"pressure":993,"linkquality":36}'; obj = JSON.parse(obj); var batt = obj.battery; var volt = obj.voltage; var temp = obj.temperature; log (batt); log (volt); log (temp);
-
-
@butsch Nein dieses Stück Code steckst Du in eine Funktion, der Du Dein Objekt übergibst. Durch die Schleife kannst Du damit selbst die Datenpunkte unter einem Gerät einmalig anlegen und später, wenn sich das Objekt verändert hat die Werte darauf verteilen. Die Schleife macht nichts anderes als @bahnuhr im Code beschrieben hat, nur dass es eben generisch arbeitet und die Zuweisung über obj.x funktioniert und man nicht im Voraus wissen muss, wie ein Objekt heißt und deshalb die Variablen fixiert (also battery, voltage etc.). Das heißt Du erstellst das Script einmal und kannst es dann für jedes Gerät erneut verwenden.
Nehmen wir also an Du nimmst die XIAOMI Temperatur/Feuchtigkeitssensoren. die schreiben das obige Objekt in einen bestimmten Datenpunkt. Der Datenpunkt spezifiziert das Gerät - Du überwachst mit einem Script alle 50 Geräte und bei der Änderung eines Datenpunktest fieselst Du das Objekt mit der Schleife auf und verteilst es mit der Schleife auf die Datenpunkte, die Du erstellt hast. Mit anderen Worten - statt der Zuweisung zu einer Variablen obj - in meinem Code schnipsel, über gibst Du es als Objekt mit der JSON.parse(obj); Funktion.
Ich meine der Zigbee Adapter macht das auch alles bereits und der basiert ja meines Wissen auch auf dem zigbeemqtt.
-
Ich nutze selber zigbee2mqtt seit langem, weil es einfach stabiler lief als der zigbee Adapter.
Hier ist ein kleines Script von mir zum parsen der Json-Objekte vom zigbee2mqtt:const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".zigbee2mqtt" // Pfad fuer geparste States const zigbee2mqttJsonPath = "mqtt.0.zigbee2mqtt" //Pfad fuer zigbee2mqtt Json Objekte let IDs = []; $("[id=" + zigbee2mqttJsonPath + ".*]").each(function (id) { IDs.push(id) }) on({id: IDs, change: "ne"}, function (obj) { let JsonObj = JSON.parse(obj.state.val) Object.keys(JsonObj).forEach(function(key){ if (getState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath)).notExist){ createState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key], {read: true, write: true, type: typeof(JsonObj[key]), name: '' , desc: ''},function(){ setState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key]) }) }else { setState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key]) }; }) })
Viel Spaß damit
-
@frostnatt VIELEN DANK!
-
@mickym VIELEN DANK!
-
@frostnatt sagte in MQTT String generell aufteilen?:
Ich nutze selber zigbee2mqtt seit langem, weil es einfach stabiler lief als der zigbee Adapter.
Hier ist ein kleines Script von mir zum parsen der Json-Objekte vom zigbee2mqtt:const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".zigbee2mqtt" // Pfad fuer geparste States const zigbee2mqttJsonPath = "mqtt.0.zigbee2mqtt" //Pfad fuer zigbee2mqtt Json Objekte let IDs = []; $("[id=" + zigbee2mqttJsonPath + ".*]").each(function (id) { IDs.push(id) }) on({id: IDs, change: "ne"}, function (obj) { let JsonObj = JSON.parse(obj.state.val) Object.keys(JsonObj).forEach(function(key){ if (getState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath)).notExist){ createState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key], {read: true, write: true, type: typeof(JsonObj[key]), name: '' , desc: ''},function(){ setState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key]) }) }else { setState(obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + '.' + key, JsonObj[key]) }; }) })
Viel Spaß damit
...ich habe das Script jetzt mal am Laufen, verstehe aber nicht genau was ich noch abändern muss, damit das ganze funktioniert?
So direkt schein es nicht zu klappen -
const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".zigbee2mqtt" // Pfad fuer geparste States const zigbee2mqttJsonPath = "mqtt.0.zigbee2mqtt" //Pfad fuer zigbee2mqtt Json Objekte
Man muss nur die o.g. Pfade anpassen.
JSPath ist hierber der Pfad zu javascript Instanz, welche das Script ausführt.
zigbee2mqttJsonPath ist der Pfad, wo Json Objekte von zigbee2mqtt landen.
parsedStatesPath ist der Pfad für die geparsten Datenpunkte.
Die Datenpunkte werden erst angelegt, wenn Json Objekte geändert werden - etwas Geduld ist hier also gefordert -
Ok, dann müssten die Einstellungen so wie in deinem Script ja bei mir passen. Hier meine Objekte:
Oder mache ich sonst wo noch einen Fehler? OnOff und Temperatur sind die Topics vom zigbee2mqtt....
-
Ok, ich habs! Danke noch mal!!!!
zigbee2mqttJsonPath musste ich anpassenGEIL!
-
Soweit scheint jetzt alles zu funktionieren, die States sind da und werden auch aktualisiert, aber:
10:06:33.041 warn javascript.0 (226402) at script.js.common.MQTT2OBJEKT.Parser:13:13 10:06:33.041 warn javascript.0 (226402) at Object.<anonymous> (script.js.common.MQTT2OBJEKT.Parser:12:26)
226402) getState "javascript.0.zigbee2mqtt.OnOff" not found (3)
Was denn da los? ;-(
-
@butsch
Die Warnings bekomme ich auch seit einiger Zeit. Das Script funktioniert aber weiterhin ohne Probleme bei mir. Muss ich mal bei Gelegenheit debuggen, es fehlt leider im Moment die Zeit... -
@butsch
Habe das Problem gefixt, das Script wirft keine Warnings mehr bei mir.const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".zigbee2mqtt" // Pfad fuer geparste States const zigbee2mqttJsonPath = "mqtt.0.zigbee2mqtt" //Pfad fuer zigbee2mqtt Json Objekte let IDs = []; $("[id=" + zigbee2mqttJsonPath + ".*]").each(function (id) { IDs.push(id) }) on({id: IDs, change: "ne"}, function (obj) { let JsonObj = JSON.parse(obj.state.val) Object.keys(JsonObj).forEach(function(key){ let currState = obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + "." + key if (getState(currState).notExist){ createState(currState, JsonObj[key], {read: true, write: true, type: typeof(JsonObj[key]), name: '' , desc: ''},function(){ setState(currState, JsonObj[key]); }) }else { setState(currState, JsonObj[key]) }; }) })
-
@frostnatt sagte in MQTT String generell aufteilen?:
const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".zigbee2mqtt" // Pfad fuer geparste States const zigbee2mqttJsonPath = "mqtt.0.zigbee2mqtt" //Pfad fuer zigbee2mqtt Json Objekte let IDs = []; $("[id=" + zigbee2mqttJsonPath + ".*]").each(function (id) { IDs.push(id) }) on({id: IDs, change: "ne"}, function (obj) { let JsonObj = JSON.parse(obj.state.val) Object.keys(JsonObj).forEach(function(key){ let currState = obj.id.replace(zigbee2mqttJsonPath, parsedStatesPath) + "." + key if (getState(currState).notExist){ createState(currState, JsonObj[key], {read: true, write: true, type: typeof(JsonObj[key]), name: '' , desc: ''},function(){ setState(currState, JsonObj[key]); }) }else { setState(currState, JsonObj[key]) }; }) })
Vielen Dank, jetzt passt es!
-
@frostnatt sagte in MQTT String generell aufteilen?:
@butsch
Habe das Problem gefixt, das Script wirft keine Warnings mehr bei mir.Jetzt habe ich primitiv geglaubt, ich kann mir das Script stehlen, ein wenig anpassen und es läuft..... war ein Irrglaube. Kannst du mir vielleicht bitte helfen?
schedule("* * * * *", function (){ //alle Minuten const JSPath = "a_andreas.0.eigene_dp" // JS- Pfad const parsedStatesPath = JSPath + ".Heizung" // Pfad fuer geparste States const JsonPath = "mqtt.0.ems-esp.sm_data" // Pfad fuer Json Objekte let IDs = []; $("[id=" + JsonPath + ".*]").each(function (id) { IDs.push(id) }) on({id: IDs, change: "ne"}, function (obj) { let JsonObj = JSON.parse(obj.state.val) Object.keys(JsonObj).forEach(function(key){ let currState = obj.id.replace(JsonPath, parsedStatesPath) + "." + key if (getState(currState).notExist){ createState(currState, JsonObj[key], {read: true, write: true, type: typeof(JsonObj[key]), name: '' , desc: ''},function(){ setState(currState, JsonObj[key]); }) }else { setState(currState, JsonObj[key]) }; }) }) })
{"collectortemp":16,"bottomtemp":57.8,"pump":"off","pumpWorkMin":30500,"energylasthour":0}
Leider tut sich nix ........ bitte um Unterstützung!
Finde deine Lösung mit dynamischen DP echt genial!!!!
LG, mxa -
@metaxa sagte:
Leider tut sich nix
Mit createState() kann man keine Datenpunkte unter "a_andreas.0.eigene_dp" erstellen.
Außerdem: Was soll das schedule() drumherum ? Damit wird jede Minute ein neuer Trigger erzeugt. -
@paul53 sagte in MQTT String generell aufteilen?:
@metaxa sagte:
Leider tut sich nix
Mit createState() kann man keine Datenpunkte unter "a_andreas.0.eigene_dp" erstellen.
Hi Paul,
ich habs geändert ... aber es tut sich auch nix.// schedule("* * * * *", function (){ //alle Minuten const JSPath = "javascript.0" // JS- Pfad const parsedStatesPath = JSPath + ".Heizung" // Pfad fuer geparste States const JsonPath = "mqtt.0.ems-esp.sm_data" // Pfad fuer Json Objekte
Hättest bitte noch eine Idee?
Ups ...... hatte ich nicht gesehen: Ich will mit dem Shedule, dass das Script alle Minuten zum Testen ausgeführt wird.