FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: timtom am 21 April 2017, 15:26:43

Titel: Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 21 April 2017, 15:26:43
Hallo zusammen,

ich bin dabei meine Heizungssteuerung weiter zu optimieren. Derzeit nutze ich folgendes vereinfachtes DOIF zur Ansteuerung von LightScenes
di_ZuhauseStatusLS DOIF (
[Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Abwesend")\
  (set ZuhauseStatusLS scene SummerAbsent) DOELSEIF \
([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Zuhause")\
  (set ZuhauseStatusLS scene SummerHome) DOELSEIF \
([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Abwesend")\
  (set ZuhauseStatusLS scene WinterAbsent) DOELSEIF \
([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Gone")\
  (set ZuhauseStatusLS scene WinterGone) DOELSEIF \
([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Zuhause")\
  (set ZuhauseStatusLS scene WinterHome) DOELSEIF \
attr di_ZuhauseStatusLS do always


Das funktioniert soweit schon mal gut. Mit ist jedoch aufgefallen, dass wenn ich aus dem Status "Winter+Gone" komme, noch einen Zwischenbefehl anstoßen möchte. Dieser wird nicht benötigt, wenn ich zwischen den anderen Status wechsele. Laut Commandref sollte es bei DOIF ein Reading last_cmd geben. Dies finde ich dort aber nicht.
Gibt es noch noch eine andere Möglichkeit?
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 21 April 2017, 18:15:02
Das Reading last_cmd wird nur im Zusammenhang mit set disable gesetzt, um bei set enable den vorherigen Zustand zu setzen.

Das Reading state wird erst nach der Befehlsauführung auf den geänderten Zustand gesetzt, daher könntest Du in die betreffenden Zweige eine IF-Abfrage einbauen

(IF ($cmd = 5) (<Zwischenbefehl>), set ZuhauseStatusLS scene ... )
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: ComputerZOO am 22 April 2017, 11:23:47
Moin moin,
passt hier vielleicht nur bedingt rein (aber dafür will ich kein neues Thema aufmachen). Wie kann ich:
Log 3, "DIES IST EIN TEXT FÜR DAS LOGFILE, LEVEL 3;
in ein DOIF einfügen?
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 22 April 2017, 11:48:44
Zitat von: ComputerZOO am 22 April 2017, 11:23:47
Moin moin,
passt hier vielleicht nur bedingt rein (aber dafür will ich kein neues Thema aufmachen). Wie kann ich:
Log 3, "DIES IST EIN TEXT FÜR DAS LOGFILE, LEVEL 3;
in ein DOIF einfügen?
Schau mal unter "Angaben im Ausführungsteil" nach.
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: ComputerZOO am 22 April 2017, 12:00:53
Danke  ;)
Lösung: {Log 3, "DIES IST EIN TEXT FÜR DAS LOGFILE, LEVEL 3}
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 22 April 2017, 14:44:18
Zitat von: Ellert am 21 April 2017, 18:15:02
Das Reading last_cmd wird nur im Zusammenhang mit set disable gesetzt, um bei set enable den vorherigen Zustand zu setzen.

Das Reading state wird erst nach der Befehlsauführung auf den geänderten Zustand gesetzt, daher könntest Du in die betreffenden Zweige eine IF-Abfrage einbauen

(IF ($cmd = 5) (<Zwischenbefehl>), set ZuhauseStatusLS scene ... )
Ok, prima. Danke. Kann man das alles auch noch irgendwie "schicker" lösen? Also außer den beiden Möglichkeiten?
1) Dein Vorschlag wäre es ja, in das DOIF jeweils noch ein IF einzuschachteln.
2) Man müsste die das gesamte DOIF-Konstrukt duplizieren und und jeweils 1x mit $cdm=5 und ohne machen
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 22 April 2017, 15:55:28
zu 2): Nein, der Zwischenbefehl wird nur ausgeführt, wenn vorher der Status 5 war, der set-Befehl immer.
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 23 April 2017, 12:01:36
Zitat von: Ellert am 22 April 2017, 15:55:28
zu 2): Nein, der Zwischenbefehl wird nur ausgeführt, wenn vorher der Status 5 war, der set-Befehl immer.
Sorry, da hab ich mich wohl missverständlich ausgedrückt. Ich hatte hierbei an sowas gedacht.

...
DOIF [Heizungsmodus:state] eq "Sommer" and ($cmd = 5)
  (set Zwischenbefehl)
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF  [Heizungsmodus:state] eq "Sommer"
  (set ZuhauseStatusLS scene SummerAbsent)
...


Rein theoretisch würde ja deine IF-Lösung gehen. Hier geht es mit wohl eher um den Programmierstil ;)
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 23 April 2017, 18:45:56
Zitat($cmd = 5)

Die runden Klammern sind nicht erforderlich (s. Rangfolge von Operatoren)
"=" ist ein Zuweisungsoperator, kein Vergleichsoperator, s. DOIF-Doku Ereignissteuerung
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 24 April 2017, 10:30:06
Ok, d.h.
...
DOIF [Heizungsmodus:state] eq "Sommer" and [$SELF:state] eq "5"
  (set Zwischenbefehl)
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF  [Heizungsmodus:state] eq "Sommer" and [$SELF:state] ne "5"
  (set ZuhauseStatusLS scene SummerAbsent)
...


oder so?

