Triggern auf jegliche Zustandsänderung

Begonnen von vbs, 26 Februar 2017, 13:51:43

Vorheriges Thema - Nächstes Thema

vbs

Sorry, blöde Frage, aber ich hab offenbar das Grundprinzip von DOIF immer noch nicht verstanden ???

Der Plan war eigentlich ein DOIF zu machen, das immer auslöst, wenn sich der state in einem von zwei Devices ändert:
DEF        ([env_presence] or [wz_mode]) ({updateDevices("$DEVICE", "$EVENT")})
   NAME       sys_di_updateDevices
   NR         523
   NTFY_ORDER 50-sys_di_updateDevices
   STATE      cmd_1
   TYPE       DOIF
   Readings:
     2017-02-26 13:43:28   Device          env_presence
     2017-02-26 13:42:06   cmd             1
     2017-02-26 13:42:06   cmd_event       env_presence
     2017-02-26 13:42:06   cmd_nr          1
     2017-02-26 13:43:28   e_env_presence_STATE home
     2017-02-26 13:43:06   e_wz_mode_STATE tv
     2017-02-26 13:42:06   state           cmd_1
     2017-02-26 13:42:06   wait_timer      no timer


Eigentlich sollte jetzt mMn das DOIF immer ausführen, wenn sich der state von env_presence ODER wz_mode ändert. Aber wie man in dem Listing sieht, passiert das nicht. Um 13:43:28 hat sich env_presence auf home geändert und um 13:43:06 wz_mode auf tv. Ausgeführt wurde aber zum letzten Mal um 13:42:06.
Wenn ich do_always setzte, dann klappts, also dann wirds ausgeführt wie erwartet. Aber warum? Ich dachte do_always braucht man nur, wenn man mehrfach auf den gleichen Zustand auslösen möchte?

Und wie macht mans besser? Zwingend auf ereignisbasierte Triggerung umstellen? Also in der Art [env_presence:".*"]? Im Idealfall wird wirklich nur auf eine Änderung des Zustands reagiert. Also wenn home (warum auch immer) nochmal auf home gesetzt wird, dann sollte nicht getriggert werden.

dieter56

Hallo,

ich denke, es fehlt

attr sys_di_updateDevices do always

Ellert

#2
Zitatwenn man mehrfach auf den gleichen Zustand auslösen möchte?

Zustand, bezieht sich auf den Zustand des DOIF und nicht auf den Zustand der abgefragten Geräte.

So steht es auch in der Einleitung der Befehlsreferenz zu DOIF:
ZitatDas DOIF-Modul arbeitet mit Zuständen. Jeder Ausführungszweig DOIF/DOELSEIF..DOELSEIF/DOELSE stellt einen eigenen Zustand dar (cmd_1, cmd_2, usw.). Das Modul merkt sich den zuletzt ausgeführten Ausführungszweig und wiederholt diesen standardmäßig nicht. Ein Ausführungszweig wird erst dann wieder ausgeführt, wenn zwischenzeitlich ein anderer Ausführungszweig ausgeführt wurde, also ein Zustandswechsel stattgefunden hat.

ZitatAlso wenn home (warum auch immer) nochmal auf home gesetzt wird, dann sollte nicht getriggert werden.

Das könntest Du mit event-on-change-reading an der Quelle abfangen.

Alternativ vielleicht auch mit [env_presence] ne OldValue("env_presence") or ...

vbs

Zitat von: Ellert am 26 Februar 2017, 14:14:17
Zustand, bezieht sich auf den Zustand des DOIF und nicht auf den Zustand der abgefragten Geräte.
Ach, das ist ja höchstinteressant! :) Das hab ich nie kapiert scheinbar, aber das macht jetzt vieles klarer, danke!
Aber das heißt im Endeffekt, dass jedes DOIF, welches nur einen Zweig hat, eigentlich nur Sinn mit do_always macht, oder? Ansonsten führt er den Zweig ja nur einmal aus und dann nie wieder?

Damian

Zitat von: vbs am 26 Februar 2017, 14:48:53
Ach, das ist ja höchstinteressant! :) Das hab ich nie kapiert scheinbar, aber das macht jetzt vieles klarer, danke!
Aber das heißt im Endeffekt, dass jedes DOIF, welches nur einen Zweig hat, eigentlich nur Sinn mit do_always macht, oder? Ansonsten führt er den Zweig ja nur einmal aus und dann nie wieder?

Nicht ganz.

DOIF ([test] eq "on") (set bla off)

