diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm index 449b4e25a..592f4fbab 100644 --- a/fhem/FHEM/98_DOIF.pm +++ b/fhem/FHEM/98_DOIF.pm @@ -22,7 +22,6 @@ package main; use strict; use warnings; use Color; -use vars qw($FW_wname); # Web instance name sub DOIF_cmd ($$$$); sub DOIF_Notify ($$); @@ -69,6 +68,7 @@ sub DOIF_Initialize($) my ($hash) = @_; $hash->{DefFn} = "DOIF_Define"; $hash->{SetFn} = "DOIF_Set"; + $hash->{GetFn} = "DOIF_Get"; $hash->{UndefFn} = "DOIF_Undef"; $hash->{AttrFn} = "DOIF_Attr"; $hash->{NotifyFn} = "DOIF_Notify"; @@ -80,7 +80,7 @@ sub DOIF_Initialize($) $data{FWEXT}{DOIF}{SCRIPT} = "doif.js"; - $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always,resetwait cmdState state initialize repeatsame repeatcmd waitsame waitdel cmdpause timerWithWait:1,0 notexist selftrigger:wait,all timerevent:1,0 checkReadingEvent:1,0 addStateEvent:1,0 checkall:event,timer,all weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes; + $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always,resetwait cmdState startup state initialize repeatsame repeatcmd waitsame waitdel cmdpause timerWithWait:1,0 notexist selftrigger:wait,all timerevent:1,0 checkReadingEvent:1,0 addStateEvent:1,0 checkall:event,timer,all weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes; } # uiTable @@ -486,10 +486,12 @@ sub DOIF_RegisterEvalAll for (my $m=0;$m < scalar keys %{$hash->{$table}{table}{$i}{$k}{$l}};$m++) { if (defined $hash->{$table}{table}{$i}{$k}{$l}{$m}){ my $value= eval ($hash->{$table}{table}{$i}{$k}{$l}{$m}); - if (defined $hash->{$table}{shownodevicelink} and !$hash->{$table}{shownodevicelink} and defined $defs{$value}) { - $ret.="$value"; - } else { - $ret.=$value; + if (defined ($value)) { + if (defined $defs{$value} and (!defined $hash->{$table}{shownodevicelink} or !$hash->{$table}{shownodevicelink})) { + $ret.="$value"; + } else { + $ret.=$value; + } } } } @@ -501,24 +503,10 @@ sub DOIF_RegisterEvalAll } $ret .= "\n"; # if ($table eq "uiTable"); - # my $jsh = ""; - # $ret .= $jsh.$jsc.$jsf if ($jsc); #$hash->{$table}{deftable}=$ret; return $ret; } -# sub DOIF_summaryFn ($$$$) { - # my ($FW_wname, $d, $room, $pageHash) = @_; - # my $hash = $defs{$d}; - # return ($hash->{$table}{shownostate} ? "" : undef); -# } - sub DOIF_tablePopUp { my ($pn,$d,$icon,$table) = @_; $table = $table ? $table : "uiTable"; @@ -684,8 +672,7 @@ sub SplitDoIf($$) if (defined $tailBlock) { while ($tailBlock ne "") { ($cmd,$tailBlock,$err)=GetCommandDoIf($separator,$tailBlock); - #return (@commands,$err) if ($err); - push(@commands,$cmd); + push(@commands,$cmd) if (defined $cmd); } } return(@commands); @@ -2107,9 +2094,9 @@ sub CheckRegexpDoIf return undef; } -sub DOIF_Trigger ($$) +sub DOIF_Trigger { - my ($hash,$device)= @_; + my ($hash,$device,$checkall)= @_; my $timerNr=-1; my $ret; my $err; @@ -2148,7 +2135,7 @@ sub DOIF_Trigger ($$) $hash->{helper}{event}=$event; } else { #event if (!defined CheckRegexpDoIf($hash,"cond", $device,$i,$hash->{helper}{triggerEvents},1)) { - if (AttrVal($pn, "checkall", 0) !~ "1|all|event") { + if (AttrVal($pn, "checkall", 0) !~ "1|all|event" and !defined $checkall) { next if (!defined ($hash->{devices}{$i})); next if ($hash->{devices}{$i} !~ / $device /); next if (AttrVal($pn, "checkReadingEvent", 0) and !CheckReadingDoIf ($hash->{readings}{$i},$hash->{helper}{triggerEventsState}) and (defined $hash->{internals}{$i} ? $hash->{internals}{$i} !~ / $device:.+ /:1)) @@ -2226,6 +2213,21 @@ DOIF_Notify($$) } } + if (AttrVal($pn,"initialize",0) and !AttrVal($pn,"disable",0)) { + readingsBeginUpdate($hash); + readingsBulkUpdate ($hash,"state",AttrVal($pn,"initialize",0)); + readingsBulkUpdate ($hash,"cmd_nr","0"); + readingsBulkUpdate ($hash,"cmd",0); + readingsEndUpdate($hash, 0); + } + + my $startup=AttrVal($pn, "startup", 0); + if ($startup and !AttrVal($pn,"disable",0)) { + $startup =~ s/\$SELF/$pn/g; + my ($cmd,$err)=ParseCommandsDoIf($hash,$startup,1); + Log3 ($pn,3,"$pn: error in startup: $err") if ($err); + } + my $uiTable=AttrVal($pn, "uiTable", 0); if ($uiTable){ my $err=DOIF_uiTable_def($hash,$uiTable,"uiTable"); @@ -2237,14 +2239,6 @@ DOIF_Notify($$) my $err=DOIF_uiTable_def($hash,$uiState,"uiState"); Log3 ($pn,3,"$pn: error in uiState: $err") if ($err); } - - if (AttrVal($pn,"initialize",0) and !AttrVal($pn,"disable",0)) { - readingsBeginUpdate($hash); - readingsBulkUpdate ($hash,"state",AttrVal($pn,"initialize",0)); - readingsBulkUpdate ($hash,"cmd_nr","0"); - readingsBulkUpdate ($hash,"cmd",0); - readingsEndUpdate($hash, 0); - } } return "" if (!$hash->{helper}{globalinit}); @@ -2745,6 +2739,7 @@ CmdDoIf($$) readingsBeginUpdate($hash); readingsBulkUpdate($hash,"cmd",0); readingsBulkUpdate($hash,"state","initialized"); + readingsBulkUpdate ($hash,"mode","enabled"); readingsEndUpdate($hash, 1); $hash->{helper}{globalinit}=1; } @@ -2853,7 +2848,10 @@ DOIF_Attr(@) } elsif($a[0] eq "set" and $a[2] eq "disable" and $a[3] eq "1") { DOIF_delTimer($hash); DOIF_delAll ($hash); - readingsSingleUpdate ($hash,"state","deactivated",1); + readingsBeginUpdate($hash); + readingsBulkUpdate ($hash, "state", "deactivated"); + readingsBulkUpdate ($hash, "mode", "deactivated"); + readingsEndUpdate ($hash, 1); } elsif($a[0] eq "set" && $a[2] eq "state") { delete $hash->{Regex}{"STATE"}; my ($block,$err)=ReplaceAllReadingsDoIf($hash,$a[3],-2,0); @@ -2888,6 +2886,11 @@ DOIF_Attr(@) #my $table=$a[2]; delete ($hash->{Regex}{$a[2]}); delete ($hash->{$a[2]}); + } elsif($a[0] eq "set" && $a[2] eq "startup") { + my ($cmd,$err)=ParseCommandsDoIf($hash,$a[3],0); + if ($err) { + return ("error in startup $a[3], $err"); + } } return undef; } @@ -2922,7 +2925,7 @@ DOIF_Set($@) readingsBulkUpdate($hash, "mode", "disabled"); readingsEndUpdate ($hash, 1); } elsif ($arg eq "initialize" ) { - delete ($defs{$hash->{NAME}}{READINGS}{mode}); + readingsSingleUpdate ($hash,"mode","enabled",1); delete ($defs{$hash->{NAME}}{READINGS}{cmd_nr}); delete ($defs{$hash->{NAME}}{READINGS}{cmd}); delete ($defs{$hash->{NAME}}{READINGS}{cmd_seqnr}); @@ -2932,7 +2935,9 @@ DOIF_Set($@) #delete ($defs{$hash->{NAME}}{READINGS}{mode}); readingsSingleUpdate ($hash,"state",ReadingsVal($pn,"last_cmd",""),0) if (ReadingsVal($pn,"last_cmd","") ne ""); delete ($defs{$hash->{NAME}}{READINGS}{last_cmd}); - readingsSingleUpdate ($hash,"mode","enable",1) + readingsSingleUpdate ($hash,"mode","enabled",1) + } elsif ($arg eq "checkall" ) { + DOIF_Trigger ($hash,$pn,1); } elsif ($arg =~ /^cmd_(.*)/ ) { if (ReadingsVal($pn,"mode","") ne "disabled") { if ($hash->{helper}{sleeptimer} != -1) { @@ -2955,7 +2960,7 @@ DOIF_Set($@) $cmdList.="cmd_".($i+1).":noArg "; #$cmdList.=EvalCmdStateDoIf($hash,$cmdSubState[0]).":noArg " if defined ($cmdState[$i]); } - return "unknown argument ? for $pn, choose one of disable:noArg initialize:noArg enable:noArg $cmdList $setList"; + return "unknown argument ? for $pn, choose one of disable:noArg initialize:noArg enable:noArg checkall:noArg $cmdList $setList"; } else { my @rl = split(" ", AttrVal($pn, "readingList", "")); my $doRet; @@ -2989,6 +2994,20 @@ DOIF_Set($@) return $ret; } +sub +DOIF_Get($@) +{ + my ($hash, @a) = @_; + my $pn = $a[0]; + return "$pn: get needs at least one parameter" if(@a < 2); + my $arg= $a[1]; + if( $arg eq "html" ) { + return DOIF_RegisterEvalAll($hash,$pn,"uiTable"); + } + + return undef; +} + 1; @@ -3143,7 +3162,7 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel [NEU] Erzeugen berechneter Readings
Vorbelegung des Status mit Initialisierung nach dem Neustart mit dem Attribut initialize
Deaktivieren des Moduls
- Bedingungslose Ausführen von Befehlszweigen
+ Bedingungslose Ausführen von Befehlszweigen
Initialisieren des Moduls
Weitere Anwendungsbeispiele
Zu beachten
@@ -3176,6 +3195,7 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel selftrigger   readingList   setList   + startup   state   timerevent   timerWithWait   @@ -3186,6 +3206,20 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel weekdays  
readingFnAttributes   +
+ Set Befehle
+ +
+ Get Befehle
+
Features   back
@@ -4581,22 +4615,66 @@ Das Attribut do always ist in diesem Beispiel unkritisch, obwohl Temperatur zykl
Das ist insb. dann sinnvoll, wenn das System ohne Sicherung der Konfiguration (unvorhergesehen) beendet wurde und nach dem Neustart die zuletzt gespeicherten Zustände des Moduls nicht mit den tatsächlichen übereinstimmen.

