From bd0800f2856eae3d3c8f035b1258b0634cbdd15c Mon Sep 17 00:00:00 2001
From: Damian <>
Date: Wed, 22 Mar 2017 15:48:02 +0000
Subject: [PATCH] 98_DOIF.pm: new attribute weekdays, Modul will be defined now
in spite of an incorrect timer specification; Error message will be stored in
timer reading
git-svn-id: https://svn.fhem.de/fhem/trunk@13770 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/98_DOIF.pm | 151 +++++++++++++++++++++++++++----------------
1 file changed, 97 insertions(+), 54 deletions(-)
diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index 207f4649f..987a66ffc 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -74,7 +74,7 @@ DOIF_Initialize($)
$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 repeatcmd waitsame waitdel cmdpause timerWithWait:1,0 notexist selftrigger:wait,all timerevent:1,0 checkReadingEvent:1,0 addStateEvent:1,0 checkall:event,timer,all setList:textField-long readingList ".$readingFnAttributes;
+ $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 ".$readingFnAttributes;
}
@@ -762,6 +762,18 @@ ParseCommandsDoIf($$$)
return("",$last_error);
}
+sub DOIF_weekdays($$)
+{
+ my ($hash,$weekdays)=@_;
+ my @days=SplitDoIf(',',AttrVal($hash->{NAME},"weekdays","So,Mo,Di,Mi,Do,Fr,Sa,WE,AT"));
+ for (my $i=0;$i<@days;$i++)
+ {
+ $weekdays =~ s/$days[$i]/$i/;
+ }
+ return($weekdays);
+}
+
+
sub
DOIF_CheckTimers($$$$)
{
@@ -842,8 +854,9 @@ DOIF_CheckTimers($$$$)
$hash->{timeCond}{$nr}=$condition;
$hash->{days}{$nr}=$days if ($days ne "");
if ($init_done) {
- $err=(DOIF_SetTimer($hash,"DOIF_TimerTrigger",$nr));
- return($hash->{time}{$nr},$err) if ($err);
+ 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);
}
@@ -871,6 +884,8 @@ DOIF_time
my $ret=0;
my ($hash,$b,$e,$wday,$hms,$days)=@_;
$days="" if (!defined ($days));
+ return 0 if (!defined $hash->{realtime}{$b});
+ return 0 if (!defined $hash->{realtime}{$e});
my $begin=$hash->{realtime}{$b};
my $end=$hash->{realtime}{$e};
my $err;
@@ -882,6 +897,7 @@ DOIF_time
readingsSingleUpdate ($hash, "error", $errmsg,0);
return 0;
}
+ $days=DOIF_weekdays($hash,$days);
my $we=DOIF_we($wday);
if ($end gt $begin) {
if ($hms ge $begin and $hms lt $end) {
@@ -916,6 +932,7 @@ DOIF_time_once
readingsSingleUpdate ($hash, "error", $errmsg,0);
return 0;
}
+ $days=DOIF_weekdays($hash,$days);
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));
@@ -1414,20 +1431,21 @@ DOIF_Notify($$)
}
}
+
+ return "" if (!$hash->{helper}{globalinit});
+ return "" if (defined $hash->{helper}{cur_cmd_nr});
+ return "" if (!$hash->{itimer}{all} and !$hash->{devices}{all} and !$hash->{state}{device} and !$hash->{regexp}{all});
+
if (($hash->{itimer}{all}) and $hash->{itimer}{all} =~ / $dev->{NAME} /) {
- for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
+ for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
if (CheckiTimerDoIf ($dev->{NAME},$hash->{time}{$j},$eventas)) {
- # { if (AttrVal($pn, "checkReadingEvent", 0) and CheckiTimerDoIf ($dev->{NAME},$hash->{time}{$j},$eventas)
- # or !AttrVal($pn, "checkReadingEvent", 0) and $hash->{time}{$j} =~ /\[$dev->{NAME}(\]|:.+\]|,.+\])/) {
DOIF_SetTimer($hash,"DOIF_TimerTrigger",$j);
}
}
}
+
return "" if (ReadingsVal($pn,"mode","") eq "disabled");
- return "" if (!$hash->{helper}{globalinit});
- return "" if (defined $hash->{helper}{cur_cmd_nr});
- return "" if (!$hash->{devices}{all} and !$hash->{state}{device} and !$hash->{regexp}{all});
-
+
if ((($hash->{devices}{all}) and $hash->{devices}{all} =~ / $dev->{NAME} /) or CheckRegexpDoIf($hash,$dev->{NAME},$eventa,-1)){
$hash->{helper}{cur_cmd_nr}="Trigger $dev->{NAME}" if (AttrVal($hash->{NAME},"selftrigger","") ne "all");
readingsSingleUpdate ($hash, "Device",$dev->{NAME},0);
@@ -1480,16 +1498,17 @@ DOIF_TimerTrigger ($)
my $pn = $hash->{NAME};
my $localtime=${$timer}->{localtime};
delete $hash->{triggertime}{$localtime};
+
my $ret;
my ($now, $microseconds) = gettimeofday();
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now);
$hash->{helper}{cur_cmd_nr}="timer $localtime" if (AttrVal($hash->{NAME},"selftrigger","") ne "all");
#$hash->{helper}{cur_cmd_nr}="timer $localtime";
for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
- if ($hash->{localtime}{$j} == $localtime) {
+ if (defined $hash->{localtime}{$j} and $hash->{localtime}{$j} == $localtime) {
if (defined ($hash->{interval}{$j})) {
if ($hash->{interval}{$j} != -1) {
- if ($hash->{realtime}{$j} eq $hash->{realtime}{$hash->{interval}{$j}}) {
+ if (defined $hash->{realtime}{$j} eq $hash->{realtime}{$hash->{interval}{$j}}) {
$hash->{timer}{$hash->{interval}{$j}}=0;
next;
}
@@ -1504,7 +1523,7 @@ DOIF_TimerTrigger ($)
$ret=DOIF_Trigger ($hash,"") if (ReadingsVal($pn,"mode","") ne "disabled");
for (my $j=0; $j<$hash->{helper}{last_timer};$j++) {
$hash->{timer}{$j}=0;
- if ($hash->{localtime}{$j} == $localtime) {
+ if (defined $hash->{localtime}{$j} and $hash->{localtime}{$j} == $localtime) {
if (!AttrVal($hash->{NAME},"disable","")) {
if (defined ($hash->{interval}{$j})) {
if ($hash->{interval}{$j} != -1) {
@@ -1665,7 +1684,22 @@ DOIF_SetTimer($$$)
my $timeStr=$hash->{time}{$nr};
my $cond=$hash->{timeCond}{$nr};
my $next_time;
-
+ if (defined ($hash->{localtime}{$nr})) {
+ my $old_lt=$hash->{localtime}{$nr};
+ my $found=0;
+ delete ($hash->{localtime}{$nr});
+ delete ($hash->{realtime}{$nr});
+ foreach my $lt (keys %{$hash->{localtime}}) {
+ if ($hash->{localtime}{$lt} == $old_lt) {
+ $found=1;
+ last;
+ }
+ }
+ if (!$found) {
+ RemoveInternalTimer(\$hash->{triggertime}{$old_lt});
+ delete ($hash->{triggertime}{$old_lt});
+ }
+ }
my ($second,$err, $rel)=DOIF_CalcTime($hash,$timeStr);
my $timernr=sprintf("timer_%02d_c%02d",($nr+1),($cond+1));
if ($err)
@@ -1673,7 +1707,7 @@ DOIF_SetTimer($$$)
readingsSingleUpdate ($hash,$timernr,"error: ".$err,AttrVal($hash->{NAME},"timerevent","")?1:0);
Log3 $hash->{NAME},4 , "$hash->{NAME} ".$timernr." error: ".$err;
#RemoveInternalTimer($timer);
- $hash->{realtime}{$nr}="00:00:00";
+ #$hash->{realtime}{$nr} = "00:00:00" if (!defined $hash->{realtime}{$nr});
return $err;
}
@@ -1705,35 +1739,16 @@ DOIF_SetTimer($$$)
}
}
}
- #if ($next_time < $now and $isdst_now == $isdst) {
- # readingsSingleUpdate ($hash,"timer_".($nr+1)."_c".($cond+1),"back to the past is not allowed",AttrVal($hash->{NAME},"timerevent","")?1:0);
- # return("timer_".($nr+1)."_c".($cond+1),"back to the past is 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,$timernr,$next_time_str,AttrVal($hash->{NAME},"timerevent","")?1:0);
$hash->{realtime}{$nr}=strftime("%H:%M:%S",localtime($next_time));
- if (defined ($hash->{localtime}{$nr})) {
- my $old_lt=$hash->{localtime}{$nr};
- my $found=0;
- delete ($hash->{localtime}{$nr});
- foreach my $lt (keys %{$hash->{localtime}}) {
- if ($hash->{localtime}{$lt} == $old_lt) {
- $found=1;
- last;
- }
- }
- if (!$found) {
- RemoveInternalTimer(\$hash->{triggertime}{$old_lt});
- delete ($hash->{triggertime}{$old_lt});
- }
- }
$hash->{localtime}{$nr}=$next_time;
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;
}
@@ -2026,6 +2041,8 @@ DOIF_Set($@)
} elsif ($arg eq "initialize" ) {
delete ($defs{$hash->{NAME}}{READINGS}{mode});
delete ($defs{$hash->{NAME}}{READINGS}{cmd_nr});
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd});
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_seqnr});
delete ($defs{$hash->{NAME}}{READINGS}{cmd_event});
readingsSingleUpdate($hash, "state","initialize",1);
} elsif ($arg eq "enable" ) {
@@ -2180,12 +2197,21 @@ Dieses Verhalten ist sinnvoll, um zu verhindern, dass zyklisch sendende Sensoren
Einfache Anwendungsbeispiele:
define di_rc_tv DOIF ([remotecontol:"on"]) (set tv on) DOELSE (set tv off)
define di_clock_radio DOIF ([06:30|8] or [08:30|7]) (set radio on) DOELSEIF ([08:00|8] or [09:30|7]) (set radio off)
define di_rc_tv DOIF ([remotecontol:"on"]) (set tv on) DOELSE (set tv off)
define di_lamp DOIF ([06:00-09:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)
define di_clock_radio DOIF ([06:30|Mo Di Mi] or [08:30|Do Fr Sa So]) (set radio on) DOELSEIF ([08:00|Mo Di Mi] or [09:30|Do Fr Sa So]) (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
Attribute
+ addStateEvent
+ checkall
+ checkReadingEvent
cmdpause
cmdState
disable
@@ -2254,19 +2283,16 @@ Kombinierte Ereignis- und Zeitsteuerung: define di_lamp DOIF ([06:00-09:00
notexist
repeatcmd
repeatsame
+ selftrigger
+ readingList
+ setList
state
+ timerevent
timerWithWait
wait
waitdel
waitsame
- checkReadingEvent
- addStateEvent
- selftrigger
- timerevent
- checkall
- setList
- readingList
-
+ weekdays
readingFnAttributes
@@ -2558,22 +2584,39 @@ attr di_gong do always
[<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)
[<time>|So Mo Di Mi Do Fr Sa WE AT]
WE entspricht der Ziffer 7 und AT der Ziffer 8weekdays
können beliebige Wochentagbezeichnungen definiert werden. Die Syntax lautet:weekdays <Bezeichnung für Sonntag>,<Bezeichnung für Montag>,...,<Bezeichnung für Wochenende>,<Bezeichnung für Arbeitstage>
di_mydoif attr weekdays Son,Mon,Die,Mit,Don,Fre,Sam,Wochenende,Arbeitstag
define di_radio DOIF ([06:30|Mo We] or [08:30|WE]) (set radio on) DOELSEIF ([07:30|Mo We] or [09:30|WE]) (set radio off)
attr di_radio weekdays Su,Mo,Tu,We,Th,Fr,Sa,WE,WD
define dummy Wochentag
-set Wochentag 135
+define dummy myweekday
+set myweekday monday wednesday thursday weekend
-define di_radio DOIF ([06:30|[Wochentag]]) (set radio on) DOELSEIF ([07:30|[Wochentag]]) (set radio off)
+define di_radio DOIF ([06:30|[myweekday]]) (set radio on) DOELSEIF ([07:30|[myweekday]]) (set radio off)
+
+attr di_radio weekdays sunday,monday,thuesday,wednesday,thursday,friday,saturday,weekend,workdays
checkall event
Es werden alle Bedingungen geprüft, wenn ein Event-Trigger auslöst.checkall timer
Es werden alle Bedingungen geprüft, wenn ein Timer-Trigger auslöst.