98_WeekdayTimer.pm: add HMCCUDEV window contact type; change handling and initial configuration

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@20421 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Beta-User 2019-10-28 20:07:02 +00:00
parent 8674a13c28
commit 5d6761a5a0

View File

@ -186,6 +186,25 @@ sub WeekdayTimer_Define($$) {
my $language = WeekdayTimer_Language ($hash, \@a); my $language = WeekdayTimer_Language ($hash, \@a);
$hash->{NAME} = $name;
$hash->{DEVICE} = $device;
InternalTimer(time(), "WeekdayTimer_Start",$hash,0);
return undef;
}
sub WeekdayTimer_Start($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my @a = split("[ \t]+", $hash->{DEF});
#my @a = split("[ \t]+", $def);
#my $type = shift @a;
my $device = shift @a;
my $language = WeekdayTimer_Language ($hash, \@a);
my $idx = 0; my $idx = 0;
$hash->{dayNumber} = {map {$_ => $idx++} @{$hash->{shortDays}{$language}}}; $hash->{dayNumber} = {map {$_ => $idx++} @{$hash->{shortDays}{$language}}};
$hash->{helper}{daysRegExp} = '(' . join ("|", @{$hash->{shortDays}{$language}}) . ")"; $hash->{helper}{daysRegExp} = '(' . join ("|", @{$hash->{shortDays}{$language}}) . ")";
@ -196,9 +215,6 @@ sub WeekdayTimer_Define($$) {
WeekdayTimer_GlobalDaylistSpec ($hash, \@a); WeekdayTimer_GlobalDaylistSpec ($hash, \@a);
$hash->{NAME} = $name;
$hash->{DEVICE} = $device;
my @switchingtimes = WeekdayTimer_gatherSwitchingTimes ($hash, \@a); my @switchingtimes = WeekdayTimer_gatherSwitchingTimes ($hash, \@a);
my $conditionOrCommand = join (" ", @a); my $conditionOrCommand = join (" ", @a);
@ -229,9 +245,10 @@ sub WeekdayTimer_Define($$) {
$attr{$name}{commandTemplate} = $attr{$name}{commandTemplate} =
'set $NAME '. WeekdayTimer_isHeizung($hash) .' $EVENT' if (!defined $attr{$name}{commandTemplate}); 'set $NAME '. WeekdayTimer_isHeizung($hash) .' $EVENT' if (!defined $attr{$name}{commandTemplate});
InternalTimer(time(), "$hash->{TYPE}_SetTimer", $hash, 0); WeekdayTimer_SetTimerOfDay({ HASH => $hash});
#WeekdayTimer_SetTimer($hash);
WeekdayTimer_SetTimerForMidnightUpdate( { HASH => $hash} ); #WeekdayTimer_SetTimerForMidnightUpdate( { HASH => $hash} );
return undef; return undef;
} }
@ -243,9 +260,9 @@ sub WeekdayTimer_Profile($) {
my %longDays = %{$hash->{longDays}}; my %longDays = %{$hash->{longDays}};
delete $hash->{profil}; delete $hash->{profil};
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time());
my $now = time(); my $now = time();
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
# ---- Zeitpunkte den Tagen zuordnen ----------------------------------- # ---- Zeitpunkte den Tagen zuordnen -----------------------------------
my $idx = 0; my $idx = 0;
foreach my $st (@{$hash->{SWITCHINGTIMES}}) { foreach my $st (@{$hash->{SWITCHINGTIMES}}) {
@ -255,16 +272,12 @@ sub WeekdayTimer_Profile($) {
foreach my $d (@{$tage}) { foreach my $d (@{$tage}) {
my @listeDerTage = ($d); my @listeDerTage = ($d);
push (@listeDerTage, WeekdayTimer_getListeDerTage($d, $time)) if ($d>=7); push (@listeDerTage, WeekdayTimer_getListeDerTage($hash, $d, $time)) if ($d>=7);
map { my $day = $_; map { my $day = $_;
my $dayOfEchteZeit = $day; my $dayOfEchteZeit = $day;
unless (AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b,|| $day > 6 ) {
$dayOfEchteZeit = ($wday==0||$wday==6) ? 1 : $wday if ($day==8); # ggf. Montag $wday ~~ [0, 6]
$dayOfEchteZeit = ($wday>=1&&$wday<=5) ? 6 : $wday if ($day==7); # ggf. Samstag $wday ~~ [1..5] $dayOfEchteZeit = ($wday>=1&&$wday<=5) ? 6 : $wday if ($day==7); # ggf. Samstag $wday ~~ [1..5]
} else { $dayOfEchteZeit = ($wday==0||$wday==6) ? 1 : $wday if ($day==8); # ggf. Montag $wday ~~ [0, 6]
$dayOfEchteZeit = $wday;
}
my $echtZeit = WeekdayTimer_EchteZeit($hash, $dayOfEchteZeit, $time); my $echtZeit = WeekdayTimer_EchteZeit($hash, $dayOfEchteZeit, $time);
$hash->{profile} {$day}{$echtZeit} = $parameter; $hash->{profile} {$day}{$echtZeit} = $parameter;
$hash->{profile_IDX}{$day}{$echtZeit} = $idx; $hash->{profile_IDX}{$day}{$echtZeit} = $idx;
@ -302,9 +315,8 @@ sub WeekdayTimer_Profile($) {
delete $hash->{profile}; delete $hash->{profile};
} }
################################################################################ ################################################################################
sub WeekdayTimer_getListeDerTage($$) { sub WeekdayTimer_getListeDerTage($$$) {
my ($d, $time) = @_; my ($hash, $d, $time) = @_;
my %hdays=(); my %hdays=();
unless (AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b,) { unless (AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b,) {
@hdays{(0, 6)} = undef if ($d==7); # sa,so ( $we) @hdays{(0, 6)} = undef if ($d==7); # sa,so ( $we)
@ -312,41 +324,12 @@ sub WeekdayTimer_getListeDerTage($$) {
} else { } else {
@hdays{(0..6)} = undef if ($d==8); # mo-fr (!$we) @hdays{(0..6)} = undef if ($d==8); # mo-fr (!$we)
} }
my $wday; my ($sec,$min,$hour,$mday,$mon,$year,$nowWday,$yday,$isdst) = localtime(time());
my $now = time();
my ($sec,$min,$hour,$mday,$mon,$year,$nowWday,$yday,$isdst) = localtime($now);
my @realativeWdays = (0..6);
for (my $i=0;$i<=6;$i++) { for (my $i=0;$i<=6;$i++) {
my $relativeDay = $i - $nowWday;
my $relativeDay = $i-$nowWday; $relativeDay = $relativeDay + 7 if $relativeDay < 0 ;
#Log 3, "relativeDay------------>$relativeDay"; if ($hash->{helper}{WEDAYS}{$relativeDay}) {
my ($stunde, $minute, $sekunde) = split (":",$time); $hdays{$i} = undef if ($d==7);#||AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b,); # $we Tag aufnehmen
my $echteZeit = WeekdayTimer_zeitErmitteln ($now, $stunde, $minute, $sekunde, $relativeDay);
#Log 3, "echteZeit---$i---->>>$relativeDay<<<----->".FmtDateTime($echteZeit);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($echteZeit);
my $noWeekEnd = 0;
my $ergebnis = 'none';
if ($wday==$nowWday ){
$ergebnis = "is_true" if IsWe();
} elsif ( $wday==$nowWday+1) {
$ergebnis = "is_true" if IsWe("tomorrow");
} else {
foreach my $h2we (split(',', AttrVal('global', 'holiday2we', ''))) {
if($h2we && ( $ergebnis eq 'none' || $h2we eq "noWeekEnd" ) && InternalVal($h2we, 'TYPE', '') eq "holiday" && !$noWeekEnd) {
$ergebnis = CommandGet(undef,$h2we . ' ' . sprintf("%02d-%02d",$mon+1,$mday));
if ($ergebnis ne 'none' && $h2we eq "noWeekEnd") {
$ergebnis = 'none';
$noWeekEnd = 1;
}
}
}
}
if ($ergebnis ne 'none') {
#Log 3, "ergebnis-------$i----->$ergebnis";
$hdays{$i} = undef if ($d==7||AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b,); # $we Tag aufnehmen
delete $hdays{$i} if ($d==8); # !$we Tag herausnehmen delete $hdays{$i} if ($d==8); # !$we Tag herausnehmen
} }
} }
@ -607,6 +590,45 @@ sub WeekdayTimer_SetTimerOfDay($) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time()); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());
my $secSinceMidnight = 3600*$hour + 60*$min + $sec; my $secSinceMidnight = 3600*$hour + 60*$min + $sec;
my %wedays =();
my $iswe = IsWe();
$wedays{(0)} = $iswe if $iswe;
$iswe = IsWe("tomorrow");
$wedays{(1)} = $iswe if $iswe;
for (my $i=2;$i<=6;$i++) {
my $noWeekEnd = 0;
my $ergebnis = 'none';
my $izeit = time() + DAYSECONDS * $i;
my ($isec,$imin,$ihour,$imday,$imon,$iyear,$iwday,$iyday,$iisdst) = localtime($izeit);
foreach my $h2we (split(',', AttrVal('global', 'holiday2we', ''))) {
if($h2we && ( $ergebnis eq 'none' || $h2we eq "noWeekEnd" ) && InternalVal($h2we, 'TYPE', '') eq "holiday" && !$noWeekEnd) {
$ergebnis = CommandGet(undef,$h2we . ' ' . sprintf("%02d-%02d",$imon+1,$imday));
if ($ergebnis ne 'none' && $h2we eq "noWeekEnd") {
$ergebnis = 'none';
$noWeekEnd = 1;
}
}
}
if ($ergebnis ne 'none') {
$wedays{$i} = $ergebnis ;
} else {
if (AttrVal('global', 'holiday2we', '') =~ m,\bweekEnd\b, && ($iwday == 0 || $iwday == 6)) {
delete $wedays{$i};
} elsif ( $iwday == 0 || $iwday == 6) {
$wedays{$i} = 1 ;
} else {
delete $wedays{$i};
}
}
}
$hash->{helper}{WEDAYS} = \%wedays;
$hash->{SETTIMERATMIDNIGHT} = $myHash->{SETTIMERATMIDNIGHT}; $hash->{SETTIMERATMIDNIGHT} = $myHash->{SETTIMERATMIDNIGHT};
WeekdayTimer_DeleteTimer($hash); WeekdayTimer_DeleteTimer($hash);
WeekdayTimer_Profile ($hash); WeekdayTimer_Profile ($hash);
@ -713,10 +735,12 @@ sub WeekdayTimer_delayedTimerInPast($) {
return if (!defined($hash)); return if (!defined($hash));
my $tim = time(); my $tim = time();
my $tipIpHash = $modules{WeekdayTimer}{timerInThePast}; my $tipIpHash = $modules{WeekdayTimer}{timerInThePast};
####To be deactivated for new routine, might be wrong...
foreach my $device ( keys %$tipIpHash ) { foreach my $device ( keys %$tipIpHash ) {
foreach my $time ( sort keys %{$tipIpHash->{$device}} ) { foreach my $time ( sort keys %{$tipIpHash->{$device}} ) {
Log3 $hash, 4, "$device ".FmtDateTime($time)." ".($tim-$time)."s "; Log3 $hash, 4, "$device ".FmtDateTime($time)." ".($tim-$time)."s ";
foreach my $para ( @{$tipIpHash->{$device}{$time}} ) { foreach my $para ( @{$tipIpHash->{$device}{$time}} ) {
@ -726,6 +750,12 @@ sub WeekdayTimer_delayedTimerInPast($) {
} }
} }
} }
############# end deactivation
#### new
#### end new
delete $modules{WeekdayTimer}{timerInThePast}; delete $modules{WeekdayTimer}{timerInThePast};
delete $modules{WeekdayTimer}{timerInThePastHash} delete $modules{WeekdayTimer}{timerInThePastHash}
} }
@ -759,12 +789,25 @@ sub WeekdayTimer_searchAktNext($$) {
$nextTime = WeekdayTimer_zeitErmitteln ($now, $stunde, $minute, $sekunde, $relativeDay); $nextTime = WeekdayTimer_zeitErmitteln ($now, $stunde, $minute, $sekunde, $relativeDay);
$nextPara = $hash->{helper}{SWITCHINGTIME}{$relWday}{$time}; $nextPara = $hash->{helper}{SWITCHINGTIME}{$relWday}{$time};
$nextIdx = $hash->{profile_IDX}{$relWday}{$time}; #$nextIdx = $hash->{helper}{SWITCHINGTIME}{$relWday}{$time};
$nextTag = $relWday; $nextIdx = $hash->{profile_IDX}{$relWday}{$time};
$nextTag = $relWday;
#Log3 $hash, 3, $shortDays{$language}[$nextTag]." ".FmtDateTime($nextTime)." ".$nextPara." ".$nextIdx; #Log3 $hash, 3, $shortDays{$language}[$nextTag]." ".FmtDateTime($nextTime)." ".$nextPara." ".$nextIdx;
my $ignore = 0;
if ($nextTime >= $now) { my $wend = 0;
my $tage = $hash->{profil}{$nextIdx}{TAGE}[0];
if ($wday==$relWday) {
$wend = $hash->{helper}{WEDAYS}{0};
#$wend = IsWe();
$ignore = (($tage == 7 && !$wend ) || ($tage == 8 && $wend ));
} elsif ( $wday==$relWday+1) {
$wend = $hash->{helper}{WEDAYS}{1};
#$wend = IsWe("tomorrow");
$ignore = (($tage == 7 && !$wend ) || ($tage == 8 && $wend ));
}
if (!$ignore && $nextTime >= $now ) {
#if ($nextTime >= $now ) {
#Log3 $hash, 3, "oldIdx------------->$oldIdx"; #Log3 $hash, 3, "oldIdx------------->$oldIdx";
#Log3 $hash, 3, "oldTime------------>".FmtDateTime($oldTime); #Log3 $hash, 3, "oldTime------------>".FmtDateTime($oldTime);
#Log3 $hash, 3, "oldPara------------>$oldPara"; #Log3 $hash, 3, "oldPara------------>$oldPara";
@ -797,7 +840,6 @@ sub WeekdayTimer_Update($) {
# Schaltparameter ermitteln # Schaltparameter ermitteln
my $tage = $hash->{profil}{$idx}{TAGE}; my $tage = $hash->{profil}{$idx}{TAGE};
my $time = $hash->{profil}{$idx}{TIME}; my $time = $hash->{profil}{$idx}{TIME};
#my $newParam = WeekdayTimer_evalAndcleanupParam($hash,$time,$hash->{profil}{$idx}{PARA}, $isHeating );
my $newParam = $hash->{profil}{$idx}{PARA}; my $newParam = $hash->{profil}{$idx}{PARA};
#Log3 $hash, 3, "[$name] $idx ". $time . " " . $newParam . " " . join("",@$tage); #Log3 $hash, 3, "[$name] $idx ". $time . " " . $newParam . " " . join("",@$tage);
@ -808,9 +850,13 @@ sub WeekdayTimer_Update($) {
return; return;
} }
my $dieGanzeWoche = [7,8]; my $dieGanzeWoche = $hash->{helper}{WEDAYS}{0} ? [7]:[8];
#my $dieGanzeWoche = IsWe() ? [7]:[8] ; ## Test, Benennung ist dann irreführend...
#my $dieGanzeWoche = [7,8];
my ($activeTimer, $activeTimerState); my ($activeTimer, $activeTimerState);
if (defined $myHash->{immerSchalten}) { if (defined $myHash->{immerSchalten}) {
$activeTimer = WeekdayTimer_isAnActiveTimer ($hash, $dieGanzeWoche, $newParam); $activeTimer = WeekdayTimer_isAnActiveTimer ($hash, $dieGanzeWoche, $newParam);
$activeTimerState = WeekdayTimer_isAnActiveTimer ($hash, $tage, $newParam); $activeTimerState = WeekdayTimer_isAnActiveTimer ($hash, $tage, $newParam);
Log3 $hash, 4, "[$name] Update - past timer activated"; Log3 $hash, 4, "[$name] Update - past timer activated";
@ -854,7 +900,6 @@ sub WeekdayTimer_isAnActiveTimer ($$$) {
Log3 $hash, 5, "[$name] condition: $xPression"; Log3 $hash, 5, "[$name] condition: $xPression";
my $ret = AnalyzeCommandChain(undef, $xPression); my $ret = AnalyzeCommandChain(undef, $xPression);
#Log3 $hash, 3, "[$name] condition:>>>$ret<<< $xPression";
Log3 $hash, 5, "[$name] result of condition:$ret"; Log3 $hash, 5, "[$name] result of condition:$ret";
return $ret; return $ret;
} }
@ -929,7 +974,9 @@ sub WeekdayTimer_FensterOffen ($$$) {
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}!=$time) {
Log3 $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skiped by new timer at $hash->{profil}{$time}{TIME}"; #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";
WeekdayTimer_RemoveInternalTimer($hash->{VERZOEGRUNG_IDX},$hash); WeekdayTimer_RemoveInternalTimer($hash->{VERZOEGRUNG_IDX},$hash);
} }
$hash->{VERZOEGRUNG_IDX} = $time; $hash->{VERZOEGRUNG_IDX} = $time;
@ -945,6 +992,7 @@ sub WeekdayTimer_FensterOffen ($$$) {
"ZWave" => { "READING" => "state", "STATUS" => "(open)", "MODEL" => "r" }, "ZWave" => { "READING" => "state", "STATUS" => "(open)", "MODEL" => "r" },
"MAX" => { "READING" => "state", "STATUS" => "(open.*)", "MODEL" => "r" }, "MAX" => { "READING" => "state", "STATUS" => "(open.*)", "MODEL" => "r" },
"dummy" => { "READING" => "state", "STATUS" => "(([Oo]pen|[Tt]ilt).*)", "MODEL" => "r" }, "dummy" => { "READING" => "state", "STATUS" => "(([Oo]pen|[Tt]ilt).*)", "MODEL" => "r" },
"HMCCUDEV" => { "READING" => "state", "STATUS" => "(open|tilted)", "MODEL" => "r" },
"WeekdayTimer" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" }, "WeekdayTimer" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" },
"Heating_Control" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" } "Heating_Control" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" }
); );
@ -990,7 +1038,7 @@ sub WeekdayTimer_FensterOffen ($$$) {
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}!=$time) {
Log3 $hash, 3, "[$name] timer at $hash->{profil}{$hash->{VERZOEGRUNG_IDX}}{TIME} skiped by new timer at $hash->{profil}{$time}{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";
WeekdayTimer_RemoveInternalTimer($hash->{VERZOEGRUNG_IDX},$hash); WeekdayTimer_RemoveInternalTimer($hash->{VERZOEGRUNG_IDX},$hash);
} }
$hash->{VERZOEGRUNG_IDX} = $time; $hash->{VERZOEGRUNG_IDX} = $time;
@ -1011,35 +1059,7 @@ sub WeekdayTimer_FensterOffen ($$$) {
delete $hash->{VERZOEGRUNG_IDX} if defined($hash->{VERZOEGRUNG_IDX}); delete $hash->{VERZOEGRUNG_IDX} if defined($hash->{VERZOEGRUNG_IDX});
return 0; return 0;
} }
################################################################################
sub WeekdayTimer_evalAndcleanupParam($$$$) {
my ($hash,$time,$param,$isHeating) = @_;
my $name = $hash->{DEVICE} ;
my $wdName = $hash->{NAME};
my $newParam = $param;
if ($param =~ m/^{.*}$/) {
Log3 $hash, 4, "[$wdName] calculating dynamic param before all: ....... $newParam";
$newParam =~ s/\$NAME/$hash->{DEVICE}/g;
$newParam =~ s/\$TIME/$time/g;
Log3 $hash, 4, "[$wdName] calculating dynamic param after substitutions: $newParam";
$newParam = eval $newParam;
if ($@ || not defined $newParam) {
Log3 $hash, 1, "[$wdName] problem calculating dynamic param: ........... $param";
Log3 $hash, 1, "[$wdName] $@";
} else {
Log3 $hash, 4, "[$wdName] calculating dynamic param after eval: ........ $newParam";
}
}elsif($isHeating && $param =~ m/^\d{1,3}$/){
$newParam = sprintf("%.1f", $param);
}
return $newParam;
}
################################################################################ ################################################################################
sub WeekdayTimer_Device_Schalten($$$) { sub WeekdayTimer_Device_Schalten($$$) {
my ($hash, $newParam, $tage) = @_; my ($hash, $newParam, $tage) = @_;
@ -1064,8 +1084,6 @@ sub WeekdayTimer_Device_Schalten($$$) {
my $aktParam = ReadingsVal($hash->{DEVICE}, $setModifier, ""); my $aktParam = ReadingsVal($hash->{DEVICE}, $setModifier, "");
$aktParam = sprintf("%.1f", $aktParam) if ($isHeating && $aktParam =~ m/^[0-9]{1,3}$/i); $aktParam = sprintf("%.1f", $aktParam) if ($isHeating && $aktParam =~ m/^[0-9]{1,3}$/i);
$newParam = sprintf("%.1f", $newParam) if ($isHeating && $newParam =~ m/^[0-9]{1,3}$/i); $newParam = sprintf("%.1f", $newParam) if ($isHeating && $newParam =~ m/^[0-9]{1,3}$/i);
# my $aktParam = WeekdayTimer_evalAndcleanupParam($hash,$dummy,ReadingsVal($hash->{DEVICE}, $setModifier, ""),$isHeating);
# newParam is already processed by evalAndcleanupParam()
my $disabled = AttrVal($hash->{NAME}, "disable", 0); my $disabled = AttrVal($hash->{NAME}, "disable", 0);
my $disabled_txt = $disabled ? " " : " not"; my $disabled_txt = $disabled ? " " : " not";
@ -1399,3 +1417,4 @@ sub WeekdayTimer_SetAllParms(;$) { # {WeekdayTimer_SetAllParms()}
=end :application/json;q=META.json =end :application/json;q=META.json
=cut =cut