+ +Ausführen von Befehlsketten beim Starten von FHEM   back
+
+Beim Hochfahren von FHEM lässt sich eine bestimme Aktion ausführen. Es kann dazu genutzt werden, um sofort nach dem Hochfahren des Systems einen definierten Zustand des Moduls zu erreichen. +Dabei wird sichergestellt, dass die angegebenen Befehle erst dann ausgeführt werden, wenn FHEM komplett hochgefahren ist.
+
+Symtax:
+
+attr <DOIF-Modul> startup <FHEM-Befehl oder Perl-Befehl in geschweiften Klammern mit DOIF-Syntax>
+
+Die Syntax entspricht der eines DOIF-Ausführungsteils (runde Klammern brauchen nicht angegeben werden).
+
+Beispiele:
+
+attr di_test startup set $SELF cmd_1
+attr di_test startup set $SELF checkall
+attr di_test startup sleep 60;set lamp1 off;set lamp2 off
+attr di_test startup {myfunction()},set lamp1 on,set lamp2 on
+
Deaktivieren des Moduls   back

Ein DOIF-Modul kann mit Hilfe des Attributes disable, deaktiviert werden. Dabei werden alle Timer und Readings des Moduls gelöscht. Soll das Modul nur vorübergehend deaktiviert werden, so kann das durch set <DOIF-modul> disable geschehen. -Hierbei bleiben alle Timer aktiv, sie werden aktualisiert - das Modul bleibt im Takt, allerding werden keine Befehle ausgeführt. -Das Modul braucht mehr Rechenzeit, als wenn es komplett über das Attribut deaktiviert wird. In beiden Fällen bleibt der Zustand nach dem Neustart erhalten, das Modul bleibt deaktiviert.
+
+
+ +Set-Befehle
+
+ +Überprüfung aller DOIF-Bedingungen mit Ausführung eines DOIF-Zweiges   back
+
+mit dem set-Befehl checkall werden wie beim gleichnamigen Attribut alle DOIF-Bedingung überprüft, sobald eine Bedingung als wahr geprüft ist, wird das dazugehörige Kommando ausgeführt. +Zu beachten ist, dass nur der erste wahre DOIF-Zweig ausgeführt wird und dass nur Zustandsabfragen sowie Zeitintervalle sinnvoll überprüft werden können. +Ereignisabfragen sowie Zeitpunkt-Definitionen, sind zum Zeitpunkt der checkall-Abfrage normalerweise nicht wahr.
+
+Beispiel:
+
+attr di_test startup set $SELF checkall
+
+ +Inaktivieren des Moduls   back
+
+mit dem set-Befehl disable wird ein DOIF-Modul inaktiviert. Hierbei bleiben alle Timer aktiv, sie werden aktualisiert - das Modul bleibt im Takt, allerdings werden keine Befehle ausgeführt. +Das Modul braucht mehr Rechenzeit, als wenn es komplett über das Attribut disable deaktiviert wird. Ein inaktiver Zustand bleibt nach dem Neustart erhalten. +Ein inaktives Modul kann über set-Befehle enable bzw. initialize wieder aktiviert werden.
+
+ +Aktivieren des Moduls   back
+
+mit dem set-Befehl enable wird ein inaktives DOIF-Modul wieder aktiviert. Im Gegensatz zum set-Befehl initialize wird der letzte Zustand vor der Inaktivierung des Moduls wieder hergestellt.

