NEWS
Zigbee Adapter Fehlerbehandlung möglich?
-
Moin liebes Forum,
heute morgen sollte ein Zigbee Gerät eigentlich ein Licht ausschalten. Das Licht blieb an, im Log ein Fehler:
zigbee.0 2021-03-31 07:59:11.669 error (22801) Send command to 0x804b50fffeb73c9f failed with no error code (no response received)
Frage nun: Kann man auf so ein Ereignis reagieren? Das Command neu senden?
-
Kann man. Allerdings wird nicht auf die Fehlermeldung selber reagiert sondern auf das ausbleiben des "acknowledge" des DP. Problematisch ist dabei das Risiko einer Endlosschleife.
Man Nehme:
Wobei die beiden Blöcke "command or update" und "state value" der gleiche Block aus dem Trigger Bereich sind.Mit diesem Skript wird max. 3 mal der Datenpunkt neu angesteuert wenn das "acknowledge" der Hardware ausbleibt.
A.
-
@asgothian Hört sich gut an - kannst du das mal als JS posten? Sonst müsste ich das in Blockly erst nachbauen
-
@asgothian Ok hab mir das mal selbst zusammengeblockt. Grundsätzlich hab ich das kapiert - Das Ack = true bestätigt, dass das Setzen des States durchgeführt wurde (Das Licht also geschaltet wurde). Falls ich mich nicht irre ist in deinem Blockly dann aber ein Fehler ? Das "Is Command or Update" müsste doch negiert werden? Du willst ja das Setzen des States bis zu 3 mal wiederholen solange das Ack = false ist ? Kommt ein Ack=true ist das Setzen (Licht schalten) erfolgreich gewesen? Klär mich mal auf?
-
@kitzelblitze wenn du mit "is command or update" ansteuerst dann ist das der Versuch die hardware zu steuern. Wann immer das passiert wird ein 20 sekunden timeout gestartet, der automatisch beendet wird wenn eine weitere Aktualisierung des Wertes ankommt.
Kommt innerhalb von 20 sekunden keine dann wird der State nochmal angesteuert.
Kommt sie, dann hat der Zigbee Adapter den Wert Bestätigt und der Zähler kann auf 0 zurück gesetzt werden.
A.
-
@asgothian Vielleicht hab ich mich falsch ausgedrückt - Habe dein Blockly in JS konvertieren lassen:
on({id: "Object ID", change: "any"}, async function (obj) { var value = obj.state.val; var oldValue = obj.oldState.val; (function () {if (timeout2) {clearTimeout(timeout2); timeout2 = null;}})(); if ((obj.state ? obj.state.ack : "") && repeatcount <= 3) { timeout2 = setTimeout(async function () { repeatcount = (typeof repeatcount == 'number' ? repeatcount : 0) + 1; setState("Object ID", (obj.state ? obj.state.val : "")); }, 1000); } else { repeatcount = 0; } });
so kann ich das besser verstehen - Was ich meinte: Es wird
if ((obj.state ? obj.state.ack : "") && repeatcount <= 3)
geprüft - Heisst: Wenn das Update von der Hardware kommt (dann ist ack=true) und repeatcount <= 3 ... dann setze Timeout usw.
Das ist doch nicht korrekt so?
-
@kitzelblitze Hmm..
da passt aber dann der Blockly Baustein nicht zum JS, da hast du recht. Ich hätte eher mit (if (!obj.state.ack && repeat count < 3) gerechnet.
A.
-
@asgothian Uiuiui - Okay dann stimmt was mit dem Blocklykonverter nicht - Egal - ich hab mal kurz ne JS Klasse gebaut, die man an irgendeiner Stelle als Addon für ein Lichtstate verwenden kann. Somit wird jedes Licht automatisch zu einem "Mehrfachversucher": (Bitte vergebt mir meine Klammersetzung)
class RetrySetter { constructor (objectid,maxretry,timeoutms) { var desiredstate = null; var timeout = null; var retrycount = 0; on({id:objectid,change:"any"},function(obj) { if (obj.state.ack == false || (desiredstate!=null && obj.state.val!=desiredstate)) // we got a new state to perform on { if (desiredstate!=null && obj.state.val!=desiredstate) retrycount=0; desiredstate = obj.state.val; console.log(objectid+" trying to get ack for state = "+desiredstate); if (timeout) {clearTimeout(timeout);timeout=null;} timeout = setTimeout(function() { retrycount++; if (retrycount==maxretry+1) { retrycount=0; desiredstate=null; return; } console.log(objectid+" retry to set state = "+desiredstate+" retry = "+retrycount); setState(objectid,desiredstate); },timeoutms); } if (obj.state.ack == true && obj.state.val==desiredstate) // we got our ack { retrycount=0; if (timeout) {clearTimeout(timeout);timeout=null;} console.log(objectid+" happy to tell the ack has come with desired state = "+desiredstate); desiredstate=null; } }); } } new RetrySetter("zigbee.0.0017880108b5533e.state",10,5000);
Macht für das im Konstruktor angegebene Zigbee Gerät max 10 Versuche mit 5000 Sekunden Timeout dazwischen.