diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index c080eadbf..366add2f2 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -22,19 +22,53 @@ package main;
use strict;
use warnings;
+sub DOIF_cmd ($$$$);
+sub
+DOIF_delTimer($)
+{
+ my ($hash) = @_;
+ RemoveInternalTimer($hash);
+ my $max_timer=keys %{$hash->{timerfunc}};
+ for (my $i=0; $i<$max_timer;$i++)
+ {
+ RemoveInternalTimer ($hash->{timerfunc}{$i});
+ }
+ return undef;
+}
-##########################
+sub
+DOIF_delAll($)
+{
+ my ($hash) = @_;
+ delete ($hash->{helper});
+ delete ($hash->{condition});
+ delete ($hash->{do});
+ delete ($hash->{devices});
+ delete ($hash->{time});
+ delete ($hash->{timer});
+ delete ($hash->{timers});
+ delete ($hash->{itimer});
+ delete ($hash->{timeCond});
+ delete ($hash->{realtime});
+ delete ($hash->{days});
+ delete ($hash->{readings});
+ delete ($hash->{internals});
+ delete ($hash->{trigger});
+ delete ($defs{$hash->{NAME}}{READINGS});
+}
+
+#########################
sub
DOIF_Initialize($)
{
my ($hash) = @_;
$hash->{DefFn} = "DOIF_Define";
- #$hash->{SetFn} = "DOIF_Set";
+ $hash->{SetFn} = "DOIF_Set";
$hash->{UndefFn} = "DOIF_Undef";
$hash->{AttrFn} = "DOIF_Attr";
$hash->{NotifyFn} = "DOIF_Notify";
- $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always,resetwait cmdState state initialize repeatsame waitsame waitdel cmdpause ".$readingFnAttributes;
+ $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always,resetwait cmdState state initialize repeatsame waitsame waitdel cmdpause timerWithWait ".$readingFnAttributes;
}
@@ -460,18 +494,26 @@ DOIF_CheckTimers($$$$$)
$hash->{timerfunc}{$nr}=\${$timerarray}[$nr];
}
if ($i == 2) {
- $block='DOIF_time($hash->{realtime}{'.$nrs[0].'},$hash->{realtime}{'.$nrs[1].'},$wday,$hms,"'.$days.'")';
+ $block='DOIF_time($hash,$hash->{realtime}{'.$nrs[0].'},$hash->{realtime}{'.$nrs[1].'},$wday,$hms,"'.$days.'")';
} else {
- $block='DOIF_time_once($hash->{timer}{'.$nrs[0].'},$wday,"'.$days.'")';
+ $block='DOIF_time_once($hash,$hash->{timer}{'.$nrs[0].'},$wday,"'.$days.'")';
}
return ($block,"");
}
sub
-DOIF_time($$$$$)
+DOIF_time($$$$$$)
{
my $ret=0;
- my ($begin,$end,$wday,$hms,$days)=@_;
+ my ($hash,$begin,$end,$wday,$hms,$days)=@_;
+ my $err;
+ ($days,$err)=ReplaceAllReadingsDoIf($hash,$days,-1,1);
+ if ($err) {
+ my $errmsg="error in days: $err";
+ Log3 ($hash->{NAME},2 , "$hash->{NAME}: $errmsg");
+ readingsSingleUpdate ($hash, "error", $errmsg,1);
+ return 0;
+ }
my $we=DOIF_we($wday);
if ($end gt $begin) {
if ($hms ge $begin and $hms lt $end) {
@@ -493,10 +535,17 @@ DOIF_time($$$$$)
}
sub
-DOIF_time_once($$$)
+DOIF_time_once($$$$)
{
- my $ret;
- my ($flag,$wday,$days)=@_;
+ my ($hash,$flag,$wday,$days)=@_;
+ my $err;
+ ($days,$err)=ReplaceAllReadingsDoIf($hash,$days,-1,1);
+ if ($err) {
+ my $errmsg="error in days: $err";
+ Log3 ($hash->{NAME},2 , "$hash->{NAME}: $errmsg");
+ readingsSingleUpdate ($hash, "error", $errmsg,1);
+ return 0;
+ }
my $we=DOIF_we($wday);
if ($flag) {
return 1 if ($days eq "" or $days =~ /$wday/ or ($days =~ /7/ and $we) or ($days =~ /8/ and !$we));
@@ -506,9 +555,9 @@ DOIF_time_once($$$)
############################
sub
-DOIF_SetState($$$$)
+DOIF_SetState($$$$$)
{
- my ($hash,$nr,$event,$last_error)=@_;
+ my ($hash,$nr,$subnr,$event,$last_error)=@_;
my $pn=$hash->{NAME};
my $cmdNr="";
my $cmd="";
@@ -517,17 +566,28 @@ DOIF_SetState($$$$)
my $state=AttrVal($hash->{NAME},"state","");
my @cmdState=split(/\|/,$attr);
$nr=ReadingsVal($pn,"cmd_nr",0)-1 if (!$event);
+
if ($nr!=-1) {
$cmdNr=$nr+1;
- if ($attr) {
- $cmd=$cmdState[$nr] if (defined ($cmdState[$nr]));
+ if (defined $hash->{do}{$nr}{$subnr+1}) {
+ $cmd="cmd_".$cmdNr."_".($subnr+1);
} else {
- $cmd="cmd_$cmdNr";
+ if ($attr) {
+ $cmd=$cmdState[$nr] if (defined ($cmdState[$nr]));
+ } else {
+ $cmd="cmd_$cmdNr";
+ }
}
}
readingsBeginUpdate ($hash);
if ($event) {
readingsBulkUpdate($hash,"cmd_nr",$cmdNr);
+ if (defined $hash->{do}{$nr}{1}) {
+ readingsBulkUpdate($hash,"cmd_seqnr",$subnr+1)
+
+ } else {
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_seqnr});
+ }
readingsBulkUpdate($hash,"cmd_event",$event);
if ($last_error) {
readingsBulkUpdate($hash,"error",$last_error);
@@ -535,7 +595,8 @@ DOIF_SetState($$$$)
delete ($defs{$hash->{NAME}}{READINGS}{error});
}
}
- if ($state) {
+
+ if ($state and !defined $hash->{do}{$nr}{$subnr+1}) {
my $stateblock='\['.$pn.'\]';
$state =~ s/$stateblock/$cmd/g;
($state,$err)=ReplaceAllReadingsDoIf($hash,$state,-1,1);
@@ -580,7 +641,7 @@ DOIF_CheckCond($$)
my $reading;
my $internal;
my $we=DOIF_we($wday);
-
+
$month++;
$year+=1900;
if (defined ($hash->{readings}{$condition})) {
@@ -604,9 +665,9 @@ DOIF_CheckCond($$)
}
sub
-DOIF_cmd ($$$)
+DOIF_cmd ($$$$)
{
- my ($hash,$nr,$event)=@_;
+ my ($hash,$nr,$subnr,$event)=@_;
my $pn = $hash->{NAME};
my $ret;
my $cmd;
@@ -617,46 +678,56 @@ DOIF_cmd ($$$)
my @cmdpause=split(/:/,AttrVal($pn,"cmdpause",""));
my @waitsame=split(/:/,AttrVal($pn,"waitsame",""));
my ($seconds, $microseconds) = gettimeofday();
- if ($cmdpause[$nr]) {
+ if ($cmdpause[$nr] and $subnr==0) {
return undef if ($seconds - time_str2num(ReadingsTimestamp($pn, "state", "1970-01-01 01:00:00")) < $cmdpause[$nr]);
}
if (AttrVal($pn,"repeatsame","")) {
- if ($repeatsame[$nr]) {
- $repeatnr=ReadingsVal($pn,"cmd_count",0);
- if ($last_cmd == $nr) {
- if ($repeatnr < $repeatsame[$nr]) {
- $repeatnr++;
+ if ($subnr == 0) {
+ if ($repeatsame[$nr]) {
+ $repeatnr=ReadingsVal($pn,"cmd_count",0);
+ if ($last_cmd == $nr) {
+ if ($repeatnr < $repeatsame[$nr]) {
+ $repeatnr++;
+ } else {
+ return undef;
+ }
} else {
- return undef;
+ $repeatnr=1;
}
+ readingsSingleUpdate ($hash, "cmd_count", $repeatnr,1);
} else {
- $repeatnr=1;
+ return undef if ($last_cmd == $nr and $subnr==0 and (AttrVal($pn,"do","") ne "always" and AttrVal($pn,"do","") ne "resetwait"));
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_count});
}
- readingsSingleUpdate ($hash, "cmd_count", $repeatnr,1);
- } else {
- return undef if ($last_cmd == $nr and (AttrVal($pn,"do","") ne "always" and AttrVal($pn,"do","") ne "resetwait"));
- delete ($defs{$hash->{NAME}}{READINGS}{cmd_count});
}
}
if (AttrVal($pn,"waitsame","")) {
- if ($waitsame[$nr]) {
- my $cmd_nr="cmd_".($nr+1);
- if (ReadingsVal($pn,"waitsame","") eq $cmd_nr) {
- if ($seconds - time_str2num(ReadingsTimestamp($pn, "waitsame", "1970-01-01 01:00:00")) > $waitsame[$nr]) {
+ if ($subnr == 0) {
+ if ($waitsame[$nr]) {
+ my $cmd_nr="cmd_".($nr+1);
+ if (ReadingsVal($pn,"waitsame","") eq $cmd_nr) {
+ if ($seconds - time_str2num(ReadingsTimestamp($pn, "waitsame", "1970-01-01 01:00:00")) > $waitsame[$nr]) {
+ readingsSingleUpdate ($hash, "waitsame", $cmd_nr,1);
+ return undef;
+ }
+ } else {
readingsSingleUpdate ($hash, "waitsame", $cmd_nr,1);
return undef;
}
- } else {
- readingsSingleUpdate ($hash, "waitsame", $cmd_nr,1);
- return undef;
- }
- }
- delete ($defs{$hash->{NAME}}{READINGS}{waitsame});
+ }
+ delete ($defs{$hash->{NAME}}{READINGS}{waitsame});
+ }
}
- if ($hash->{do}{$nr}) {
- ($cmd,$err)=ParseCommandsDoIf($hash,$hash->{do}{$nr},1);
+ if ($hash->{do}{$nr}{$subnr}) {
+ ($cmd,$err)=ParseCommandsDoIf($hash,$hash->{do}{$nr}{$subnr},1);
+ }
+ DOIF_SetState ($hash,$nr,$subnr,$event,$err);
+ if (defined $hash->{do}{$nr}{++$subnr}) {
+ my $last_cond=ReadingsVal($pn,"cmd_nr",0)-1;
+ if (DOIF_SetSleepTimer($hash,$last_cond,$nr,$subnr,$event,-1)) {
+ DOIF_cmd ($hash,$nr,$subnr,$event);
+ }
}
- DOIF_SetState ($hash,$nr,$event,$err);
return undef;
}
@@ -689,8 +760,8 @@ DOIF_Trigger ($$$)
return undef;
}
if ($ret) {
- if (DOIF_SetSleepTimer($hash,$last_cond,$i,$device,$timerNr)) {
- DOIF_cmd ($hash,$i,$event);
+ if (DOIF_SetSleepTimer($hash,$last_cond,$i,0,$device,$timerNr)) {
+ DOIF_cmd ($hash,$i,0,$event);
return 1;
} else {
return undef;
@@ -701,9 +772,9 @@ DOIF_Trigger ($$$)
}
}
if ($doelse) { #DOELSE
- if (defined ($hash->{do}{$max_cond}) or ($max_cond == 1 and !(AttrVal($pn,"do","") or AttrVal($pn,"repeatsame","")))) { #DOELSE
- if (DOIF_SetSleepTimer($hash,$last_cond,$max_cond,$device,$timerNr)) {
- DOIF_cmd ($hash,$max_cond,$event) ;
+ if (defined ($hash->{do}{$max_cond}{0}) or ($max_cond == 1 and !(AttrVal($pn,"do","") or AttrVal($pn,"repeatsame","")))) { #DOELSE
+ if (DOIF_SetSleepTimer($hash,$last_cond,$max_cond,0,$device,$timerNr)) {
+ DOIF_cmd ($hash,$max_cond,0,$event) ;
return 1;
}
}
@@ -726,13 +797,13 @@ DOIF_Notify($$)
if ($dev->{NAME} eq "global" and ((EventDoIf("global","global",deviceEvents($dev, AttrVal("global", "addStateEvent", 0)),"INITIALIZED")) or EventDoIf("global","global",deviceEvents($dev, AttrVal("global", "addStateEvent", 0)),"REREADCFG")))
{
+ $hash->{helper}{globalinit}=1;
if ($hash->{helper}{last_timer} > 0){
for (my $j=0; $j<$hash->{helper}{last_timer};$j++)
{
DOIF_SetTimer("DOIF_TimerTrigger",$hash->{timerfunc}{$j});
}
}
- # return undef;
}
if (($hash->{itimer}{all}) and $hash->{itimer}{all} =~ / $dev->{NAME} /) {
@@ -744,9 +815,15 @@ DOIF_Notify($$)
}
}
- return "" if (!$hash->{devices}{all} and !$hash->{state}{device}) ;
-
+ return "" if (!$hash->{devices}{all} and !$hash->{state}{device});
+ return "" if (!$hash->{helper}{globalinit});
+ return "" if (ReadingsVal($pn,"mode","") eq "disabled");
+
if (($hash->{devices}{all}) and $hash->{devices}{all} =~ / $dev->{NAME} /) {
+ readingsSingleUpdate ($hash, "Device",$dev->{NAME},0);
+ #my $events = deviceEvents($dev, AttrVal($dev->{NAME}, "addStateEvent", 0));
+ #readingsSingleUpdate ($hash, "Event","@{$events}",0);
+
if ($hash->{readings}{all}) {
foreach my $item (split(/ /,$hash->{readings}{all})) {
($device,$reading)=(split(":",$item));
@@ -776,7 +853,7 @@ DOIF_Notify($$)
$ret=DOIF_Trigger($hash,$dev->{NAME},-1);
}
if (($hash->{state}{device}) and $hash->{state}{device} =~ / $dev->{NAME} / and !$ret) {
- DOIF_SetState($hash,"","","");
+ DOIF_SetState($hash,"",0,"","");
}
return undef;
}
@@ -787,8 +864,10 @@ DOIF_TimerTrigger ($)
my ($timer)=@_;
my $nr=${$timer}->{nr};
my $hash=${$timer}->{hash};
+ my $pn = $hash->{NAME};
my $ret;
- if (!AttrVal($hash->{NAME},"disable","")) {
+# if (!AttrVal($hash->{NAME},"disable","")) {
+ if (ReadingsVal($pn,"mode","") ne "disabled") {
$hash->{timer}{$nr}=1;
$ret=DOIF_Trigger ($hash,"",$nr);
$hash->{timer}{$nr}=0;
@@ -821,7 +900,7 @@ DOIF_DetTime($)
$align=$2;
} elsif ($timeStr =~ m/^:([0-5][0-9])$/) {
$align=$1;
- } elsif ($timeStr =~ m/^([0-9]+)$/) {
+ } elsif ($timeStr =~ m/^(\-?([0-9]+))$/) {
$s=$1;
} else {
if ($timeStr =~ m/^\$hms$/) {
@@ -973,53 +1052,85 @@ DOIF_SetTimer($$)
$next_time-=3600 if ($isdst == 1);
}
}
- 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,"timer_".($nr+1)."_c".($cond+1),$next_time_str,0);
- $hash->{realtime}{$nr}=strftime("%H:%M:%S",localtime($next_time));
- RemoveInternalTimer($timer);
- InternalTimer($next_time, $func, $timer, 0);
+ if ($next_time < $now) {
+ readingsSingleUpdate ($hash,"timer_".($nr+1)."_c".($cond+1),"back to the past ist not allowed",0);
+ return("timer_".($nr+1)."_c".($cond+1),"back to the past ist not allowed");
+ } else {
+ 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,"timer_".($nr+1)."_c".($cond+1),$next_time_str,0);
+ $hash->{realtime}{$nr}=strftime("%H:%M:%S",localtime($next_time));
+ RemoveInternalTimer($timer);
+ InternalTimer($next_time, $func, $timer, 0);
+ }
return undef;
}
sub
-DOIF_SetSleepTimer($$$$$)
+DOIF_SetSleepTimer($$$$$$)
{
- my ($hash,$last_cond,$nr,$device,$timerNr)=@_;
+ my ($hash,$last_cond,$nr,$subnr,$device,$timerNr)=@_;
my $pn = $hash->{NAME};
my $sleeptimer=$hash->{helper}{sleeptimer};
- return 1 if ($timerNr == -2); #Sleeptrigger
my @waitdel=split(/:/,AttrVal($pn,"waitdel",""));
- if ($sleeptimer != -1 and (($sleeptimer != $nr or AttrVal($pn,"do","") eq "resetwait") or ($sleeptimer == $nr and $waitdel[$sleeptimer]))) {
+ my @waitdelsubnr=split(/,/,defined $waitdel[$sleeptimer] ? $waitdel[$sleeptimer] : "");
+ my $err;
+
+ if ($sleeptimer != -1 and (($sleeptimer != $nr or AttrVal($pn,"do","") eq "resetwait") or ($sleeptimer == $nr and $waitdelsubnr[$subnr]))) {
RemoveInternalTimer($hash);
#delete ($defs{$hash->{NAME}}{READINGS}{wait_timer});
readingsSingleUpdate ($hash, "wait_timer", "no timer",1);
$hash->{helper}{sleeptimer}=-1;
- return 0 if ($sleeptimer == $nr and $waitdel[$sleeptimer]);
+ $subnr=$hash->{helper}{sleepsubtimer} if ($hash->{helper}{sleepsubtimer}!=-1);
+ return 0 if ($sleeptimer == $nr and $waitdelsubnr[$subnr]);
}
- if ($timerNr >= 0) {#Timer
+ if ($timerNr >= 0 and !AttrVal($pn,"timerWithWait","")) {#Timer
if ($last_cond != $nr or AttrVal($pn,"do","") eq "always" or AttrVal($pn,"repeatsame","")) {
return 1;
} else {
return 0;
}
}
- if ($hash->{helper}{sleeptimer} == -1 and ($last_cond != $nr or AttrVal($pn,"do","") eq "always" or AttrVal($pn,"do","") eq "resetwait" or AttrVal($pn,"repeatsame",""))) {
+
+ if ($hash->{helper}{sleeptimer} == -1 and ($last_cond != $nr or $subnr > 0 or AttrVal($pn,"do","") eq "always" or AttrVal($pn,"do","") eq "resetwait" or AttrVal($pn,"repeatsame",""))) {
my @sleeptimer=split(/:/,AttrVal($pn,"wait",""));
my $sleeptime=0;
- if ($waitdel[$nr]) {
- $sleeptime = $waitdel[$nr];
- } elsif ($sleeptimer[$nr]) {
- $sleeptime=$sleeptimer[$nr]
+ if ($waitdelsubnr[$subnr]) {
+ $sleeptime = $waitdelsubnr[$subnr];
+ } else {
+ my @sleepsubtimer=split(/,/,defined $sleeptimer[$nr]? $sleeptimer[$nr]: "");
+ if ($sleepsubtimer[$subnr]) {
+ $sleeptime=$sleepsubtimer[$subnr];
+ }
}
+ ($sleeptime,$err)=ReplaceAllReadingsDoIf($hash,$sleeptime,-1,1);
+ if ($err) {
+ Log3 $pn,2 , "$pn: error in wait: $err" if ($err);
+ $sleeptime=0;
+ } else {
+ my $ret = eval $sleeptime;
+ if ($@) {
+ Log3 ($pn,2 , "$pn: error in wait: $sleeptimer: $@");
+ $sleeptime=0;
+ } else {
+ $sleeptime=$ret;
+ }
+ }
if ($sleeptime) {
my ($seconds, $microseconds) = gettimeofday();
my $next_time = $seconds+$sleeptime;
$hash->{helper}{sleeptimer}=$nr;
+ $hash->{helper}{sleepsubtimer}=$subnr;
+ $device="timer_".($timerNr+1) if ($timerNr >= 0);
$hash->{helper}{sleepdevice}=$device;
my $cmd_nr=$nr+1;
- readingsSingleUpdate ($hash,"wait_timer",strftime("%d.%m.%Y %H:%M:%S cmd_$cmd_nr $device",localtime($next_time)),1);
+ if (defined $hash->{do}{$nr}{1}) {
+ my $cmd_subnr=$subnr+1;
+ readingsSingleUpdate ($hash,"wait_timer",strftime("%d.%m.%Y %H:%M:%S cmd_$cmd_nr"."_$cmd_subnr $device",localtime($next_time)),1);
+ } else {
+ readingsSingleUpdate ($hash,"wait_timer",strftime("%d.%m.%Y %H:%M:%S cmd_$cmd_nr $device",localtime($next_time)),1);
+ }
InternalTimer($next_time, "DOIF_SleepTrigger",$hash, 0);
return 0;
} else {
@@ -1034,11 +1145,17 @@ sub
DOIF_SleepTrigger ($)
{
my ($hash)=@_;
+ my $sleeptimer=$hash->{helper}{sleeptimer};
+ my $sleepsubtimer=$hash->{helper}{sleepsubtimer};
$hash->{helper}{sleeptimer}=-1;
+ $hash->{helper}{sleepsubtimer}=-1;
+ my $pn = $hash->{NAME};
readingsSingleUpdate ($hash, "wait_timer", "no timer",1);
- if (!AttrVal($hash->{NAME},"disable","")) {
- DOIF_Trigger($hash,$hash->{helper}{sleepdevice},-2);
+# if (!AttrVal($hash->{NAME},"disable","")) {
+ if (ReadingsVal($pn,"mode","") ne "disable") {
+ DOIF_cmd ($hash,$sleeptimer,$sleepsubtimer,$hash->{helper}{sleepdevice});
}
+
return undef;
}
@@ -1057,41 +1174,30 @@ CmdDoIf($$)
my $eval="";
my $beginning;
my $i=0;
+ my $j=0;
my $last_do;
-
+
if (!$tail) {
$tail="";
} else {
- $tail =~ s/\n//g;
+ $tail =~ s/(##.*\n)|(##.*$)|\n//g;;
}
- if (defined $hash->{helper}) #def modify
+
+# if (defined $hash->{helper}) #def modify
+ if ($init_done)
{
- RemoveInternalTimer($hash);
- my $max_timer=keys %{$hash->{timerfunc}};
- for (my $i=0; $i<$max_timer;$i++)
- {
- RemoveInternalTimer ($hash->{timerfunc}{$i});
- }
- delete ($hash->{helper});
- delete ($hash->{condition});
- delete ($hash->{do});
- delete ($hash->{devices});
- delete ($hash->{time});
- delete ($hash->{timer});
- delete ($hash->{timers});
- delete ($hash->{itimer});
- delete ($hash->{timeCond});
- delete ($hash->{realtime});
- delete ($hash->{days});
- delete ($hash->{readings});
- delete ($hash->{internals});
- delete ($hash->{trigger});
- delete ($defs{$hash->{NAME}}{READINGS});
+ DOIF_delTimer($hash);
+ DOIF_delAll ($hash);
readingsSingleUpdate ($hash,"state","initialized",1);
+ $hash->{helper}{globalinit}=1;
}
#$hash->{STATE} = 'initialized';
$hash->{helper}{last_timer}=0;
$hash->{helper}{sleeptimer}=-1;
+# if ($init_done) {
+# $hash->{helper}{globalinit}=1;
+# }
+
while ($tail ne "") {
return($tail, "no left bracket of condition") if ($tail !~ /^ *\(/);
#condition
@@ -1103,14 +1209,16 @@ CmdDoIf($$)
$hash->{condition}{$i}=$cond;
#DOIF
$if_cmd_ori="";
- if ($tail =~ /^\s*\(/) {
+ $j=0;
+ while ($tail =~ /^\s*\(/) {
($beginning,$if_cmd_ori,$err,$tail)=GetBlockDoIf($tail,'[\(\)]');
return ($if_cmd_ori,$err) if ($err);
($if_cmd,$err)=ParseCommandsDoIf($hash,$if_cmd_ori,0);
return ($if_cmd,$err) if ($err);
#return ($tail,"no commands") if ($if_cmd eq "");
+ $hash->{do}{$i}{$j++}=$if_cmd_ori;
}
- $hash->{do}{$i}=$if_cmd_ori;
+ $hash->{do}{$i}{0}=$if_cmd_ori if ($j==0); #do without brackets
$last_do=$i;
if (length($tail)) {
$tail =~ /^\s*DOELSEIF/g;
@@ -1134,13 +1242,15 @@ CmdDoIf($$)
} else {
return ($tail,"expected DOELSE");
}
- if ($tail =~ /^\s*\(/) {
+ $j=0;
+ while ($tail =~ /^\s*\(/) {
($beginning,$else_cmd_ori,$err,$tail)=GetBlockDoIf($tail,'[\(\)]');
return ($else_cmd_ori,$err) if ($err);
($else_cmd,$err)=ParseCommandsDoIf($hash,$else_cmd_ori,0);
return ($else_cmd,$err) if ($err);
+ $hash->{do}{$last_do+1}{$j++}=$else_cmd_ori;
}
- $hash->{do}{$last_do+1}=$else_cmd_ori;
+ $hash->{do}{$last_do+1}{0}=$else_cmd_ori if ($j==0); #doelse without brackets
}
return("","")
}
@@ -1150,6 +1260,7 @@ DOIF_Define($$$)
{
my ($hash, $def) = @_;
my ($name, $type, $cmd) = split(/[\s]+/, $def, 3);
+ return undef if (AttrVal($hash->{NAME},"disable",""));
my ($msg,$err)=CmdDoIf($hash,$cmd);
if ($err ne "") {
$msg=$cmd if (!$msg);
@@ -1167,19 +1278,19 @@ DOIF_Attr(@)
{
my @a = @_;
my $hash = $defs{$a[1]};
- if($a[0] eq "set" && $a[2] eq "disable")
+ my $ret="";
+ if (($a[0] eq "set" and $a[2] eq "disable" and ($a[3] eq "0")) or (($a[0] eq "del" and $a[2] eq "disable")))
{
- if($a[3] eq "0") {
- readingsSingleUpdate ($hash,"state","initialized",1);
- delete ($defs{$hash->{NAME}}{READINGS}{cmd_nr});
- delete ($defs{$hash->{NAME}}{READINGS}{cmd_event});
- } elsif($a[3] eq "1") {
- readingsSingleUpdate ($hash,"state","disabled",1);
+ my $cmd = $defs{$hash->{NAME}}{DEF};
+ my ($msg,$err)=CmdDoIf($hash,$cmd);
+ if ($err ne "") {
+ $msg=$cmd if (!$msg);
+ return ("$err: $msg");
}
- } elsif($a[0] eq "del" && $a[2] eq "disable") {
- readingsSingleUpdate ($hash,"state","initialized",1);
- delete ($defs{$hash->{NAME}}{READINGS}{cmd_nr});
- delete ($defs{$hash->{NAME}}{READINGS}{cmd_event});
+ } 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);
} elsif($a[0] eq "set" && $a[2] eq "state") {
delete ($hash->{state}{device});
my ($block,$err)=ReplaceAllReadingsDoIf($hash,$a[3],-2,0);
@@ -1205,12 +1316,7 @@ DOIF_Undef
{
my ($hash, $name) = @_;
$hash->{DELETED} = 1;
- RemoveInternalTimer($hash);
- my $max_timer=keys %{$hash->{timerfunc}};
- for (my $i=0; $i<$max_timer;$i++)
- {
- RemoveInternalTimer ($hash->{timerfunc}{$i});
- }
+ DOIF_delTimer($hash);
return undef;
}
@@ -1221,7 +1327,27 @@ DOIF_Set($@)
{
my ($hash, @a) = @_;
my $pn = $hash->{NAME};
+ my $arg = $a[1];
+ my $value = (defined $a[2]) ? $a[2] : "";
my $ret="";
+ if ($arg eq "disable" or $arg eq "initialize") {
+ if (AttrVal($hash->{NAME},"disable","")) {
+ return ("modul ist deactivated by disable attribut, delete disable attribut first");
+ }
+ }
+ if ($arg eq "disable") {
+ readingsBeginUpdate ($hash);
+ readingsBulkUpdate($hash, "state", "disabled");
+ readingsBulkUpdate($hash, "mode", "disabled");
+ readingsEndUpdate ($hash, 1);
+ } elsif ($arg eq "initialize" ) {
+ delete ($defs{$hash->{NAME}}{READINGS}{mode});
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_nr});
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_event});
+ readingsSingleUpdate($hash, "state","initialize",1);
+ } else {
+ return "$pn: unknown argument $a[1], choose one of disable initialize"
+ }
return $ret;
}
@@ -1296,13 +1422,16 @@ Syntax:
define <name> DOIF (<Bedingung>) (<Befehle>) DOELSEIF (<Bedingung>) (<Befehle>) DOELSEIF ... DOELSE (<Befehle>)define di_rc_tv DOIF ([remotecontol] eq "on") (set tv on) DOELSE (set tv off)define di_rc_tv DOIF ([remotecontol] eq "on") (set tv on) DOELSE (set tv off)define di_clock_radio DOIF ([06:30]) (set radio on) DOELSEIF ([08:00]) (set radio off)define di_clock_radio DOIF ([06:30]) (set radio on) DOELSEIF ([08:00]) (set radio off)define di_lamp DOIF ([06:00-09:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)define di_lamp DOIF ([06:00-09:00
+ Verzögerungsangaben mit Zurückstellung sind möglich (watchdog-Funktionalität)
+ Der Ausführungsteil kann jeweils ausgelassen werden. Damit kann das Modul für reine Statusanzeige genutzt werden
define di_Modul DOIF ([Switch1] eq "on" and [Switch2] eq "on") ## wenn Schalter 1 und Schalter 2 on ist
+
+(set lamp on) ## wird Lampe eingeschaltet
+
+DOELSE ## im sonst-Fall, also wenn einer der Schalter off ist
+
+(set lamp off) ## wird die Lampe ausgeschaltet
+...(set lamp on)...(set lamp on)... (set lamp1 on, set lamp2 off)[<time>|012345678] 0-8 entspricht: 0-Sonntag, 1-Montag, ... bis 6-Samstag sowie 7 für Wochende und Feiertage (entspricht $we) und 8 für Arbeitstage (entspricht !$we)[<time>|012345678] 0-8 entspricht: 0-Sonntag, 1-Montag, ... bis 6-Samstag sowie 7 für Wochenende und Feiertage (entspricht $we) und 8 für Arbeitstage (entspricht !$we)define di_radio DOIF ([06:30|8] or [08:30|7]) (set radio on) DOELSEIF ([07:30|8] or [09:30|7]) (set radio off)define dummy Wochentag
+set Wochentag 135
+
+define di_radio DOIF ([06:30|[Wochentag]] (set radio on) DOELSEIF ([07:30|[Wochentag]]) (set radio off)[<begin>-<end>],
@@ -1504,7 +1660,7 @@ Einschalten am Freitag ausschalten am Montag:define di_light DOIF ([{sunrise_abs()}-{sunset(1800,"17:00","21:00")}])(set outdoorlight off) DOELSE (set outdoorlight on)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)attr <Modulname> wait <Sekunden für das erste Kommando>:<Sekunden für das zweite Kommando>:...
+attr <Modulname> wait <Sekunden für Befehlsfolge des ersten DO-Falls>:<Sekunden für Befehlsfolge des zweiten DO-Falls>:...
attr <Modulname> wait 1:[Verzoegerung]:rand(600)(set lamp1 on, set lamp2 on), soll vor dem Schalten von lamp2 eine Verzögerung von einer Sekunde stattfinden.
+Die Befehlsfolge muss zunächst mit Hilfe von Klammerblöcke aufgespaltet werden: (set lamp1 on)(set lamp2 on).
+Nun kann mit dem wait-Attribut nicht nur für den Beginn der Sequenz, sondern für jeden Klammerblock eine Verzögerung, getrennt mit Komma, definieren werden,
+ hier also: wait 0,1. Damit wird lamp1 sofort, lamp2 nach einer Sekunden geschaltet.DOIF (Bedingung1)
+(set ...) #erster Befehl der ersten Sequenz soll um eine Sekunde verzögert werden
+(set ...) #zweiter Befehl der ersten Sequenz soll um 2 Sekunden verzögert werden
+DOELSE (Bedingung2)
+(set ...) #erster Befehl der zweiten Sequenz soll um 3 Sekunden verzögert werden
+(set ...) #zweiter Befehl der zweiten Sequenz soll um 0,5 Sekunden verzögert werden
+
+attr <Modulname> wait 1,2:3,0.5timerwithWait auf Timer ausgeweitet werden.define di_rand_sunset([{sunset()}])(set lamp on)
+attr di_rand_sunset wait rand(1200)
+attr di_rand_sunset timerWithWait
+attr di_rand_sunset do alwaysset <Modulname> 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 <Modulname> initialize wird ein mit set <Modulname> disable deaktiviertes Modul wieder aktiviert.
+Das Kommando set <Modulname> 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.define switch_d dummy
+define di_on_for_timer ([detector:?motion])
+ (set light on)
+ (set light off)
+attr di_on_for_timer do resetwait
+attr di_on_for_timer wait 0,30
-define di_switch DOIF ([detector:?motion]) (set switch_d on, set switch_d off)
-attr di_switch do always
-
-define di_light DOIF ([switch_d] eq "on") (set light on) DOELSE (set light off)
-attr di_light wait 0:300