NEWS
Probleme mit ack in Adaptern und Scripten
-
Vielleicht habe ich Verständnisprobleme oder es fehlt mir die Erklärung, aber ich komme mit dem 'ack' nicht zurecht!
Laut Beschreibung ist ack=false das Kommando und ack=true die Rückmeldung vom Sensor dass das Kommando ausgeführt wurde!
Nun, ich habe viele Geräte (auch eine CCU2) aber 80% davon (mit Ausnahme der CCU) verwenden keine oder andere ack=true/false - Methoden.
Als Beispiel, ich habe einen Adapter welcher per text stream Zustandsänderungen meldet und ich per Rest-Api diese initiieren kann.
Die Änderungen von Zuständen können jedoch noch von außen passieren und dann wird dann per stream natürlich genauso gemeldet.
Ich hatte original den Adapter so eingestellt dass er ein setState mit ack=?false mach wenn er einen Wert setzt (und dann per Rest-Api auf das Device weitergibt).
Wenn Das Device per test-stream das Device als umgeschaltet meldet habe ich mit ack=true das wieder eingetragen.
Nun hab ich aber das Problem dass ich Z.B in VIS die States nicht upgedated bekomme wenn ein externes Signal (also nur mit ack=true) ohne vorher ein Command mit ack=false kommt! Komischer Weise bei Werten wie Temperaturen ist es kein Problem aber states setzten sich nicht um und auch der Zeitpunkt der letzten Änderung wird nicht upgedated.
Ich hätte eher an folgende Logik für die internen states gedacht:
-
ack=false: Kommando, also setzt KEINEN Wert um sondern gibt NUR das Kommando an das gerät!
-
ack = true: setzt Wert auf neuen Wert! Änderungen werden aufgezeichet u.s.w…
-
ack = undefined: Gibt Kommando und setzt Wert…, das ist für alle Adapter die keine Rückmeldungen machen (wie z.B. die GPIO pins oder einige der FS20 oder anderen Funkadapter)
Wie ist das wirklich implementiert? Irgenwie hab ich das Gefühl dass es in verschiedenen Adaptern unterschiedlich gehandhabt wird und deshalb werden je nach Fähigkeit des Devices/Adapters unterschiedliche Ergebnisse erzielt.
Ich habe selbst Adapter die, wie im Beispiel zwar melden wenn was 'geändert' worden ist aber andere die das nicht tun, davon können einige gepollt werden um einen aktuellen Status anzuzeigen.
Ich habe versucht durch Polling den Status upzudaten, scheitere aber daran dass der Wert nicht umgesetzt wird wenn ich ack=true setzte da viele Dinge nur auf commands reagieren. Bei ack=false werden aber bei Änderungen andere Kommandos und Updates (von VIS) nicht immer (oder vielleicht nicht von allen Adaptern) durchgeführt.
Für mich ist das falsch!
ack=false sollte kein state ändern und nichts im ioBroker Status setzten, es sollte doch nur 'Diesem einem Adapter dem das State gehört' melden dass er das Kommando aussenden soll und dann eventuell nach Rückmeldung das State ändern soll! Ok, wenn der Adapter keine Rückmeldung kriegt dann muss er sie selbst sofort generieren, und er könnte mit einem 'proposedState-Objekt' vielleicht in den ioBroker-Objekt speichern dass ein Kommando gesendet wurde welches noch nicht berücksichtigt wurde. Bei der Rückmeldung würde das dann gelöscht werden. Es kann ja auch sein dass man sich wünscht dass ein state gestzt wird aber das nicht möglich ist da andere Bedingungen dafür nicht vorhanden sind.
Damit wird das Komanndo ausgesendet und vielleicht ein Rückmeldung generiert die wieder einen anderen Wert hat!
Wer kann mir helfen zu verstehen wie die ioBroker - Strategie dafür eigentlich definiert ist und wie die Implementierung in Scripts oder Adaptern zu geschehen hat.
Ich sehe die folgenden 3 Möglichkeiten und hätte gerne gesehen wie sie implementiert werden können oder sollen und welche setStates jede Box verwenden soll/kann.
Ach ja, hab ganz vergessen: Ein Kommando (=Befehl an den Adapter) kann natürlich auch VIELE Daten verändern die alle durch Rückmeldungen dann umgesetzt werden müssen, das gilt für die 1. und 2. Variante oben!
Mit Aktionen setzten meine ich dass ioBroker jetzt erst die internen Variablen setzten sollte und eventuelle Aktionen mit on(…) ausführen sollte.
p.s.: Frohe Weihnachten! Muss 2 Adapter updaten um diese Logik zu implementieren
-
-
In meinen Augen ist es korrekt das bei "ack=false" das auch genau so gespeichert wird. Die States-Datenpunkte stellen immer den "letzten Zustand" dar.
Ein Kommando besteht aus zwei Schritten:
1.) Wenn man das Kommando sendet wird das mit "ack=false" (weil nur gesendet und von der Gegenseite noch nicht bestätigt) gespeichert. So kann auch jede Logik sehen ob das letzte Kommando ausgeführt wurde.
2.) Wenn der Zieladapter das Kommando ausgeführt hat wird der State mit "ack=true" als Bestätigung aktualisiert.
Einzig blöd am ersten Schritt ist, wenn ein Kommando nicht erledigt wird hat man den vorhergehenden (echten) Status nicht mehr im Zugriff.
Ich glaube auch das diese Idee bei den meisten Adaptern nicht sauber umgesetzt ist, bzw die meisten Adapter liefern ja am Ende nur Daten. Diese schreiben Sie einfach mit ack=true und alle anderen können konsumieren. Und wenn Adapter "kommando"-Datenpunkte haben dann werden die meistens nur für die Kommandos benutzt und an der Stelle glaube ich oft das "ack"-Flag ignoriert weil eine Schreibaktion nur andere Datenpunkte aktualisiert …
Oder ?!
-
Zu deinen drei Optionen
1.) Nutzersicht (also der User der das Kommando sendet)
A) setState mit ack=false
B) Warten gibts an sich nicht …bzw entspricht einem "subscribe" auf den Datenpunkt wo man die Änderung erwartet
C) Idealerweise der asynchrone Callback mit dem "subscribe"
1.) Adaptersicht
A) der Adapter macht faktisch nichts, ausser das er einen subscribe auf den State hat sodass er auf Änderungen reagieren kann. Wenn eine Änderung kommt kann der Adapter müsste das "ack=false" ist und dann die entsprechende Aktion ausführen. Alle geänderten Werte schreibt er mit "ack=true"
2.) siehe 1.) Weil am Ende ja nicht der gleiche Datenpunkt von einem Kommando aktualisiert werden muss. Oder auch nichts. User sendet mit "ack=false" das Kommando, Adapter tut was er tun muss. Fertig. Wenn das so ist. ist eine Rückmeldung vom Adapter ja nicht nötig ... oder im Zuge von "GPIO"-Kram will man vllt den entsprechenden kanal als Wert auf das neu gesetzte aktualisieren
3.) User macht subscribe auf die Werte und verarbeitet nur alles mit "ack=true"