diff --git a/fhem/FHEM/98_WeekdayTimer.pm b/fhem/FHEM/98_WeekdayTimer.pm index b9ae902fd..df00858a9 100644 --- a/fhem/FHEM/98_WeekdayTimer.pm +++ b/fhem/FHEM/98_WeekdayTimer.pm @@ -33,7 +33,6 @@ use warnings; use Time::Local qw( timelocal_nocheck ); use Data::Dumper; $Data::Dumper::Sortkeys = 1; -use Scalar::Util qw( weaken ); use FHEM::Core::Timer::Register qw(:ALL); use GPUtils qw(GP_Import); @@ -854,10 +853,8 @@ sub _SetTimer { #$modules{WeekdayTimer}{timerInThePastHash} = $tipHash; #$tipHash = $hash->{helper}{timerInThePastHash} = $tipHash; $hash->{helper}{timerInThePastHash} = $tipHash; - resetRegIntTimer('delayed', time + 5 + AttrVal($name,'WDT_sendDelay',0), \&WeekdayTimer_delayedTimerInPast, $tipHash, 0); - return; } @@ -892,6 +889,18 @@ sub WeekdayTimer_delayedTimerInPast { return; } +sub _checkTimerReset { + my $hash = shift // return; + my $idx = shift // return; + + return if $hash->{profil}{$idx}{EPOCH} <= time; + return if + !isAnActiveTimer ($hash, $hash->{profil}{$idx}{TAGE}, $hash->{profil}{$idx}{PARA}, $hash->{profil}{$idx}{WE_Override}) + && !isAnActiveTimer ($hash, $hash->{helper}{WEDAYS}{0} ? [7]:[8], $hash->{profil}{$idx}{PARA}, $hash->{profil}{$idx}{WE_Override}); + resetRegIntTimer($idx, $hash->{profil}{$idx}{EPOCH}, \&WeekdayTimer_Update, $hash, 0); + return; +} + ################################################################################ sub _searchAktNext { my ($hash, $now) = @_; @@ -985,7 +994,8 @@ sub WeekdayTimer_Update { $activeTimer = isAnActiveTimer ($hash, $dieGanzeWoche, $newParam, $overrulewday); $activeTimerState = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday); Log3( $hash, 4, "[$name] Update - past timer activated" ); - resetRegIntTimer("$idx", $timToSwitch, \&WeekdayTimer_Update, $hash, 0) if $timToSwitch > $now && ($activeTimerState || $activeTimer ); + deleteSingleRegIntTimer($idx, $hash, 1); + setRegIntTimer($idx, $timToSwitch, \&WeekdayTimer_Update, $hash, 0) if $timToSwitch > $now && ($activeTimerState || $activeTimer ); } else { $activeTimer = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday); $activeTimerState = $activeTimer; @@ -1065,34 +1075,34 @@ sub checkIfDeviceIsHeatingType { ################################################################################ sub checkDelayedExecution { - my ($hash, $event, $time) = @_; + my ($hash, $event, $idx) = @_; my $name = $hash->{NAME}; my %specials = ( '%WEEKDAYTIMER' => $hash->{NAME}, '%NAME' => $hash->{DEVICE}, '%EVENT' => $event, - '%TIME' => $hash->{profil}{$time}{TIME}, + '%TIME' => $hash->{profil}{$idx}{TIME}, '$WEEKDAYTIMER' => $hash->{NAME}, '$NAME' => $hash->{DEVICE}, '$EVENT' => $event, - '$TIME' => $hash->{profil}{$time}{TIME}, + '$TIME' => $hash->{profil}{$idx}{TIME}, ); my $verzoegerteAusfuehrungCond = AttrVal($hash->{NAME}, 'delayedExecutionCond', 0); my $nextRetry = time + 55 + int(rand(10)); - my $epoch = $hash->{profil}{$time}{EPOCH}; + my $epoch = $hash->{profil}{$idx}{EPOCH}; if (!$epoch) { #prevent FHEM crashing when profile is somehow damaged or incomlete, forum #109164 my $actual_wp_reading = ReadingsVal($name,'weekprofiles','none'); - Log3( $hash, 0, "[$name] profile $actual_wp_reading, item $time seems to be somehow damaged or incomplete!" ); + Log3( $hash, 0, "[$name] profile $actual_wp_reading, item $idx seems to be somehow damaged or incomplete!" ); $epoch = int(time) - 10*MINUTESECONDS; readingsSingleUpdate( $hash, 'corrupt_wp_count', ReadingsNum($name,'corrupt_wp_count', 0) + 1, 1 ); } my $delay = int(time) - $epoch; my $nextDelay = int($delay/60.+1.5)*60; # round to multiple of 60sec $nextRetry = $epoch + $nextDelay + AttrVal($name,'WDT_sendDelay',0); - Log3( $hash, 4, "[$name] time=".$hash->{profil}{$time}{TIME}."/$epoch delay=$delay, nextDelay=$nextDelay, nextRetry=$nextRetry" ); + Log3( $hash, 4, "[$name] time=".$hash->{profil}{$idx}{TIME}."/$epoch delay=$delay, nextDelay=$nextDelay, nextRetry=$nextRetry" ); for my $key (keys %specials) { my $val = $specials{$key}; @@ -1110,19 +1120,15 @@ sub checkDelayedExecution { if ( !defined $hash->{VERZOEGRUNG} ) { Log3( $hash, 3, "[$name] switch of $hash->{DEVICE} delayed - delayedExecutionCond: '$verzoegerteAusfuehrungCond' is TRUE" ); } - if ( defined $hash->{VERZOEGRUNG_IDX} && $hash->{VERZOEGRUNG_IDX}!=$time) { + if ( defined $hash->{VERZOEGRUNG_IDX} && $hash->{VERZOEGRUNG_IDX}!=$idx) { #Prüfen, ob der nächste Timer überhaupt für den aktuellen Tag relevant ist! - Log3( $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skipped by new timer at $hash->{profil}{$time}{TIME}, delayedExecutionCond returned $verzoegerteAusfuehrung" ); + Log3( $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skipped by new timer at $hash->{profil}{$idx}{TIME}, delayedExecutionCond returned $verzoegerteAusfuehrung" ); deleteSingleRegIntTimer($hash->{VERZOEGRUNG_IDX},$hash); - #xxxxx add logic for last timer of day - resetRegIntTimer($time, $hash->{profil}{$time}{EPOCH}, \&WeekdayTimer_Update, $hash, 0) - if $hash->{profil}{$time}{EPOCH} > time - && (isAnActiveTimer ($hash, $hash->{profil}{$time}{TAGE}, $hash->{profil}{$time}{PARA}, $hash->{profil}{$time}{WE_Override}) - || isAnActiveTimer ($hash, $hash->{helper}{WEDAYS}{0} ? [7]:[8], $hash->{profil}{$time}{PARA}, $hash->{profil}{$time}{WE_Override}) ); + _checkTimerReset($hash, $idx); } - $hash->{VERZOEGRUNG_IDX} = $time; - resetRegIntTimer("$time", $nextRetry, \&WeekdayTimer_Update, $hash, 0); + $hash->{VERZOEGRUNG_IDX} = $idx; + resetRegIntTimer($idx, $nextRetry, \&WeekdayTimer_Update, $hash, 0); $hash->{VERZOEGRUNG} = 1; return $verzoegerteAusfuehrung; } @@ -1173,17 +1179,14 @@ sub checkDelayedExecution { if ( !defined $hash->{VERZOEGRUNG} ) { Log3( $hash, 3, "[$name] switch of $hash->{DEVICE} delayed - sensor '$fk' Reading/Attribute '$reading' is '$windowStatus'" ); } - if ( defined $hash->{VERZOEGRUNG_IDX} && $hash->{VERZOEGRUNG_IDX} != $time ) { - Log3( $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skipped by new timer at $hash->{profil}{$time}{TIME} while window contact returned open state"); + if ( defined $hash->{VERZOEGRUNG_IDX} && $hash->{VERZOEGRUNG_IDX} != $idx ) { + Log3( $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skipped by new timer at $hash->{profil}{$idx}{TIME} while window contact returned open state"); deleteSingleRegIntTimer($hash->{VERZOEGRUNG_IDX},$hash); #xxxxx add logic for last timer of day - resetRegIntTimer($time, $hash->{profil}{$time}{EPOCH}, \&WeekdayTimer_Update, $hash, 0) - if $hash->{profil}{$time}{EPOCH} > time - && (isAnActiveTimer ($hash, $hash->{profil}{$time}{TAGE}, $hash->{profil}{$time}{PARA}, $hash->{profil}{$time}{WE_Override}) - || isAnActiveTimer ($hash, $hash->{helper}{WEDAYS}{0} ? [7]:[8], $hash->{profil}{$time}{PARA}, $hash->{profil}{$time}{WE_Override}) ); + _checkTimerReset($hash, $idx); } - $hash->{VERZOEGRUNG_IDX} = $time; - resetRegIntTimer("$time", $nextRetry, \&WeekdayTimer_Update, $hash, 0); + $hash->{VERZOEGRUNG_IDX} = $idx; + resetRegIntTimer($idx, $nextRetry, \&WeekdayTimer_Update, $hash, 0); $hash->{VERZOEGRUNG} = 1; return 1 } @@ -1193,6 +1196,7 @@ sub checkDelayedExecution { } delete $hash->{VERZOEGRUNG}; delete $hash->{VERZOEGRUNG_IDX} if defined $hash->{VERZOEGRUNG_IDX}; + _checkTimerReset($hash, $idx); return 0; } diff --git a/fhem/lib/FHEM/Core/Timer/Register.pm b/fhem/lib/FHEM/Core/Timer/Register.pm index 52a25798b..ae9b2daed 100644 --- a/fhem/lib/FHEM/Core/Timer/Register.pm +++ b/fhem/lib/FHEM/Core/Timer/Register.pm @@ -5,7 +5,7 @@ use warnings; use Carp qw( carp ); use Scalar::Util qw( weaken ); -use version; our $VERSION = qv('1.0.0'); +use version; our $VERSION = qv('1.0.1'); use Exporter ('import');use GPUtils qw(GP_Import); @@ -70,7 +70,16 @@ sub resetRegIntTimer { my $hash = shift // carp q[No hash reference specified] && return; my $initFlag = shift // 0; - deleteSingleRegIntTimer( $modifier, $hash ); + my $timerName = "$hash->{NAME}_$modifier"; + my $fnHash = $hash->{TIMER}{$timerName}; + + if ( defined $fnHash ) { + ::Log3( $hash, '5', "[$hash->{NAME}] resetting Timer: $timerName" ); + ::RemoveInternalTimer($fnHash); + ::InternalTimer( $time, $callback, $fnHash, $initFlag ); + return $fnHash; + } + return setRegIntTimer ( $modifier, $time, $callback, $hash, $initFlag ); }