NEWS
Array erstellen mit Prüfung für Json Tabelle
-
Puh lang ist her, und nun brauche ich mal wieder euer Schwarmwissen.
Ich versuche gerade eine Art Fehlermeldungfenster ala TIA Portal für die Vis zu bauen und benötige dafür eine Tabelle, die ich mit MaterialDesignWidget nutzen wollte.Zu meinen Problem, ich weiß was ich will, finde aber nicht den Faden für die Umsetzung.
Ich versuche es mal zu erklären.
Ich benötige eine fertige Json für die Tabelle. Ok, also brauch in ein Array, wo alle Möglichen Fehlermeldungen drinstehen, die auch aktiv sind.Ob die Meldung dann auch per arr.push geschrieben werden soll, muss noch vorher geprüft werden
Stelle mir ein Array so in der Art vor. Das kann ich dann beliebig erweitern und auch Prüfungen auf <50% oder so machen.Meldenummer1, Prüfung ID auf irgendwas, arr.push(Meldetext1) Meldenummer2, Prüfung ID auf irgendwas,arr.push( Meldetext2) ...
Leider komme ich absolut nicht weiter, wie ich das coden kann.
im Array, wo alle Meldungen mit Aktoren versehen sind, müsste auch immer drauf reagiert werden, wenn irgendein Aktor was meldet, damit auch nur die Meldungen angezeigt werden, die true sind.Ich hatte mal versucht das Fenster Zählen Script abzuwandeln, leider ohne Erfolg.
Vielleicht hat jemand sowas schon irgendwo im Gebrauch.
Danke und Gruß
-
@ple
Ich greife mal einen Ansatz aus dem anderen Thread auf zur Erstellung der Alias-Datenpunkte mit gleichen Eigenschaften für einen Selektor:var typeAlias, read, write, nameAlias, role, desc, min, max, unit, states, custom; function createAlias(idSrc, idDst) { if(existsState(idDst)) log(idDst + ' schon vorhanden !', 'warn'); else { var obj = {}; obj.type = 'state'; obj.common = getObject(idSrc).common; obj.common.alias = {}; obj.common.alias.id = idSrc; if(typeAlias) obj.common.type = typeAlias; if(obj.common.read !== false && read) obj.common.alias.read = read; if(obj.common.write !== false && write) obj.common.alias.write = write; if(nameAlias) obj.common.name = nameAlias; if(role) obj.common.role = role; if(desc) obj.common.desc = desc; if(min !== undefined) obj.common.min = min; if(max !== undefined) obj.common.max = max; if(unit) obj.common.unit = unit; if(states) obj.common.states = states; if(custom && obj.common.custom) obj.common.custom = custom; obj.native = {}; setObject(idDst, obj); } } let meldungen = [ {trigger: "hm-rpc.xxxxxx", message: "Fenster im Schlafzimmer ist offen" }, {trigger: "XXXXXXX", check: "val >= 100", message: "Jalousie im Schlafzimmer ist oben" }, {trigger: 'ping.0.192_168_10_1'/*Steuerung*/, check: "!val", message: "Server nicht erreichbar" } ] typeAlias = 'boolean'; role = 'indicator'; custom = []; for(let i = 0; i < meldungen.length; i++) { let idOrigin = meldungen[i].trigger; let idAlias = 'alias.0.Meldungen.M' + (i + 1); nameAlias = meldungen[i].message; read = meldungen[i].check; createAlias(idOrigin, idAlias); }
EDIT: Die Auswertung der Alias-Datenpunkte kann dann mit einem einfachen Script erfolgen.
const idsMsg = $('alias.0.Meldungen.*'); function schleife() { let arrMsg = []; // Array mit allen Namen, deren DP den Wert true hat idsMsg.each(function(id, i) { if(getState(id).val) arrMsg.push(getObject(id).common.name); }); // Array für Darstellung auswerten } idsMsg.on(schleife); // Triggert bei Wertänderung eines Datenpunktes schleife(); // Scriptstart
-
Erstmal vielen herzlichen Dank für deine Unterstützung und Beispiele.
Ich glaube, mit den Alias bin ich doch auf dem falschen Wege, oder ich schiebe es mal weiter nach hinten.
Ist aber sehr interessant für andere Sachen.Ich versuche es mal wieder wie am Anfang, somit benötige ich, wenn es denn klappt. keine Datenpunkte.
let Meldung = [ {trigger: 'javascript.0.Test.test', Check: "true oder false oder Wert in %", message: "test" }, {trigger: 'ping.0.10_170_21_254'/*Server*/, Check: "true oder false oder Wert in %", message: "Server nicht erreichbar" }, {trigger: 'ping.0.192_168_10_1'/*Steuerung*/, Check: "true oder false oder Wert in %", message: "Steuerung nicht erreichbar" }, ] on({id: Meldung.trigger, change: "ne" }, function () { log(" hat mal ausgelöst") })
Ich versuche gerade auf das array Meldung den trigger zu reagieren. Bei einem Array wie diesen hier funktioniert das auch.
let Meldung = ['ping.0.192_168_10_1', 'javascript.0.Test.test', 'ping.0.10_170_21_254' ]
Es es überhaupt möglich da irgendwie drauf zu reagieren mit each oder sowas?
Wenn ja, dann würde ich dadrin die Prüfung ablaufen lassen und per Push die Meldungsjson zusammenbauen oder entfernen lassen.Gruß und Danke
schön mal wieder mehr Zeit für den iobroker zu haben. -
Nicht das du denkst, ich würde mit deinen Informationen nichts anfangen
Ich bin noch mal zurück zum Anfang gegangen und habe mir was zusammengebastelt. Hat zwar einige Nachmittage gebraucht, aber der Start ist gemacht und ich glaube damit komme ich zum Ziel meines Vorhaben.
Könnte man auch für Fenstersensoren usw. benutzen, naja, hoffe ich zumindest.Es ist noch am Anfang, ich weiß auch garnicht wie dreckig ich das programmiert habe ;-), aber über Ratschläge wäre ich sehr dankbar, man lern ja nie aus.
Was noch fehlt.- Meldenummer fortlaufen anhand der Meldungen in Reihenfolge (wichtigste stehen oben zu erste)
- Filtermöglichkeiten später?
- Datum der Meldung.
var pfad = "javascript." + "0.Log.Meldung."; var output_json = pfad + "output_json" var Aktor_1 = pfad + "Aktor_1" var Aktor_2 = pfad + "Aktor_2" var Aktor_3 = pfad + "Aktor_3" var Aktor_4 = pfad + "Aktor_4" createState(output_json,"", { name: "output_json", desc: "", type: "string", }); createState(Aktor_1, false, { name: "Aktor 1", desc: "", type: "boolean", }); createState(Aktor_2, false, { name: "Aktor 2", desc: "", type: "boolean", }); createState(Aktor_3, false, { name: "Aktor 3", desc: "", type: "boolean", }); createState(Aktor_4, 0, { name: "Aktor 4", desc: "", type: "number", }); let json = [] let meldung = [ { trigger: 'javascript.0.Log.Meldung.Aktor_1'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 1 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_2'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 2 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_3'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 3 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_4'/*Aktor 1*/, check1: '>=50', check2: "<51", message: "Aktor 4 ist über 50%" }, ] meldung.forEach(meld => { on({ id: meld.trigger, change: "ne" }, function () { let trigger = getState(meld.trigger).val // Überprüfung boolean if (eval('' + trigger + meld.check1) && (json.indexOf(meld.message) == -1)) { json.push(meld.message) } else if (eval('' + trigger + meld.check2) && json.indexOf(meld.message) >= 0) { json.splice(json.indexOf(meld.message), 1) } log(json.indexOf(meld.message)) log(json) setState(output_json, JSON.stringify(json)) }) })
-
Tja, leider hänge ich am nächsten Problem.
Ich muss wohl im Array ein Object pushen, damit ich später meine Table direkt bekomme.
Nur leider finde ich nicht heraus, wie man später in dem Array nach schon bereits existierende Meldung suchen kann und diese auch aus dem Objekt wieder löschen kann, falls der Aktor wieder auf false geht.
Das Script von Mic
https://github.com/Mic-M/iobroker.logfile-script#23-script-einstellen
ist schon sehr hilfreich, aber leider für mich nicht nachvollziehbar.
Hat vielleicht jemand noch einen Ansatz oder eine Idee?var pfad = "javascript." + "0.Log.Meldung."; var output_json = pfad + "output_json" var output_raw = pfad + "output_raw" var Aktor_1 = pfad + "Aktor_1" var Aktor_2 = pfad + "Aktor_2" var Aktor_3 = pfad + "Aktor_3" var Aktor_4 = pfad + "Aktor_4" createState(output_json, "", { name: "output_json", desc: "", type: "string", }); createState(output_raw, "", { name: "output_raw", desc: "", type: "string", }); createState(Aktor_1, false, { name: "Aktor 1", desc: "", type: "boolean", }); createState(Aktor_2, false, { name: "Aktor 2", desc: "", type: "boolean", }); createState(Aktor_3, false, { name: "Aktor 3", desc: "", type: "boolean", }); createState(Aktor_4, 0, { name: "Aktor 4", desc: "", type: "number", }); let arr = [] let arr_test = [] let meldung = [ { trigger: 'javascript.0.Log.Meldung.Aktor_1'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 1 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_2'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 2 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_3'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 3 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_4'/*Aktor 1*/, check1: '>=50', check2: "<51", message: "Aktor 4 ist über 50%" }, ] meldung.forEach(meld => { on({ id: meld.trigger, change: "ne" }, function () { let trigger = getState(meld.trigger).val let obj = { "Datum": "", "Meldung": meld.message }; // Überprüfung boolean if (eval('' + trigger + meld.check1) ) { //Meldung ist nicht vorhanden log("schreiben") arr.push(obj) // log(arr.indexOf(obj)) // log(arr) } else if (eval('' + trigger + meld.check2) ) { arr.splice(arr.indexOf(obj.Meldung), 1) log("löschen") } log(arr.indexOf(meld.message)) log(arr) }) })
-
so würde ich das Problem angehen:
var meldung = [ { trigger: 'javascript.0.Log.Meldung.Aktor_1'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 1 mit ist true", subscription:0 }, { trigger: 'javascript.0.Log.Meldung.Aktor_2'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 2 mit ist true", subscription:0 }, { trigger: 'javascript.0.Log.Meldung.Aktor_3'/*Aktor 1*/, check1: "==true", check2: "==false", message: "Aktor 3 mit ist true", subscription:0 }, { trigger: 'javascript.0.Log.Meldung.Aktor_4'/*Aktor 1*/, check1: '>=50', check2: "<51", message: "Aktor 4 ist über 50%", subscription:0 }, ] for (var a=0;a<meldung.length;a++) { meldung[a].subscription = on({ id: meldung[a].trigger, change: "ne" }, main); } main(obj) { if (!meldung || meldung.length==0) return; var a = 0; for (a=0;a<meldung.length;a++) { if ( meldung[a].trigger == obj.Id ) break; } if (a==meldung.length) return; // entferne trigger; var meld = meldung[a]; if (meld.subscription) unsubscribe(meld.subscription); })
ungetestet und kann Syntaxfehler enthalten
Ups das war nicht die aktuelle Frage. sry
Zur aktuellen Frage könnte das klappen. Ist aber ebenfalls ungetestet
} else if (eval('' + trigger + meld.check2) ) { arr = arr.filter(({"Meldung"}) => Meldung != obj.Meldung); log("löschen") }
-
@ple sagte:
arr.splice(arr.indexOf(obj.Meldung), 1)
funktioniert nicht wie erwartet ? Dann verwende eine Schleife über arr.
-
Hab gerade etwas ähnliche gebraucht:
function sendMsg(f, msg) { if (messageArray.findIndex(function(a){ return (a.from == f && a.msg == msg)}) != -1) return; messageArray[0]={"from":f,"msg":msg};
-
@ticaki said in Array erstellen mit Prüfung für Json Tabelle:
Hab gerade etwas ähnliche gebraucht:
function sendMsg(f, msg) { if (messageArray.findIndex(function(a){ return (a.from == f && a.msg == msg)}) != -1) return; messageArray[0]={"from":f,"msg":msg};
Kannst du mir vielleicht dein ganzen script zur Verfügung stellen? leider verstehe ich einfach nicht, was da genau passiert.
Durch try and error bin ich mit meinem jetzt so weit.
var pfad = "javascript." + "0.Log.Meldung."; var output_json = pfad + "output_json" var Aktor_1 = pfad + "Aktor_1" var Aktor_2 = pfad + "Aktor_2" var Aktor_3 = pfad + "Aktor_3" var Aktor_4 = pfad + "Aktor_4" createState(output_json, "", { name: "output_json", desc: "", type: "string", }); createState(Aktor_1, false, { name: "Aktor 1", desc: "", type: "boolean", }); createState(Aktor_2, false, { name: "Aktor 2", desc: "", type: "boolean", }); createState(Aktor_3, false, { name: "Aktor 3", desc: "", type: "boolean", }); createState(Aktor_4, 0, { name: "Aktor 4", desc: "", type: "number", }); let arr = [] let arr_test = [] let meldung = [ { trigger: 'javascript.0.Log.Meldung.Aktor_1'/*Aktor 1*/, debug: "Störung", check1: "==true", check2: "==false", message: "Aktor 1 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_2'/*Aktor 1*/, debug: "Störung", check1: "==true", check2: "==false", message: "Aktor 2 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_3'/*Aktor 1*/, debug: "Störung", check1: "==true", check2: "==false", message: "Aktor 3 mit ist true" }, { trigger: 'javascript.0.Log.Meldung.Aktor_4'/*Aktor 1*/, status: "error", check1: '>=50', check2: "<51", message: "Aktor 4 ist über 50 %" }, ] meldung.forEach(meld => { on({ id: meld.trigger, change: "ne" }, function () { let trigger = getState(meld.trigger).val let trigger_ts = formatDate(getDateObject(getState(meld.trigger).ts), "JJJJ.MM.TT SS:mm:ss"); let obj = { "Datum": trigger_ts, "Art": meld.debug, "Meldung": meld.message }; let alarm = false arr.forEach(function (a, Index) { if (a.Meldung == obj.Meldung) { alarm = true if (eval('' + trigger + meld.check2)) { arr.splice(Index, 1) //log("löschen") } } else { alarm = false } }) if (eval('' + trigger + meld.check1) && (!alarm)) { arr.push(obj) } //log(arr) setState(output_json, JSON.stringify(arr)) }) })
Ich weiß aber, dass die Werte bei iobroker neustart nicht eingelesen werden und das sortieren klappt auch noch nicht.
Eigentlich eine feine Sache, um sich den Status von Datenpunkten ausgeben zu lassen und die direkt visualisieren lassen zu können. Noch besser wäre es, wenn man das irgendwie mit dem Script für Logs realisieren könnte, da man dort direkt auch Filtern kann und eine ganze Menge mehr Sachen machen, aber leider zu hoch für mich.Gruß
-
@ple sagte in Array erstellen mit Prüfung für Json Tabelle:
mit .findIndex kannst du eine Funktion aufrufen, in der du prüfen kannst ob das übergebene Object(oder was auch immer) deiner Suche entspricht. Ich suche hier den Eintrag in dem from und msg == den übergebenen Werten ist und geben über return true zurück, wenn dem so ist.
messageArray.findIndex(function(a) { return (a.from == f && a.msg == msg) })
Ich hab nen Display der 3 Zeilen anzeigen kann und dieses Script verwaltet das.
var messageArray = [{},{},{}]; messageArray[0] = {"from":"","msg":"-1"}; messageArray[1] = {"from":"","msg":"-1"}; messageArray[2] = {"from":"","msg":"-1"}; onMessage("DisplayMessage", function(data,result){ var msgfrom = data[2]; var mode = data[1]; var msg = data[0].toString(); if (msg.length == 0 && mode !=0) return; var done = false; switch (mode) { case 0: done = deleteAllMsg(msgfrom); break; case 1: done = sendMsg(msgfrom,msg); break; case 2: done = deleteMsg(msgfrom,msg); break; } if (done) { var check=true; while(check) { check=false; var first=-1; for (var i=0; i<3;i++){ if (messageArray[i].msg != '-1' && first != -1) { messageArray[first] = messageArray[i]; log(messageArray[i].msg+' swap int:'+ i +' '+first); check = true; break; } if (messageArray[i].msg=='-1') { first = i; } } } for (var i=0; i<messageArray.length;i++){ if (typeof messageArray[i].msg == 'number') { setState('mqtt.1.display.show.Nachricht.msg'+(i+1), '-1'); } else { setState('mqtt.1.display.show.Nachricht.msg'+(i+1), messageArray[i].msg); } } } }); function sendMsg(f, msg) { if (messageArray.findIndex(function(a){ return (a.from == f && a.msg == msg)}) != -1) return; // keine doppelten Einträge var a = 2; while (a--) { messageArray[a] = messageArray[a-1]; } messageArray[0]={"from":f,"msg":msg}; return true; } function deleteAllMsg(f) { for (var a=0;a<3;a++){ if (messageArray[a].from == f) messageArray[a]={"from":"","msg":"-1"}; } return true; } function deleteMsg(f,msg) { for (var a=0;a<3;a++){ if (messageArray[a].msg==msg && messageArray[a].from == f ) { messageArray[a]={"from":"","msg":"-1"}; return true; } } return false; }