2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-07 16:59:18 +00:00

98_WeekdayTimer: renew delayed timer when window is closed

git-svn-id: https://svn.fhem.de/fhem/trunk@24513 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Beta-User 2021-05-26 03:53:53 +00:00
parent f8b4cc54c7
commit ed3e21a268
2 changed files with 42 additions and 29 deletions

View File

@ -33,7 +33,6 @@ use warnings;
use Time::Local qw( timelocal_nocheck ); use Time::Local qw( timelocal_nocheck );
use Data::Dumper; use Data::Dumper;
$Data::Dumper::Sortkeys = 1; $Data::Dumper::Sortkeys = 1;
use Scalar::Util qw( weaken );
use FHEM::Core::Timer::Register qw(:ALL); use FHEM::Core::Timer::Register qw(:ALL);
use GPUtils qw(GP_Import); use GPUtils qw(GP_Import);
@ -854,10 +853,8 @@ sub _SetTimer {
#$modules{WeekdayTimer}{timerInThePastHash} = $tipHash; #$modules{WeekdayTimer}{timerInThePastHash} = $tipHash;
#$tipHash = $hash->{helper}{timerInThePastHash} = $tipHash; #$tipHash = $hash->{helper}{timerInThePastHash} = $tipHash;
$hash->{helper}{timerInThePastHash} = $tipHash; $hash->{helper}{timerInThePastHash} = $tipHash;
resetRegIntTimer('delayed', time + 5 + AttrVal($name,'WDT_sendDelay',0), \&WeekdayTimer_delayedTimerInPast, $tipHash, 0); resetRegIntTimer('delayed', time + 5 + AttrVal($name,'WDT_sendDelay',0), \&WeekdayTimer_delayedTimerInPast, $tipHash, 0);
return; return;
} }
@ -892,6 +889,18 @@ sub WeekdayTimer_delayedTimerInPast {
return; 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 { sub _searchAktNext {
my ($hash, $now) = @_; my ($hash, $now) = @_;
@ -985,7 +994,8 @@ sub WeekdayTimer_Update {
$activeTimer = isAnActiveTimer ($hash, $dieGanzeWoche, $newParam, $overrulewday); $activeTimer = isAnActiveTimer ($hash, $dieGanzeWoche, $newParam, $overrulewday);
$activeTimerState = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday); $activeTimerState = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday);
Log3( $hash, 4, "[$name] Update - past timer activated" ); 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 { } else {
$activeTimer = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday); $activeTimer = isAnActiveTimer ($hash, $tage, $newParam, $overrulewday);
$activeTimerState = $activeTimer; $activeTimerState = $activeTimer;
@ -1065,34 +1075,34 @@ sub checkIfDeviceIsHeatingType {
################################################################################ ################################################################################
sub checkDelayedExecution { sub checkDelayedExecution {
my ($hash, $event, $time) = @_; my ($hash, $event, $idx) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %specials = ( my %specials = (
'%WEEKDAYTIMER' => $hash->{NAME}, '%WEEKDAYTIMER' => $hash->{NAME},
'%NAME' => $hash->{DEVICE}, '%NAME' => $hash->{DEVICE},
'%EVENT' => $event, '%EVENT' => $event,
'%TIME' => $hash->{profil}{$time}{TIME}, '%TIME' => $hash->{profil}{$idx}{TIME},
'$WEEKDAYTIMER' => $hash->{NAME}, '$WEEKDAYTIMER' => $hash->{NAME},
'$NAME' => $hash->{DEVICE}, '$NAME' => $hash->{DEVICE},
'$EVENT' => $event, '$EVENT' => $event,
'$TIME' => $hash->{profil}{$time}{TIME}, '$TIME' => $hash->{profil}{$idx}{TIME},
); );
my $verzoegerteAusfuehrungCond = AttrVal($hash->{NAME}, 'delayedExecutionCond', 0); my $verzoegerteAusfuehrungCond = AttrVal($hash->{NAME}, 'delayedExecutionCond', 0);
my $nextRetry = time + 55 + int(rand(10)); 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 if (!$epoch) { #prevent FHEM crashing when profile is somehow damaged or incomlete, forum #109164
my $actual_wp_reading = ReadingsVal($name,'weekprofiles','none'); 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; $epoch = int(time) - 10*MINUTESECONDS;
readingsSingleUpdate( $hash, 'corrupt_wp_count', ReadingsNum($name,'corrupt_wp_count', 0) + 1, 1 ); readingsSingleUpdate( $hash, 'corrupt_wp_count', ReadingsNum($name,'corrupt_wp_count', 0) + 1, 1 );
} }
my $delay = int(time) - $epoch; my $delay = int(time) - $epoch;
my $nextDelay = int($delay/60.+1.5)*60; # round to multiple of 60sec my $nextDelay = int($delay/60.+1.5)*60; # round to multiple of 60sec
$nextRetry = $epoch + $nextDelay + AttrVal($name,'WDT_sendDelay',0); $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) { for my $key (keys %specials) {
my $val = $specials{$key}; my $val = $specials{$key};
@ -1110,19 +1120,15 @@ sub checkDelayedExecution {
if ( !defined $hash->{VERZOEGRUNG} ) { if ( !defined $hash->{VERZOEGRUNG} ) {
Log3( $hash, 3, "[$name] switch of $hash->{DEVICE} delayed - delayedExecutionCond: '$verzoegerteAusfuehrungCond' is TRUE" ); 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! #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); deleteSingleRegIntTimer($hash->{VERZOEGRUNG_IDX},$hash);
#xxxxx add logic for last timer of day _checkTimerReset($hash, $idx);
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}) );
} }
$hash->{VERZOEGRUNG_IDX} = $time; $hash->{VERZOEGRUNG_IDX} = $idx;
resetRegIntTimer("$time", $nextRetry, \&WeekdayTimer_Update, $hash, 0); resetRegIntTimer($idx, $nextRetry, \&WeekdayTimer_Update, $hash, 0);
$hash->{VERZOEGRUNG} = 1; $hash->{VERZOEGRUNG} = 1;
return $verzoegerteAusfuehrung; return $verzoegerteAusfuehrung;
} }
@ -1173,17 +1179,14 @@ sub checkDelayedExecution {
if ( !defined $hash->{VERZOEGRUNG} ) { if ( !defined $hash->{VERZOEGRUNG} ) {
Log3( $hash, 3, "[$name] switch of $hash->{DEVICE} delayed - sensor '$fk' Reading/Attribute '$reading' is '$windowStatus'" ); 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 ) { 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}{$time}{TIME} while window contact returned open state"); 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); deleteSingleRegIntTimer($hash->{VERZOEGRUNG_IDX},$hash);
#xxxxx add logic for last timer of day #xxxxx add logic for last timer of day
resetRegIntTimer($time, $hash->{profil}{$time}{EPOCH}, \&WeekdayTimer_Update, $hash, 0) _checkTimerReset($hash, $idx);
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}) );
} }
$hash->{VERZOEGRUNG_IDX} = $time; $hash->{VERZOEGRUNG_IDX} = $idx;
resetRegIntTimer("$time", $nextRetry, \&WeekdayTimer_Update, $hash, 0); resetRegIntTimer($idx, $nextRetry, \&WeekdayTimer_Update, $hash, 0);
$hash->{VERZOEGRUNG} = 1; $hash->{VERZOEGRUNG} = 1;
return 1 return 1
} }
@ -1193,6 +1196,7 @@ sub checkDelayedExecution {
} }
delete $hash->{VERZOEGRUNG}; delete $hash->{VERZOEGRUNG};
delete $hash->{VERZOEGRUNG_IDX} if defined $hash->{VERZOEGRUNG_IDX}; delete $hash->{VERZOEGRUNG_IDX} if defined $hash->{VERZOEGRUNG_IDX};
_checkTimerReset($hash, $idx);
return 0; return 0;
} }

View File

@ -5,7 +5,7 @@ use warnings;
use Carp qw( carp ); use Carp qw( carp );
use Scalar::Util qw( weaken ); 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); 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 $hash = shift // carp q[No hash reference specified] && return;
my $initFlag = shift // 0; 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 ); return setRegIntTimer ( $modifier, $time, $callback, $hash, $initFlag );
} }