Wie kann ich im Ausführungsteil eines DOIF die Abarbeitung von Befehlen fallabhängig wirksam verzögern?
- Wenn ewas ist, mach A und warte,
- mach B
Also im Falle "es ist", wäre die Ausführung dann "A,warten,B", sonst "sofort B"
Hintergrund:
Ich habe hier eine schaltdimmbare Lampe: War sie länger aus, startet sie mit 100% Helligkeit, schaltet man sie kurz aus und wieder, reduziert sich ihre Helligkeit auf 30, dann auf 10%, dann wieder voll ...
Um sie also auf 10% zu bekommen:
- (ein)(aus)(ein)(aus)(ein)
War sie bereits eingeschaltet, dann muss die Folge lauten:
- (aus)(5s warten)(ein)(aus)(ein)(aus)(ein)
Die erste Schaltaktion ist natürlich nur erforderlich, wenn die Lampe zuvor eingeschaltet war. Also fragt man ab:
(IF ([OGWLicht] eq "on")(set OGWLicht off, sleep 5 quiet), set OGWLicht on, set OGWLicht off, set OGWLicht on, set OGWLicht off, set OGWLicht on)
und schickt damit FHEM in die ewigen Jagdgründe: kein Befehl nach sleep = Freeze.
Ergänze ich nach der Klammer einen Einschaltbefehl,
(IF ([OGWLicht] eq "on")(set OGWLicht off, sleep 5 quiet, set OGWLicht on), set OGWLicht on, set OGWLicht off, set OGWLicht on, set OGWLicht off, set OGWLicht on)
erfolgt der dann doppelt hintereinander, das macht nichts - aber es funktioniert trotzdem nicht, weil beide Befehlsketten parallel abgearbeitet werden:
off (aus der IF-Klammer), on,off,on,off,on (aus dem Teil nach dem IF) - und nach 5s Verzögerung on (aus der IF-Klammer).
Natürlich kann ich die Befehlsketten auch ausführlich je nach Fall ausschreiben, aber das finde ich unelegant.
Bessere Lösung?
sollte das nicht mit dem wait Attribut funktionieren (und ein bisschen umschreiben des DOIF), also etwa so:
("Trigger" and "Lampe ist an")
(mache A)
(führe CMD2 aus)
DOELSIF ("Trigger" and "Lampe ist aus")
(mache B)
[/code}
und 5 Sekunden wait auf CMD1_1
Ob das jetzt eleganter ist sei mal dahingestellt, aber vielleicht eine Idee ;-)
Ja, dammich. Auf die Idee einen anderen command-Ausführungszweig zu triggern um so Code zu sparen war ich noch nicht gekommen.
edit: (Klartextentwurf durch funktionierende DEF ersetzt)
defmod di_LichtOGW_Dimmstufen DOIF ([$SELF:level] eq "AUS") (set OGWLicht off) \
DOELSEIF ([$SELF:level] ne "AUS" and [?OGWLicht] eq "on") ## ausschalten, wenn an, und nach Verzögerung\
(set OGWLicht off)\
(set $SELF cmd_3) ## Zweig 3 ausführen\
DOELSEIF ([$SELF:level] ne "AUS" and [?OGWLicht] eq "off")\
(set OGWLicht on, ## erst mal an\
IF ([$SELF:level] ne "HELL") (set OGWLicht off, set OGWLicht on), ## also DUNKEL oder MITTEL\
IF ([$SELF:level] eq "DUNKEL") (set OGWLicht off, set OGWLicht on)) ## bei DUNKEL zusätzlich\
attr di_LichtOGW_Dimmstufen do always
attr di_LichtOGW_Dimmstufen readingList level
attr di_LichtOGW_Dimmstufen setList level:uzsuSelectRadio,AUS,DUNKEL,MITTEL,HELL
attr di_LichtOGW_Dimmstufen wait 0:0,5:0
attr di_LichtOGW_Dimmstufen webCmd level
Läuft super, vielen Dank.
Danke auch an den Vorschlag von Damian mit dem perl-DOIF, aber ich komme nicht über die Schwelle ... ich liebe gerade diesen selbstsprechenden Code. Bin ja deswegen von notify etc weg...
Besonders "elegant" ist so etwas im Perlmodus, da man dort direkt die Verzögerungszeit angeben kann
DOIF {
my $delay;
if (...) {$delay=0} elsif {$delay=10};
set_Exec ("mytimer",$delay,'fhem_set("bla on")');
}