diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index a7ea2b365..471533b6d 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -60,6 +60,8 @@ sub DOIF_delAll($)
delete ($hash->{triggertime});
delete ($hash->{ptimer});
delete ($hash->{interval});
+ delete ($hash->{intervaltimer});
+ delete ($hash->{intervalfunc});
delete ($hash->{perlblock});
delete ($hash->{var});
@@ -88,7 +90,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 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;
+ $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:0,1 addStateEvent:1,0 checkall:event,timer,all weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes;
}
# uiTable
@@ -1559,110 +1561,83 @@ sub DOIF_weekdays($$)
sub
DOIF_CheckTimers($$$$)
{
+ my ($hash,$timer,$condition,$trigger)=@_;
my $i=0;
- my @nrs;
- my @times;
- my $nr=0;
- my $days="";
+ my $days;
my $err;
- my $beginning;
- my $pos;
my $time;
my $block;
my $result;
- my ($hash,$timer,$condition,$trigger)=@_;
+ my $end;
+ my $intervaltimer;
$timer =~ s/\s//g;
- while ($timer ne "") {
- if ($timer=~ /^\+\(/) {
- ($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\(\)]');
- return ($time,$err) if ($err);
- $time="+(".$time.")";
- ($result,$err)=ReplaceAllReadingsDoIf($hash,$time,-3,0);
- return ($time,$err) if ($err);
- } elsif ($timer=~ /^\(/) {
- ($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\(\)]');
- return ($time,$err) if ($err);
- $time="(".$time.")";
- ($result,$err)=ReplaceAllReadingsDoIf($hash,$time,-3,0);
- return ($time,$err) if ($err);
- } elsif ($timer=~ /^\{/) {
- ($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\{\}]');
- return ($time,$err) if ($err);
- $time="{".$time."}";
- } elsif ($timer=~ m/^\+\[([0-9]+)\]:([0-5][0-9])/g) {
- $pos=pos($timer);
- $time=substr($timer,0,$pos);
- $timer=substr($timer,$pos);
- } elsif ($timer=~ /^\+\[/) {
- ($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\[\]]');
- return ($time,$err) if ($err);
- $time="+[".$time."]";
- ($result,$err)=ReplaceAllReadingsDoIf($hash,$time,-3,0);
- return ($time,$err) if ($err);
- } elsif ($timer=~ /^\[/) {
- ($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\[\]]');
- return ($time,$err) if ($err);
- $time="[".$time."]";
- ($result,$err)=ReplaceAllReadingsDoIf($hash,$time,-3,0);
- return ($time,$err) if ($err);
- } elsif ($timer =~ /-/g) {
- $pos=pos($timer)-1;
- $time=substr($timer,0,$pos);
- $timer=substr($timer,$pos);
- } else {
- ($time,$days)=split(/\|/,$timer);
- $timer="";
- }
- $times[$i]=$time;
- $nrs[$i++]=$hash->{helper}{last_timer}++;
- if ($timer) {
- if ($timer =~ /\-/g) {
- $timer=substr($timer,pos($timer));
- } elsif ($timer =~ /\|/g) {
- $days=substr($timer,pos($timer));
- $timer="";
- } else {
- return ($timer,"wrong time format");
- }
+ ($timer,$days)=SplitDoIf('|',$timer);
+ $days="" if (!defined $days);
+ ($timer,$intervaltimer)=SplitDoIf(',',$timer);
+ ($time,$end)=SplitDoIf('-',$timer);
+ if (defined $intervaltimer) {
+ if (!defined $end) {
+ return($timer,"intervaltimer without time interval");
}
}
- $days = "" if (!defined ($days));
- for (my $j=0; $j<$i;$j++) {
- $nr=$nrs[$j];
- $time=$times[$j];
- $time .=":00" if ($time =~ m/^[0-9][0-9]:[0-5][0-9]$/);
- $hash->{timer}{$nr}=0;
- $hash->{time}{$nr}=$time;
- $hash->{timeCond}{$nr}=$condition;
- $hash->{days}{$nr}=$days if ($days ne "");
- if ($init_done) {
- DOIF_SetTimer($hash,"DOIF_TimerTrigger",$nr);
- #$err=(DOIF_SetTimer($hash,"DOIF_TimerTrigger",$nr));
- #return($hash->{time}{$nr},$err) if ($err);
- }
- $hash->{timers}{$condition}.=" $nr " if ($trigger);
+ $i=$hash->{helper}{last_timer}++;
+ if (defined $time) {
+ ($result,$err) = DOIF_getTime($hash,$condition,$time,$trigger,$i,$days);
+ return ($result,$err) if ($err);
+ } else {
+ return($timer,"no timer defined");
}
- if ($i == 2) {
+ if (defined $end) {
+ ($result,$err) = DOIF_getTime($hash,$condition,$end,$trigger,$hash->{helper}{last_timer}++,$days);
+ return ($result,$err) if ($err);
+ }
+ if (defined $intervaltimer) {
+ ($result,$err) = DOIF_getTime($hash,$condition,$intervaltimer,$trigger,$hash->{helper}{last_timer}++,$days);
+ return ($result,$err) if ($err);
+ }
+ if (defined $end) {
if ($days eq "") {
- $block='DOIF_time($hash,'.$nrs[0].','.$nrs[1].',$wday,$hms)';
+ $block='DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms)';
} else {
- $block='DOIF_time($hash,'.$nrs[0].','.$nrs[1].',$wday,$hms,"'.$days.'")';
+ $block='DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms,"'.$days.'")';
+ }
+ $hash->{interval}{$i}=-1;
+ $hash->{interval}{($i+1)}=$i;
+ if (defined ($intervaltimer)) {
+ $hash->{intervaltimer}{$i}=($i+2);
+ $hash->{intervaltimer}{($i+1)}=($i+2);
+ $hash->{intervalfunc}{($i+2)}=$block;
}
- $hash->{interval}{$nrs[0]}=-1;
- $hash->{interval}{$nrs[1]}=$nrs[0];
} else {
if ($days eq "") {
- $block='DOIF_time_once($hash,'.$nrs[0].',$wday)';
+ $block='DOIF_time_once($hash,'.$i.',$wday)';
} else {
- $block='DOIF_time_once($hash,'.$nrs[0].',$wday,"'.$days.'")';
+ $block='DOIF_time_once($hash,'.$i.',$wday,"'.$days.'")';
}
}
+ if ($init_done) {
+ DOIF_SetTimer ($hash,"DOIF_TimerTrigger",$i);
+ DOIF_SetTimer ($hash,"DOIF_TimerTrigger",($i+1)) if (defined $end);
+ DOIF_SetTimer ($hash,"DOIF_TimerTrigger",($i+2)) if (defined $intervaltimer);
+ }
return ($block,"");
}
-sub
-DOIF_time
-{
+sub DOIF_getTime {
+ my ($hash,$condition,$time,$trigger,$nr,$days)=@_;
+ my ($result,$err)=ReplaceAllReadingsDoIf($hash,$time,-3,0);
+ return ($time,$err) if ($err);
+ $time .=":00" if ($time =~ m/^[0-9][0-9]:[0-5][0-9]$/);
+ $hash->{timer}{$nr}=0;
+ $hash->{time}{$nr}=$time;
+ $hash->{timeCond}{$nr}=$condition;
+ $hash->{days}{$nr}=$days if ($days);
+ $hash->{timers}{$condition}.=" $nr " if ($trigger);
+}
+
+
+
+sub DOIF_time {
my $ret=0;
my ($hash,$b,$e,$wday,$hms,$days)=@_;
$days="" if (!defined ($days));
@@ -1700,9 +1675,7 @@ DOIF_time
return 0;
}
-sub
-DOIF_time_once
-{
+sub DOIF_time_once {
my ($hash,$nr,$wday,$days)=@_;
$days="" if (!defined ($days));
my $flag=$hash->{timer}{$nr};
@@ -1722,10 +1695,7 @@ DOIF_time_once
return 0;
}
-############################
-sub
-DOIF_SetState($$$$$)
-{
+sub DOIF_SetState($$$$$) {
my ($hash,$nr,$subnr,$event,$last_error)=@_;
my $pn=$hash->{NAME};
my $cmdNr="";
@@ -1779,7 +1749,6 @@ DOIF_SetState($$$$$)
}
}
- # if ($state and !defined $hash->{do}{$nr}{$subnr+1}) {
if ($state) {
my $stateblock='\['.$pn.'\]';
$state =~ s/$stateblock/$cmd/g;
@@ -1796,8 +1765,7 @@ DOIF_SetState($$$$$)
}
}
-sub
-DOIF_we($) {
+sub DOIF_we($) {
my ($wday)=@_;
my $we = (($wday==0 || $wday==6) ? 1 : 0);
if(!$we) {
@@ -1810,9 +1778,7 @@ DOIF_we($) {
return $we;
}
-sub
-DOIF_CheckCond($$)
-{
+sub DOIF_CheckCond($$) {
my ($hash,$condition) = @_;
my $err="";
my ($seconds, $microseconds) = gettimeofday();
@@ -1894,11 +1860,7 @@ DOIF_CheckCond($$)
return ($ret,$err);
}
-
-
-sub
-DOIF_cmd ($$$$)
-{
+sub DOIF_cmd ($$$$) {
my ($hash,$nr,$subnr,$event)=@_;
my $pn = $hash->{NAME};
my $ret;
@@ -1995,8 +1957,7 @@ DOIF_cmd ($$$$)
}
-sub CheckiTimerDoIf($$$)
-{
+sub CheckiTimerDoIf($$$) {
my ($device,$itimer,$eventa)=@_;
my $max = int(@{$eventa});
my $found;
@@ -2145,7 +2106,7 @@ sub DOIF_Perl_Trigger
if (!defined CheckRegexpDoIf($hash,"cond", $device,$i,$hash->{helper}{triggerEvents},1)) {
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))
+ next if (AttrVal($pn, "checkReadingEvent", 1) and !CheckReadingDoIf ($hash->{readings}{$i},$hash->{helper}{triggerEventsState}) and (defined $hash->{internals}{$i} ? $hash->{internals}{$i} !~ / $device:.+ /:1))
}
$event="$device";
}
@@ -2213,7 +2174,7 @@ sub DOIF_Trigger
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))
+ next if (AttrVal($pn, "checkReadingEvent", 1) and !CheckReadingDoIf ($hash->{readings}{$i},$hash->{helper}{triggerEventsState}) and (defined $hash->{internals}{$i} ? $hash->{internals}{$i} !~ / $device:.+ /:1))
}
}
$event="$device";
@@ -2282,9 +2243,8 @@ DOIF_Notify($$)
delete $defs{$hash->{NAME}}{READINGS}{$key} if ($key =~ "^timer_");
}
if ($hash->{helper}{last_timer} > 0){
- for (my $j=0; $j<$hash->{helper}{last_timer};$j++)
- {
- DOIF_SetTimer($hash,"DOIF_TimerTrigger",$j);
+ for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
+ DOIF_SetTimer ($hash,"DOIF_TimerTrigger",$j);
}
}
@@ -2331,9 +2291,12 @@ DOIF_Notify($$)
#return "" if (!$hash->{itimer}{all} and !$hash->{devices}{all} and !keys %{$hash->{Regex}});
if (($hash->{itimer}{all}) and $hash->{itimer}{all} =~ / $dev->{NAME} /) {
- for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
- if (CheckiTimerDoIf ($dev->{NAME},$hash->{time}{$j},$eventas)) {
- DOIF_SetTimer($hash,"DOIF_TimerTrigger",$j);
+ for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
+ if (CheckiTimerDoIf ($dev->{NAME},$hash->{time}{$j},$eventas)) {
+ DOIF_SetTimer ($hash,"DOIF_TimerTrigger",$j);
+ if (defined $hash->{intervaltimer}{$j}) {
+ DOIF_SetTimer($hash,"DOIF_TimerTrigger",$hash->{intervaltimer}{$j});
+ }
}
}
}
@@ -2355,7 +2318,7 @@ DOIF_Notify($$)
foreach my $item (split(/ /,$hash->{readings}{all})) {
($device,$reading)=(split(":",$item));
if ($item and $device eq $dev->{NAME} and defined ($defs{$device}{READINGS}{$reading})) {
- if (!AttrVal($pn, "checkReadingEvent", 0) or CheckReadingDoIf ("$item",$eventas)) {
+ if (!AttrVal($pn, "checkReadingEvent", 1) or CheckReadingDoIf ("$item",$eventas)) {
readingsSingleUpdate ($hash, "e_".$dev->{NAME}."_".$reading,$defs{$device}{READINGS}{$reading}{VAL},0);
}
}
@@ -2435,9 +2398,7 @@ DOIF_Notify($$)
return undef;
}
-sub
-DOIF_TimerTrigger ($)
-{
+sub DOIF_TimerTrigger ($) {
my ($timer)=@_;
my $hash=${$timer}->{hash};
my $pn = $hash->{NAME};
@@ -2474,6 +2435,13 @@ DOIF_TimerTrigger ($)
if ($hash->{interval}{$j} != -1) {
DOIF_SetTimer($hash,"DOIF_TimerTrigger",$hash->{interval}{$j});
DOIF_SetTimer($hash,"DOIF_TimerTrigger",$j,1);
+ #if (defined $hash->{intervaltimer}{$j}) {
+ # DOIF_DelInternalTimer($hash, $hash->{intervaltimer}{$j});
+ #}
+ } else {
+ if (defined $hash->{intervaltimer}{$j}) {
+ DOIF_SetTimer($hash,"DOIF_TimerTrigger",$hash->{intervaltimer}{$j});
+ }
}
} else {
DOIF_SetTimer($hash,"DOIF_TimerTrigger",$j,1);
@@ -2486,6 +2454,15 @@ DOIF_TimerTrigger ($)
#return($ret);
}
+sub DOIF_DelInternalTimer {
+ my ($hash, $nr) = @_;
+ RemoveInternalTimer(\$hash->{triggertime}{$hash->{localtime}{$nr}});
+ delete ($hash->{triggertime}{$hash->{localtime}{$nr}});
+ my $cond=$hash->{timeCond}{$nr};
+ my $timernr=sprintf("timer_%02d_c%02d",($nr+1),($cond+1));
+ delete ($defs{$hash->{NAME}}{READINGS}{$timernr});
+}
+
sub
DOIF_DetTime($$)
{
@@ -2567,6 +2544,7 @@ DOIF_CalcTime($$)
my $pos;
my $ret;
my $align;
+ my $alignInCalc;
if ($block=~ m/^\+\[([0-9]+)\]:([0-5][0-9])$/) {
($err,$rel,$block,$align)=DOIF_DetTime($hash,$block);
return ($block,$err,$rel,$align);
@@ -2594,9 +2572,6 @@ DOIF_CalcTime($$)
($beginning,$block,$err,$tailBlock)=GetBlockDoIf($tailBlock,'[\{\}]');
return ($block,$err) if ($err);
if ($block ne "") {
- # $ret = eval $block;
- # return($block." ",$@) if ($@);
- # $block=$ret;
($err,$rel,$block)=DOIF_DetTime($hash,"{".$block."}");
return ($block,$err) if ($err);
}
@@ -2612,7 +2587,8 @@ DOIF_CalcTime($$)
($block,$err,$device,$reading,$internal)=ReplaceReadingEvalDoIf($hash,$block,1);
return ($block,$err) if ($err);
}
- ($err,$rel,$block)=DOIF_DetTime($hash,$block);
+ ($err,$rel,$block,$alignInCalc)=DOIF_DetTime($hash,$block);
+ $align=$alignInCalc if ($alignInCalc);
return ($block,$err) if ($err);
}
$cmd.=$beginning.$block;
@@ -2623,9 +2599,7 @@ DOIF_CalcTime($$)
return ($ret,"",$relGlobal,$align);
}
-sub
-DOIF_SetTimer
-{
+sub DOIF_SetTimer {
my ($hash, $func, $nr,$next_day) = @_;
my $timeStr=$hash->{time}{$nr};
my $cond=$hash->{timeCond}{$nr};
@@ -2668,7 +2642,9 @@ DOIF_SetTimer
}
my ($now, $microseconds) = gettimeofday();
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now);
+ my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($now);
+ my $hms_now = sprintf("%02d:%02d:%02d", $hour, $min, $sec);
+ my $wday_now = $wday;
my $isdst_now=$isdst;
my $sec_today = $hour*3600+$min*60+$sec;
@@ -2681,7 +2657,7 @@ DOIF_SetTimer
if ($second <= $sec_today and !$rel or defined ($next_day) and !$rel and $second < 86400 and !$align) {
$next_time+=86400;
- ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($next_time);
+ ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($next_time);
if ($isdst_now != $isdst) {
if ($isdst_now == 1) {
$next_time+=3600 if ($isdst == 0);
@@ -2690,7 +2666,22 @@ DOIF_SetTimer
}
}
}
-
+ if (defined ($hash->{intervalfunc}{$nr})) {
+ my $hms = $hms_now;
+ $wday = $wday_now;
+ my $cond=$hash->{timeCond}{$nr};
+ my $timernr=sprintf("timer_%02d_c%02d",($nr+1),($cond+1));
+ if (!eval ($hash->{intervalfunc}{$nr})) {
+ delete ($defs{$hash->{NAME}}{READINGS}{$timernr});
+ return undef;
+ }
+ ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($next_time);
+ $hms = sprintf("%02d:%02d:%02d", $hour, $min, $sec);
+ if (!eval ($hash->{intervalfunc}{$nr})) {
+ delete ($defs{$hash->{NAME}}{READINGS}{$timernr});
+ return undef;
+ }
+ }
my $next_time_str=strftime("%d.%m.%Y %H:%M:%S",localtime($next_time));
$next_time_str.="\|".$hash->{days}{$nr} if (defined ($hash->{days}{$nr}));
readingsSingleUpdate ($hash,$timernr,$next_time_str,AttrVal($hash->{NAME},"timerevent","")?1:0);
@@ -2699,7 +2690,7 @@ DOIF_SetTimer
if (!defined ($hash->{triggertime}{$next_time})) {
$hash->{triggertime}{$next_time}{hash}=$hash;
$hash->{triggertime}{$next_time}{localtime}=$next_time;
- InternalTimer($next_time, $func, \$hash->{triggertime}{$next_time}, 0);
+ InternalTimer($next_time, $func, \$hash->{triggertime}{$next_time}, 0);
}
return undef;
}
@@ -3048,7 +3039,7 @@ DOIF_Define($$$)
} else {
$hash->{MODEL}="Perl";
#$defs{$hash->{NAME}}{".AttrList"} = "disable:0,1 loglevel:0,1,2,3,4,5,6 startup state initialize notexist checkReadingEvent:1,0 addStateEvent:1,0 weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes;
- setDevAttrList($hash->{NAME},"disable:0,1 loglevel:0,1,2,3,4,5,6 startup state initialize notexist checkReadingEvent:1,0 addStateEvent:1,0 weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes);
+ setDevAttrList($hash->{NAME},"disable:0,1 loglevel:0,1,2,3,4,5,6 startup state initialize notexist checkReadingEvent:0,1 addStateEvent:1,0 weekdays setList:textField-long readingList DOIF_Readings:textField-long uiTable:textField-long ".$readingFnAttributes);
($msg,$err)=CmdDoIfPerl($hash,$cmd);
}
if ($err ne "") {
@@ -3338,7 +3329,7 @@ Kommt ein Device in mehreren Bedingungen vor, so wird immer nur ein Kommando aus
für das die dazugehörige Bedingung in der abgearbeiteten Reihenfolge wahr ist.
Das 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.
+Ein Ausführungszweig wird erst dann wieder ausgeführt, wenn zwischenzeitlich ein anderer Ausführungszweig ausgeführt wurde, also ein Statuswechsel des DOIF-Moduls stattgefunden hat.
Dieses Verhalten ist sinnvoll, um zu verhindern, dass zyklisch sendende Sensoren (Temperatur, Feuchtigkeit, Helligkeit, usw.) zu ständiger Wiederholung des selben Befehls oder Befehlsabfolge führen.
Das Verhalten des Moduls im FHEM-Modus kann durch diverse Attribute verändert werden. Im FHEM-Modus wird maximal nur ein Zweig pro Ereignis- oder Zeit-Trigger ausgeführt, es gibt nur einen Wait-Timer.
@@ -3380,6 +3371,7 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel
Zeitsteuerung mit Zeitintervallen
Indirekten Zeitangaben
Zeitsteuerung mit Zeitberechnung
+ Intervall-Timer
Kombination von Ereignis- und Zeitsteuerung mit logischen Abfragen
Zeitintervalle, Readings und Status ohne Trigger
Nutzung von Readings, Status oder Internals im Ausführungsteil
@@ -3393,7 +3385,7 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel
Begrenzung von Wiederholungen eines Kommandos
Ausführung eines Kommandos nach einer Wiederholung einer Bedingung
Löschen des Waittimers nach einer Wiederholung einer Bedingung
- Readingauswertung nur beim Event des jeweiligen Readings
+ Readingauswertung bei jedem Event des Devices
Eindeutige Statuserkennung
Triggerung durch selbst ausgelöste Events
Setzen der Timer mit Event
@@ -4016,7 +4008,7 @@ Einschalten am Freitag ausschalten am Montag:
Schalten mit Zeitfunktionen, hier: bei Sonnenaufgang und Sonnenuntergang:
-define di_light DOIF ([+{sunrise_rel(900,"06:00","08:00")}]) (set outdoorlight off) DOELSEIF ([+{sunset_rel(900,"17:00","21:00")}]) (set outdoorlight on)
+define di_light DOIF ([{sunrise(900,"06:00","08:00")}]) (set outdoorlight off) DOELSEIF ([{sunset(900,"17:00","21:00")}]) (set outdoorlight on)
Indirekten Zeitangaben back
@@ -4061,8 +4053,6 @@ Angabe eines Readings als Zeitangabe. Beispiel: Schalten anhand eines Twilight-R
define di_time DOIF ([[myTwilight:ss_weather]])(set lamp on)
-
-
Dynamische Änderung einer Zeitangabe.
Anwendungsbeispiel: Die Endzeit soll abhängig von der Beginnzeit mit Hilfe einer eigenen Perl-Funktion, hier: OffTime(), bestimmt werden. begin und end sind Dummys, wie oben definiert:
@@ -4115,6 +4105,27 @@ Ein Änderung des Dummys Fixtime z. B. durch "set Fixtime ...", führt zur sofor
Für die Zeitberechnung wird der Perlinterpreter benutzt, daher sind für die Berechnung der Zeit keine Grenzen gesetzt.
+
+Intervall-Timer back
+
+Syntax:
+
+[<begin>-<end>,<relative timer>]
+
+Innerhalb des definierten Zeitintervalls, triggert der definierte Timer. Außerhalb des Zeitintervall wird kein Timer gesetzt.
+
+Anwendungsbeispiel: Zwischen 08:00 und 22:00 Uhr soll eine Pumpe jede halbe Stunde für fünf Minuten eingeschaltet werden:
+
+define di_pump DOIF ([08:00-22:00,+:30])(set pump on-for-timer 300)
+attr di_pump do always
+
+Es wird um 08:00, 08:30, 09:00, ..., 21:30 Uhr die Anweisung ausgeführt. Um 22:00 wird das letzte Mal getriggert, das Zeitintervall ist zu diesem Zeitpunkt nicht mehr wahr.
+
+Es lassen sich ebenso indirekte Timer, Timer-Funktionen, Zeitberechnungen sowie Wochentage miteinander kombinieren.
+
+define di_rand_lamp DOIF ([{sunset()}-[end:state],+(rand(600)+900)|Sa So])(set lamp on-for-timer 300)
+attr di_rand_lamp do always
+
Kombination von Ereignis- und Zeitsteuerung mit logischen Abfragen back
@@ -4393,24 +4404,12 @@ Die Attribute wait und waitdel lassen sich für versch
attr di_cmd waitdel 0:2
-Readingauswertung nur beim Event des jeweiligen Readings back
+Readingauswertung bei jedem Event des Devices back
-Standardmäßig werden angegebene Readings ausgewertet, wenn irgendein 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.
+Bei Angaben der Art [<Device>:<Reading>] wird das Modul getriggert, wenn ein Ereignis zum angegebenen Device und Reading kommt. Soll das Modul, wie bei Statusangaben der Art [<Device>], auf alle Ereignisse des Devices reagieren, so muss das Attribut auf Null gesetzt werden.
-Beispiel:
-
-define di_lamp DOIF ([mytwilight:light] < 3) (set lamp on) DOELSEIF ([mytwilight:light] > 3) (set lamp off)
-attr di_lamp checkReadingEvent 1
-
-Bei der Angabe von indirekten Timern wird grundsätzlich intern checkReadingEvent benutzt:
-
-define di_lamp ([[mytwilight:ss_weather]]) (set lamp on)
-attr di_lamp do always
-
-Hier braucht das Attribut checkReadingEvent nicht explizit gesetzt werden.
-Die Zeit wird nur dann neu gesetzt, wenn sich tatsächlich das Reading ss_weather ändert.
+Bemerkung: In früheren Versionen des Moduls war checkReadingEvent 0 die Voreinstellung des Moduls. Da die aktuelle Voreinstellung des Moduls checkReadingEvent 1 ist, hat das Setzen von
+checkReadingEvent 1 keine weitere Funktion mehr.
Eindeutige Statuserkennung back
@@ -5155,6 +5154,9 @@ Hier passiert das nicht mehr, da die ursprünglichen Zustände cmd_1 und cmd_2 j
[(<Berechnung, gibt Zeit in Sekunden zurück, im Sinne von time>)][<begin>-<end>,<relativ timer>][?<devicename>], [?<devicename>:<readingname>], [?<devicename>:&<internalname>], [?<time specification>]attr <name> waitdel <timer_1_1>,<timer_1_2>,...:<timer_2_1>,<timer_2_2>,...:...attr <name> checkReadingEvent <0|ungleich Null>attr <name> checkReadingEvent <0|1>attr <name> selftrigger <wait|all>wait zugelassen für verzögerte Befehle, all zugelassen auch für nicht durch wait verzögerte Befehle; es ist nur eine Rekusion möglichattr <name> cmdState <Ersatz cmd_1_1>,...,<Ersatz cmd_1>|<Ersatz cmd_2_1>,...,<Ersatz cmd_2>|...attr <name> startup <FHEM-Befehle>|{<Perl-Befehle mit DOIF-Syntax>}attr <name> state <content>