NEWS
JSON oder JavaScript Objekt in iobroker Datenpunkte zerlegen
-
Hier noch eine kleine Fehlerkorrektur der Node:
Damit man auch JSON Strings aus einem Datenpunkt als Quelle verwenden kann muss der ursprünglich msg.topic gelöscht werden, was ich hiermit am Anfang des Flows mache.
Dann werden aus den Pfaden die Leerzeichen durch Unterstriche ersetzt und der Name korrekt gesetzt.
Für alle die nicht wissen, wie man zu einem vorhanden Punkt noch die msg.top setzt hier nochmal grafisch die Abbildung und die Konfig des Change Nodes:
die Quelle unter Objects:
Wie man sieht kann man über die msg.top Eigenschaft auch bereits eine Anfangshierachie festlegen, indem man in den Pfad bereits einen '.' einfügt.
Bei den Inject-Nodes kann ich natürlich msg.topic gleich mitgeben:
Das Ergebnis sieht dann so aus:
Beim Update werden dann halt die entsprechenden Objekte aktualisiert.
-
So für alle, die es interessiert - dafür mache ich aber keinen eigenen Subflow - man kann natürlich auch umgekehrt eine iobroker Objektstruktur in einem JSON String abspeichern. Ich werde den Beispiel - Flow auch wieder löschen - aber war auch ein guter Test in wieweit Strukturen wiederhergestellt werden.
Dazu habe ich mal einen absoluten Härtetest gemacht - und die ganze Objektstruktur eines Tasmota-Gerätes, das über mqtt angebunden ist, exportiert.
Da das nicht gerade wenige Datenpunkte sind, hier mal ein Screenshot:
So um das ganze auszulesen braucht es nur ein paar Standardnodes - wie gesagt ich werden den Flow nicht exportieren, aber zum Nachbauen werde ich die Konfig kurz erklären.
-
Die erste Node ist nur eine Inject Node um das Ganze zu triggern
-
Die zweite Node ist eine iobroker list node - mit einem '*' am Ende (Wildcard) um den gesamten Objektbaum auszulesen:
Wichtig sind bei der list Node folgende Einstellungen zu verwenden:
Gut Type kann auch Any sein - aber wäre da eher vorsichtig.
Wichtig ist kein Array auszugeben, sondern einzelne Nachrichten, weil der msg.topic und msg.payload nachbearbeitet werden soll und natürlich wollen wir den state value mitnehmen. -
In der nachfolgenden Change Node setzen wir msg.payload auf den val-Wert des Objektes und extrahieren bzw. modifizieren den topic, damit der konstante Anteil des Objektbaums herausgeschnitten wird.
-
In der anschliessenden JOIN Node fasse ich alles wieder in einer Nachricht zusammen - hier habe ich aber der Einfachheit halber einfach 5 s Zeitlimit genommen, man kann auch ewig viele Einzelnachrichten ausgeben lassen - aber das finde ich in diesem Fall eher hinderlich und nach 5 Sekunden sollten auch größere Objekte bearbeitet sein.
Es kommt dann schon ein langes komplexes Objekt dabei raus, das auch in dem Debugfenster nochmal vollständig angezeigt wird. -
Anschließend wird das Ganze über eine JSON Node Stringyfiziert.
Spätestens hier - zumindest bei großen Strings wird dieser im Debug Fenster nun abgeschnitten
Deshalb habe ich den ganzen String in eine Datei unter dem iobroker home Verzeichnis weggeschrieben.
Um zu überprüfen - habe ich auf dem Raspberry mal in einem Browser den String in so einem JSON Formatter analysieren lassen und das sah gut aus. (Ich weiß macht man nicht, dass man den Raspberry mit Desktop betreibt. )
Dann habe ich gedacht - nun müsste ich ja mit meiner Node die Struktur auch wieder in den iobroker einfügen können.
Die Inject Node hat mit dem eingebauten JSON Formatierbutton - jedenfalls auch ein fehlerfreies Objekt generiert:
mit einer entsprechenden msg.top Nachricht - und meiner Subflow Node also das ganze wieder importiert - natürlich unter 0_userdata.0
und was soll ich sagen - der Reimport unter 0_userdata.0 schaut für mich einwandfrei aus:
-
-
So ich habe den Subflow nochmals geändert - da in der alten Version beim einem initialen Array - dies nicht richtig funktionierte:
Ausserdem habe ich mal die Nodes besser benannt - damit man die Funktion der Nodes besser erkennt:
-
Neue Version 8.4.2021:
Hier nun die einzelnen Beispiele einmal als Gesamtflow - hier aber dann auch nochmal in Screenshots dargestellt:
Erstmal zum Selbstausprobieren der Gesamtflow:
Nun zu den einzelnen Inputs in den Inject-Nodes:
1. Example.SimpleArray
[1,5,6.2,2,3]
Ergebnis2. Example.ComplexArray
[1,2,[3,4,5],{"Leaving":"288.700000","Returning":"24.900000"}]
Ergebnis3. Skalar (Input ist kein Objekt)
Ergebnis
4. Objekt:
{"Präsenz Wohnzimmer Essbereich":true,"Präsenz Bad":true,"Präsenz Schlafzimmer":true,"Thermometer Bad":true,"Präsenz Flur":true,"Würfel Wohnzimmer":{"1":"TV"},"Präsenz Küche":true,"Würfel Schlafzimmer":true,"Thermometer Küche":true,"Präsenz Diele":true,"Präsenz Wohnzimmer":true,"Präsenz Büro":true}
Ergebnis:5. ObjectArray:
[ { "start": 45, "end": 100, "date": "24.3.2021 18:44", "diff": 1, "quantity": 0, "price": "0.00", "basicPrice": 0, "startDate": "24.3.2021 18:44", "duration": 1, "perHour": 0 }, { "start": 51, "end": 52, "date": "24.3.2021 15:59", "diff": 3, "quantity": 0, "price": "0.00", "basicPrice": 0, "startDate": "24.3.2021 15:57", "duration": 3, "perHour": 0 }, { "start": 59, "end": 100, "date": "24.2.2021 14:27", "diff": 29, "quantity": 0, "price": "0.00", "basicPrice": 0, "startDate": "24.2.2021 13:59", "duration": 29, "perHour": 0 } ]
Ergebnis:
6. JSON-String
{"squadName":"Super hero squad","homeTown":"Metro City","formed":2016,"secretBase":"Super tower","active":true,"members":[{"name":"Molecule Man","age":29,"secretIdentity":"Dan Jukes","powers":["Radiation resistance","Turning tiny","Radiation blast"],"dressed":{"head":"Kopfbedeckung"}},{"name":"Madame Uppercut","age":69,"secretIdentity":"Jane Wilson","powers":["Million tonne punch","Damage resistance","Superhuman reflexes"]},{"name":"Eternal Flame","age":1000000,"secretIdentity":"Unknown","powers":["Immortality","Heat Immunity","Inferno","Teleportation","Interdimensional travel"]}]}
Ergebnis: -
@mickym Hallo mickym ,
irgendwie verstehe ich das mit dem msg.top als root nicht ..... Was bedeutet das für mich beim anlegen des DP ? Also Channel\Gerät ..... ?
das Script wäre nämlich genau das was ich brauchen könnte !
MfG.
Jean
-
Es muss als topic für den Objektbaum ein Name in der Eigenschaft msg.top mitgegeben werden, dann wird dieser Datenpunkt als Wurzel unter 0_userdata.0.top mit dem im Objekt oder JSON-String zugehörigen Objekten angelegt.
Nein mit msg.top legst Du den Namen fest unter dem die Struktur unter 0_userdata.0 angelegt werden soll.
Also wenn Du msg.top="meineStruktur", dann legt der Flow alles unter dem Punkt 0_userdata.0.meineStruktur an.
Seit dem Admin5 musst Du dann aber nachträglich die Verzeichnispunkte leider wieder als Objektverzeichnisse nachlegen. Also dann das Script von @fastfoot drüberlaufen lassen. Wenn die Struktur mal steht, ist es kein Problem, da dann alle Punkte natürlich aktualisiert werden.
Wenn Du Dir eigentlich das nächste Posting anschaust, da ist eigentlich auch alles mit Screenshots dokumentiert.
Also im Javascript noch die Erstellung von Objekten erlauben und dann dieses Script über 0_userdata.0 laufen lassen. Node-Red darf leider keine Objekte sondern nur states erstellen. Ich hab schon ein issue aufgemacht - aber ich befürchte, dass wird dauern ob und wann sich da jemand kümmert.
/** * Zweck: Korrigiert übergeordnete Ordnerstrukturen eines Datenpunkts * Datum: 07.08.2021 * Autor: @fastfoot */ // In den Settings der Javascript-Instanz muss setObject erlaubt sein!!! let arr = [], id = ''; const ids = $('0_userdata.0.*'); ids.each(idTmp => { arr=idTmp.split('.'); arr.splice(arr.length-1); id=arr.join('.'); if(arr[0] === '0_userdata' || arr[0] === 'alias' || arr[0] === 'mqtt' || arr[0] === 'javascript'){ correctObject(id, arr); } }) function correctObject(id,arr){ if(arr.length === 2) return; if(!existsObject(id)){ let obj = {}; obj = { type: 'folder', common:{ name: arr[arr.length - 1] } } extendObject(id, obj, e => { if (e) log('Fehler beim Schreiben des Objektes: '+ id + ' ' + e); }) } arr.splice(arr.length - 1); id = arr.join('.'); correctObject(id, arr); }
-
@mickym , Hi ..... auch schlaflos ?
Und in welchem Node trage ich die msg.top ein ? Sorry bei dem Node Red bin ich ganz neu, und hab noch keinen so richtigen Plan ! Die einfacheren Dinge wie schalten etc. hatte ich gleich verstanden. Aber hier hab ich gerade einen Knoten im Hirn Aber schonmal vielen Dank für die schnelle Antwort zu dieser späten Stunde !Ich probier mich mal durch !
-
@schonpaule Ja ich bin inzwischen zur Nachteule mutiert.
Wenn Dein JSON oder was weiß ich in der msg.payload ist - hängst einfach noch eine Change Node davor in dem msg.top festlegst.
Und wenn Du das in iobroker out Node jagst - werden diese Datenpunkte angelegt.
Die iobroker out Node erstellt die Stuktur sofern Du die Erstellung von Fremdobjekten im Adapter zulässt.
Das ist dann das Ergebnis:
Das Problem ist nur, dass das Verzeichnis mickym kein Objekt ist, deswegen musst Du das mit dem Javascript noch anlegen.
-
@mickym ...... ja mit dem schlafen habe ich es auch nicht mehr so .......
Ich probiere es gleich mal, mein Input ist von knx Ultimate die Gruppenadressen, NodeRed legt zwar welche an aber leider nur die reinen Nummern......
Danke vielmals das du so Hilfsbereit bist !
-
@schonpaule Kein Problem, solange das Gehirn noch funktioniert. - Wie sieht denn Deine Payload aus? Das Skript kann natürlich nicht mehr, als mit was Du es fütterst. Aber vielleicht bekommen wir ja zusammen hin, was Du willst.
-
@mickym , also der Payload sind KNX Gruppenadressen die am Ende nur den Status true oder false beinhalten sollen. Ich will diese dann in VIS weiterverarbeiten und durch das schreiben auf den Bus auch an allen Visualisierungen aktuell halten. Nicht erschrecken das ist ein ziemlich großes Projekt was die Menge der DP´s angeht
So sieht es ungefähr optisch aus als Text bekomme ich es gar nicht in einen Text wegen der 100000 Beschränkung
-
@schonpaule In der Change Node - setzt Du die msg.payload und nicht die msg.top. Und wie gesagt die Change Node hinter die KNX Node bzw. vor die Subflow-Node klemmen und nicht davor.
-
@mickym Ich habe gerade mal Deinen Subflow getestet. Der läuft soweit 1A. Ich schreibe damit das Objekt, was mein PV Speicher liefert. Was seltsam ist, ist, das mein Log mit warnings geflutet wird. Das scheint daran zu liegen, das die Datenpunkte readonly angelegt werden
node-red.0 2021-11-28 08:41:42.027 warn Read-only state "0_userdata.0.Solarwatt.SData.ACS.U_L2" has been written without ack-flag with value "225"
Man kann das umgehen, indem man in der Ouot-Node unten bei "Readonly" einstellt "Object is writable".
-
@waldmensch Ja das war mir bekannt - das sind alles Dinge seit dem admin5 - Du musst auch nachdem der Flow gelaufen ist, einmal das Skript von fastfoot drüber laufen lassen, damit die Objekte angelegt werden.
Da das ganze ja in userdata geschrieben wird - kann man man anstelle es auf writeable zu setzen das ACK -Flag setzen, also anstelle von command - ein value setzen. Das sollte ebenfalls gehen:
Es ist generelle so, dass man mit den Einstellungen in der iobroker-out Node - die Prüfung dieser Nodes ausschaltet . Der Subflow hat damit eigentlich gar nichts zu tun, der spaltet die Objekte ja nur in Einzelnachrichten auf und setzt die topics.
-
@waldmensch Generell muss man seit dem Admin5 - einmal auch immer noch das Skript von @fastfoot drüberlaufen lassen - das automatische Erstellen von Objekten im Admin5 lässt wohl auf sich warten.
Also dieses Skript importieren - und einmal ausführen:
Muss man nur einmal machen - wenn die Objekte angelegt sind - kann der Flow ungehindert weiter in die einzelnen Datenpunkte schreiben.
-
@mickym So ich habe die Node nochmals leicht überarbeitet. Die Bedeutung ist leider mit dem Admin 5 etwas verloren gegangen und man hat auch in den letzten 4 Monaten anscheinend immer noch keine Zeit gehabt den Admin oder NodeRed so anzupassen, dass ggf. Objekte selbst erstellt werden. Dennoch ist der Flow vielleicht noch hilfreich.
Die Node setzt nun nicht mehr zwingend das Füttern der Node mit msg.top voraus, um den Ausgangsdatenpunkt (objRoot) für den zu erstellenden Objektbaum festzulegen, sondern die Node kann nun auch mit Umgebungsvaribalen arbeiten. Endlich mal ein sinnvoller Einsatz für Umgebungsvariablen in Subflows.
Das heißt man kann nun direkt in der Node den Startpunkt eingeben. msg.top funktioniert aber weiterhin.
-
@mickym ,
danke das funktioniert mit dem LibreHardwareMonitor sehr gut.
Objekte werden jetzt selbst erstellt. -
@mickym
Danke für dein Subflow, kann ich auch gerade sehr gut gebrauchen.Ich hab allerdings Schwierigkeiten die Daten in einen Json String zurück zu konvertieren.
Hab es oben wie Du mit der Tasmota Steckdose es gemacht hast nachgebaut, nur mit einem anderen Pfad.
Aber das klappt nicht, ich nehme an das es am Change Node liegt und dort bei den Regulären Ausdruck ?
Ich möchte ganz einfach das was im IOBroker Pfad untet "0_userdata.0.objRoot" vorhanden ist als Datei speichern.Struktur im IOBroker:
Ergebnis:
{"version":3,"devices.554-6546532-36565-654654.Test":""} -
@bernd1967 Mal unabhängig davon, dass man so eine Struktur im iobroker auch einfach exportieren kann, aber was stimmt denn mit dem Ergebnis nicht? - Das schaut doch richtig aus?
Das was Du vielleicht als Problem ansiehst - ist ggf. gar keines. Falls Du erwartet hast, dass Du unter devices eine hierarchische Struktur bekommst - kann nicht funktionieren, da das kein Objekt ist. Das Problem ist eher die list Node - die gibt auch wenn Du ANY als Filter hast nur die states aus. Da müsste man halt wieder ein Issue aufmachen.
Für das Wiederherstellen der Struktur spielt das aber keine Rolle - diese wird, wenn Du meinen Subflow nimmst wieder 1:1 richtig hergestellt:
Du siehst ja, dass Du aus der List node nur 2 Objekte rausbekommst:
Auch wenn ich das im iobroker direkt exportiere bekommst Du nur 2 Objekte zurück:
Falls Du eine Objekthierarchie in Deinem JSON wiederherstellen möchtest, dann ist da nicht banal und muss man quasi selbst programmieren.
Mit einer Flow Variablen und einer function Node ist das dann sicher am Einfachsten. Hier mal eine Möglichkeit:
damit bekommst dann dieses Ergebnis:
{"version":3,"devices":{"554-6546532-36565-654654":{"Test":""}}}
-
@mickym sagte in JSON String oder Java Object in IOBroker Struktur:
hierarchische Struktur
Ja genau , das hat mich irritiert, die hierarchische Struktur......
Mit deinem Beispiel klappte es
DankeNachtrag: bei komplexen Strukturen entstehen allerding viele Fehler
Ist doch wohl nicht so einfach.