In diesem Fall wird ohne do always intern ein DOELSE gesetzt, sonst hätte man nur einmal Spaß daran;)


Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

vbs

Hm, wieder etwas verwirrt jetzt. Also der Unterschied zu meinem Fall ist, dass meins immer wahr ist (da keine Bedingung formuliert) und er daher niemals in das "virtuelle" DOELSE reinläuft?

Damian

Zitat von: vbs am 26 Februar 2017, 15:04:28
Hm, wieder etwas verwirrt jetzt. Also der Unterschied zu meinem Fall ist, dass meins immer wahr ist (da keine Bedingung formuliert) und er daher niemals in das "virtuelle" DOELSE reinläuft?

Fast!

Du hast sehr wohl eine Bedingung definiert, die wird allerdings nur theoretisch nicht wahr, wenn stati von [env_presence] und [wz_mode] nicht da wären, leer wären oder beide gleich Null wären.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

vbs

Alles klar, danke! Ich denke jetzt versteh ich es wesentlich besser!

vbs

Argh, ich nochmal: Ich hab das jetzt so:
([env_presence] or [wz_mode]) ({updateDevices("$DEVICE", "$EVENT")})
mit do_always.

Triggert nun bei jeder state-Änderungen an env_presence oder wz_mode, so weit so gut. Das unschöne ist, dass es aber auch bei jedem anderen Event an den Devices triggert (und daher cmd_1 recht oft aufgerufen wird), was ja erstmal auch so dokumentiert ist.
Aber was kann ich tun, damit das DOIF wirklich nur bei Änderungen an state triggert (und nicht bei anderen Events)? Das einzige, was ich wüsste, wäre das auf Events umzustellen. Evtl. so:
([env_presence:"^state:"] or [wz_mode:"^state:"]) ({updateDevices("$DEVICE", "$EVENT")})

Dazu dann wohl noch "addStateEvent" setzen. Ist natürlich dann irgendwie doch etwas sperrig. Hat jemand eine Idee, wie das noch schicker gehen würde?
Danke!

Bonusfrage: Wenn das DOIF nur Events enthält (keine Reading-Auswertung), dann gibt es wohl keinen "virtuellen" DOELSE-Zweig, oder? Also in dem Fall bräuchte man dann doch immer do_always, oder? (also wenn es nicht explizit ein DOELSE/IF gibt)

dieter56

Du könntest mit


attr env_presence event-on-change-reading state
attr wz_mode event-on-change-reading state


nur Änderungen von state in den beiden Devices an das DOIF weiterreichen.


vbs

Achso sorry, hab ich nicht erwähnt, aber event-on-change-reading hab ich gesetzt für die Devices. Jedoch reicht für mich nur state nicht aus. Da hängt zum Beispiel ein Statistik-Modul dran, welches stündlich auch Events erzeugt, die ich in einer Datenbank logge. Und diese Events lösen dann auch immer das DOIF aus und triggern mein {updateDevices}.

dieter56

In der CommandRef zu DOIF steht:

ZitatStandardmäßig werden angegebene Readings ausgewertet, wenn irgend ein Event des angegebenen Devices triggert. Möchte man gezielt nur dann ein angegebenes Reading auswerten, wenn sich nur dieses ändert, so lässt sich das mit dem Attribut checkReadingEvent einschränken. Das ist insb. dann interessant, wenn ein Modul verschiedene Readings zu unterschiedlichen Zeitpunkten aktualisiert.

Wenn ich das richtig verstehe, müsste es also so funktionieren:


define sys_di_updateDevices  ([env_presence:state] or [wz_mode:state]) ({updateDevices("$DEVICE", "$EVENT")})
attr sys_di_updateDevices checkReadingEvent 1



Ellert


dieter56

Das reicht aber nicht, da state im Event in der Standardeinstellung nicht mitgeschrieben wird.
Deshalb muss auch das Attribut addStateEvent gesetzt werden

vbs

@dieter56
Danke! Das mit dem "checkReadingEvent" ist ein super Tipp. Hatte ich schonmal gelesen, aber dann natürlich nicht selbst drauf gekommen.. probier ich aus!

@Ellert
Das selber in Perl per OldValue zu machen geht bestimmt, finde ich aber nicht so schick muss ich sagen. Danke trotzdem!

Nochmal eine generelle Frage:
Gibt es einen Unterschied zwischen:
([myDevice])
und
([myDevice:state])
?

Ich dachte das Weglassen von "state" wäre nur "syntatic sugar", meint aber implizit state?