NEWS
Rückmeldung, ob Befehl angekommen / Ack-State
-
Hallo zusammen,
ioBroker ist ein erstklassiges Projekt mit fast unbegrenzten Möglichkeiten - vielen Dank mal an alle, die das möglich machen.
Mir fällt aber auf, dass das Thema "Fehlerbehandlung" und hier insbesondere Rückmeldung bzw. der Ack-State quasi nicht behandelt wird, obwohl ioBroker ja die Funktionen beinhaltet.
Wir gehen ja in der Regel immer davon aus, dass der ausgelöste Befehl auch ankommt. Es gibt aber unzählige Möglichkeiten, warum das eben nicht passiert, z.B. weil die Verbindung zum Aktor gestört ist oder er garnicht aktiv ist (Shelly: keine WLAN-Verbindung oder Aktor stromlos, Homematic: duty cycle überschritten etc.).
Extrembeispiel ist sicher die Gartenbewässerung, bei der der Aus-Befehl nicht ankommt (und in ioBroker / VIS und Co. aber als "aus" signalisiert wird).
Ein Topic dazu habe ich z.B. hier gefunden (Ack-State-Überwachung mit Blockly):
https://forum.iobroker.net/topic/32275/ack-state-abfragen-lesen/5Welche Möglichkeit gibt es denn, das etwas zu professionalisieren, am besten mit einer Liste, in die Datenpunkte aufgenommen werden, die überwacht werden sollen? Sehr gerne mit oben verlinktem Blockly-Skript. Die Signalisierung in VIS erst bei erfolgreicher Rückmeldung ist dann wieder ein anderes Thema.
Danke Euch
-
@IOBaer sagte:
mit einer Liste, in die Datenpunkte aufgenommen werden, die überwacht werden sollen? Sehr gerne mit oben verlinktem Blockly-Skript.
Mit Blockly wird das leider nichts, da man in Blockly kein Array of timers verwenden kann. In Javascript geht es etwa so:
const ids = ['id1', 'id2', 'id3']; const timers = []; const vals = []; on({id: ids}, function (dp) { let idx = ids.indexOf(dp.id); if (dp.state.ack) { if (dp.state.val == vals[idx]) clearTimeout(timers[idx]); // Ist = Soll } else if (dp.state.val != dp.oldState.val) { vals[idx] = dp.state.val; timers[idx] = setTimeout(function () { // sendTo('...'); }, 2000); } });
-
Ganz lieben Dank.
Gibt es eine Möglichkeit, nur die Auslöselogik in JS zu hinterlegen und den Rest in Blockly abzubilden?
Was müsste ich in Deinem JS anpassen?
-
@IOBaer sagte:
den Rest in Blockly abzubilden?
Welchen Rest ?
Das Problem in Blockly ist "Ausführen timeout". -
Warum funktioniert dann das verlinkte Blockly? Allerdings natürlich nur mit einem Datenpunkt.
Mit Rest meine ich das, was dann passieren soll, z.B. eine Telegram-Nachricht o.ä.
Danke Dir.
-
@IOBaer sagte:
Warum funktioniert dann das verlinkte Blockly?
Weil ein Datenpunkt nur eine Timer-Variable (timeout) und kein Array of timers benötigt.
-
Verstehe. Ich muss aber nun in diesem JS auch eintragen, was danach passieren soll und kann kein Blockly antriggern? Wobeis ich dann ja auch die Frage stellen würde, wie man die Informationen wie betroffener Datenpunkt o.ä. übergibt.
Edit: sieht ähnlich aus wie https://forum.iobroker.net/topic/32275/ack-state-abfragen-lesen/23
-
@IOBaer sagte:
Ich muss aber nun in diesem JS auch eintragen, was danach passieren soll und kann kein Blockly antriggern?
Nein. Wie willst Du dem separaten Blockly-Skript z.B. den Datenpunktnamen übergeben ?
Das Senden wirst Du auch in Javascript hinbekommen, z.B.sendTo('telegram', {user: 'UserName', text: dp.common.name + ' wurde nicht bestätigt !'});
-
@paul53 Funktioniert in einem ersten Test einwandfrei. Vielen Dank. Da wird dann auch wieder klar, dass an (direktem) JS kein Weg vorbeiführt.
-
@paul53 Wenn ich dieses tolle Skript nochmal aufwärmen darf: kann man das eigentlich auch so gestalten, dass er die betroffenen / zu überwachenden Datenpunkte aus einer Aufzählung automatisch zieht?
Ich habe das jetzt mal doch via Blockly mit "IDs vom Selektor" getestet und es scheint zu funktionieren - obwohl dort doch wohl das "Array of times" fehlt?
In JS umgewandelt:
var soll, timeout2; on({id: Array.prototype.slice.apply($("state[id=*](functions=temp11)")), change: "any"}, function (obj) { var value = obj.state.val; var oldValue = obj.oldState.val; if ((obj.state ? obj.state.ack : "")) { if (soll == (obj.state ? obj.state.val : "")) { (function () {if (timeout2) {clearTimeout(timeout2); timeout2 = null;}})(); } } else { if ((obj.state ? obj.state.val : "") != (obj.oldState ? obj.oldState.val : "")) { soll = (obj.state ? obj.state.val : ""); (function () {if (timeout2) {clearTimeout(timeout2); timeout2 = null;}})(); timeout2 = setTimeout(function () { sendTo("telegram", "send", { text: ([['Datum / Uhrzeit: ',[formatDate(getDateObject((obj.state ? obj.state.ts : "")), "DD.MM.YYYY"),' / ',formatDate(getDateObject((obj.state ? obj.state.ts : "")), "hh:mm:ss")].join(''),'\n'].join(''),['Objekt-ID: ',obj.id,'\n'].join(''),['Beschreibung: ',(obj.common ? obj.common.desc : ""),'\n'].join(''),['Kanalname: ',obj.channelName,'\n'].join(''),['Ursprung: ',(obj.state ? obj.state.from : ""),'\n'].join(''),'--------------------------------------','\n','Warnung: Nicht bestätigt.','','','\n','--------------------------------------'].join('')) }); }, 2000); } } });
"temp11" ist die Aufzählung aus ioBroker, die den Datenpunkten zugeordnet ist, die überwacht werden sollen.
Entspricht das, was Blockly da gezaubert hat, Deinem ursprünglichen JS-Code? Danke Dir!
-
@paul53 habe das Skript nochmal neu einstellen müssen, weil "wurde aktualisiert" statt "wurde geändert" in Blockly nötig war. Hilfe dazu aus diesem Thema: https://forum.iobroker.net/topic/32275/ack-state-abfragen-lesen/11