Initialisieren des Moduls   back

-Mit set <DOIF-modul> initialize wird ein mit set <DOIF-modul> disable deaktiviertes Modul wieder aktiviert. -Das Kommando set <DOIF-modul> initialize kann auch dazu genutzt werden ein aktives Modul zu initialisiert, -in diesem Falle wird der letzte Zustand des Moduls gelöscht, damit wird ein Zustandswechsel herbeigeführt, der nächste Trigger führt zur Ausführung.
+mit dem set-Befehl initialize wird ein DOIF-Modul initialisiert. Ein inaktives DOIF-Modul wieder aktiviert. +Im Gegensatz zum set-Befehl enable wird der letzte Zustand des Moduls gelöscht, damit wird ein Zustandswechsel herbeigeführt, der nächste Trigger führt zur Ausführung eines wahren DOIF-Zweiges. +Diese Eigenschaft kann auch dazu genutzt werden, ein bereits aktives Modul zu initialisieren.

- + Auführen von Befehlszweigen ohne Auswertung der Bedingung   back

Mit set <DOIF-modul> cmd_<nr> lässt sich ein Befehlszweig (cmd_1, cmd_2, usw.) bedingunglos ausführen.
@@ -4762,7 +4840,7 @@ Hier passiert das nicht mehr, da die ursprünglichen Zustände cmd_1 und cmd_2 j
Wert, der mit dem Regulären Ausdruck übereinstimmt

mode
-
der Modus, in dem sich DOIF befindet: <disabled|enable>
+
der Modus, in dem sich DOIF befindet: <enabled|disabled|deactivated>

state
Status des DOIF nach Befehlsausführung, Voreinstellung: cmd_<Nr. des Befehlszweiges>⟨_<Nr. der Befehlssequenz>⟩
@@ -4867,23 +4945,35 @@ Hier passiert das nicht mehr, da die ursprünglichen Zustände cmd_1 und cmd_2 j
-set-Befehl +set-Befehle + +get-Befehle + Attribute