...
DOIF [Heizungsmodus:state] eq "Sommer"
  (IF ([$SELF:state] eq "5") (<Zwischenbefehl>))
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF...

Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 24 April 2017, 15:44:33
Fast richtig  ;)

[$SELF:cmd] == 5 oder [$SELF] eq "cmd_5" oder [$SELF:state] eq "cmd_5" oder $cmd == 5

Auch so, weil "Kommt ein Device in mehreren Bedingungen vor, so wird immer nur ein Kommando ausgeführt, und zwar das erste, für das die dazugehörige Bedingung in der abgearbeiteten Reihenfolge wahr ist."
...
DOIF [Heizungsmodus:state] eq "Sommer" and $cmd eq "5"
  (set Zwischenbefehl)
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF  [Heizungsmodus:state] eq "Sommer"
  (set ZuhauseStatusLS scene SummerAbsent)
...
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 24 April 2017, 16:01:15
Danke. Ich möchte es ja auch in paar Monaten auch noch verstehen. Also entweder paar Bedingungen mehr oder Kommentare ;)

Dann werd ich das die Tage mal testen.
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Per am 25 April 2017, 13:39:41
Müssen die Bedingungen gesammt nicht mehr in runde Klammern?
...
DOIF ([Heizungsmodus:state] eq "Sommer" and $cmd eq "5")
  (set Zwischenbefehl)
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF  ([Heizungsmodus:state] eq "Sommer")
  (set ZuhauseStatusLS scene SummerAbsent)
...
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 25 April 2017, 14:01:12
Zitat von: Per am 25 April 2017, 13:39:41
Müssen die Bedingungen gesammt nicht mehr in runde Klammern?
Ups, habe ich im "richtigen" Code natürlich auch gemacht ;)
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 25 April 2017, 16:25:20
Zitat von: Ellert am 24 April 2017, 15:44:33
Fast richtig  ;)

Also, nach etwas hin und her sieht es jetzt so aus. Passt das oder habe ich da einen Denkfehler drin?
define di_ZuhauseStatusLS DOIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "KurzWeg") ## Wechsel der LightScenes im Sommer-Modus
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "LangeWeg")
  (set ZuhauseStatusLS scene SummerGone)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Zuhause")
  (set ZuhauseStatusLS scene SummerHome)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Auto")
  (set ZuhauseStatusLS scene SummerAuto)
DOELSEIF (([Heizungsmodus:state] eq "Winter" and [ZuhauseStatusLS:state] =~ "Summer") ##Schaltet die Thermostate erst in den Auto-Modus, wenn man von einer Summer- in eine Winter-LightScene wechselt
  (set ZuhauseStatusLS scene WinterAuto)
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "KurzWeg")
  (IF ([ZuhauseStatusLS:state] eq "WinterGone") (set ZuhauseStatusLS scene WinterAuto), set ZuhauseStatusLS scene WinterAbsent) ##Schaltet die Thermostate erst in den Auto-, wenn diese vorher im Energiespar-Modus waren
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "LangeWeg")
  (set ZuhauseStatusLS scene WinterGone)
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Zuhause")
  (IF ([ZuhauseStatusLS:state] eq "WinterGone") (set ZuhauseStatusLS scene WinterAuto), set ZuhauseStatusLS scene WinterHome) ##Schaltet die Thermostate erst in den Auto-, wenn diese vorher im Energiespar-Modus waren
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Auto")
  (set ZuhauseStatusLS scene WinterAuto)

Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: Ellert am 25 April 2017, 19:43:45
Was spricht dagegen es auszuprobieren?
Titel: Antw:Ausführen eines Befehls nach Verlassen eines DOIF-Zustands
Beitrag von: timtom am 26 April 2017, 09:51:06
Zitat von: Ellert am 25 April 2017, 19:43:45
Was spricht dagegen es auszuprobieren?
Nichts ;) War noch ein keiner Fehler drin. Jetzt sollte es aber passen.
([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "KurzWeg")
  (set ZuhauseStatusLS scene SummerAbsent)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "LangeWeg")
  (set ZuhauseStatusLS scene SummerGone)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Zuhause")
  (set ZuhauseStatusLS scene SummerHome)
DOELSEIF ([Heizungsmodus:state] eq "Sommer" and [ZuhauseStatus:state] eq "Auto")
  (set ZuhauseStatusLS scene SummerAuto)
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "KurzWeg")
  (IF ([ZuhauseStatusLS:state] =~ "Summer" or [ZuhauseStatusLS:state] eq "WinterGone") (set ZuhauseStatusLS scene WinterAuto), set ZuhauseStatusLS scene WinterAbsent) ##Schaltet die Thermostate erst in den Auto-Modus, wenn diese vorher im Sommer- oder Energiespar-Modus waren
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "LangeWeg")
  (set ZuhauseStatusLS scene WinterGone)
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Zuhause")
  (IF ([ZuhauseStatusLS:state] =~ "Summer" or [ZuhauseStatusLS:state] eq "WinterGone") (set ZuhauseStatusLS scene WinterAuto), set ZuhauseStatusLS scene WinterHome) ##Schaltet die Thermostate erst in den Auto-Modus, wenn diese vorher im Sommer- oder Energiespar-Modus waren
DOELSEIF ([Heizungsmodus:state] eq "Winter" and [ZuhauseStatus:state] eq "Auto")
  (set ZuhauseStatusLS scene WinterAuto)


Danke für die Hilfe.