change Modul to packages

This commit is contained in:
Marko Oldenburg 2020-03-25 15:33:08 +01:00
parent 2ef6d60201
commit d1638cf310

View File

@ -24,66 +24,75 @@
# along with FHEM. If not, see <http://www.gnu.org/licenses/>. # along with FHEM. If not, see <http://www.gnu.org/licenses/>.
# packages #################################################################### # packages ####################################################################
package main; ## unserer packagename
package FHEM::RandomTimer;
use strict; use strict;
use warnings; use warnings;
no if $] >= 5.017011, warnings => 'experimental::smartmatch'; no if $] >= 5.017011, warnings => 'experimental::smartmatch';
use Time::HiRes qw(gettimeofday); use Time::HiRes qw(gettimeofday);
use Time::Local 'timelocal_nocheck'; use Time::Local 'timelocal_nocheck';
# forward declarations ######################################################## ## Import der FHEM Funktionen
sub RandomTimer_Initialize($); #-- Run before package compilation
BEGIN {
sub RandomTimer_Define($$); # Import from main context
sub RandomTimer_Undef($$); GP_Import(
sub RandomTimer_Set($@); qw(
sub RandomTimer_Attr($$$); readingsSingleUpdate
readingsBulkUpdate
readingsBeginUpdate
readingsEndUpdate
defs
modules
Log
Log3
attr
readingFnAttributes
AttrVal
ReadingsVal
IsDisabled)
);
}
sub RandomTimer_addDays ($$); #-- Export to main context with different name
sub RandomTimer_device_switch ($); GP_Export(
sub RandomTimer_device_toggle ($); qw(
sub RandomTimer_disableDown($); Initialize
sub RandomTimer_down($); Exec
sub RandomTimer_Exec($); )
sub RandomTimer_getSecsToNextAbschaltTest($); );
sub RandomTimer_isAktive ($);
sub RandomTimer_isDisabled($);
sub RandomTimer_schaltZeitenErmitteln ($$);
sub RandomTimer_setActive($$);
sub RandomTimer_setState($);
sub RandomTimer_setSwitchmode ($$);
sub RandomTimer_SetTimer($);
sub RandomTimer_startZeitErmitteln ($$);
sub RandomTimer_stopTimeReached($);
sub RandomTimer_stopZeitErmitteln ($$);
sub RandomTimer_Wakeup();
sub RandomTimer_zeitBerechnen ($$$$);
# initialize ################################################################## # initialize ##################################################################
sub RandomTimer_Initialize($) { sub Initialize {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "RandomTimer_Define"; $hash->{DefFn} = 'FHEM::RandomTimer::Define';
$hash->{UndefFn} = "RandomTimer_Undef"; $hash->{UndefFn} = 'FHEM::RandomTimer::Undef';
$hash->{SetFn} = "RandomTimer_Set"; $hash->{SetFn} = 'FHEM::RandomTimer::Set';
$hash->{AttrFn} = "RandomTimer_Attr"; $hash->{AttrFn} = 'FHEM::RandomTimer::Attr';
$hash->{AttrList} = "onCmd offCmd switchmode disable:0,1 disableCond disableCondCmd:none,offCmd,onCmd offState ". $hash->{AttrList} =
"runonce:0,1 keepDeviceAlive:0,1 forceStoptimeSameDay:0,1 ". 'onCmd offCmd switchmode disable:0,1 disableCond disableCondCmd:none,offCmd,onCmd offState '
$readingFnAttributes; . 'runonce:0,1 keepDeviceAlive:0,1 forceStoptimeSameDay:0,1 '
. $readingFnAttributes;
} }
# regular Fn ################################################################## # regular Fn ##################################################################
sub RandomTimer_Define($$) { sub Define {
my ( $hash, $def ) = @_; my ( $hash, $def ) = @_;
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
my ($name, $type, $timespec_start, $device, $timespec_stop, $timeToSwitch, $variation) = my ( $name, $type, $timespec_start, $device, $timespec_stop, $timeToSwitch,
split("[ \t][ \t]*", $def); $variation )
= split( "[ \t][ \t]*", $def );
return "wrong syntax: define <name> RandomTimer <timespec_start> <device> <timespec_stop> <timeToSwitch> [<variations>]" return
"wrong syntax: define <name> RandomTimer <timespec_start> <device> <timespec_stop> <timeToSwitch> [<variations>]"
if ( !defined $timeToSwitch ); if ( !defined $timeToSwitch );
return "Wrong timespec_start <$timespec_start>, use \"[+][*]<time or func>\"" return
"Wrong timespec_start <$timespec_start>, use \"[+][*]<time or func>\""
if ( $timespec_start !~ m/^(\+)?(\*)?(.*)$/i ); if ( $timespec_start !~ m/^(\+)?(\*)?(.*)$/i );
my ( $rel, $rep, $tspec ) = ( $1, $2, $3 ); my ( $rel, $rep, $tspec ) = ( $1, $2, $3 );
@ -109,7 +118,9 @@ sub RandomTimer_Define($$) {
$variation =~ /^([\d]+)/ ? $varDuration = $1 : undef; $variation =~ /^([\d]+)/ ? $varDuration = $1 : undef;
$variation =~ /[:]([\d]+)/ ? $varStart = $1 : undef; $variation =~ /[:]([\d]+)/ ? $varStart = $1 : undef;
} }
RandomTimer_setSwitchmode ($hash, "800/200") if (!defined $hash->{helper}{SWITCHMODE});
SetSwitchmode( $hash, "800/200" )
if ( !defined $hash->{helper}{SWITCHMODE} );
$hash->{NAME} = $name; $hash->{NAME} = $name;
$hash->{DEVICE} = $device; $hash->{DEVICE} = $device;
@ -129,40 +140,44 @@ sub RandomTimer_Define($$) {
$hash->{helper}{offRegex} = "off"; $hash->{helper}{offRegex} = "off";
$hash->{helper}{offReading} = "state"; $hash->{helper}{offReading} = "state";
} }
#$attr{$name}{verbose} = 4; #$attr{$name}{verbose} = 4;
readingsSingleUpdate ($hash, "TimeToSwitch", $hash->{helper}{TIMETOSWITCH}, 1); readingsSingleUpdate( $hash, "TimeToSwitch", $hash->{helper}{TIMETOSWITCH},
1 );
RandomTimer_RemoveInternalTimer("SetTimer", $hash); RemoveInternalTimer( "FHEM::RandomTimer::SetTimer", $hash );
RandomTimer_InternalTimer("SetTimer", time(), "RandomTimer_SetTimer", $hash, 0); InternalTimer( "SetTimer", time(), "FHEM::RandomTimer::SetTimer", $hash,
0 );
return undef; return undef;
} }
sub RandomTimer_Undef($$) { sub Undef {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
RandomTimer_RemoveInternalTimer("SetTimer", $hash); RemoveInternalTimer( "FHEM::RandomTimer::SetTimer", $hash );
RandomTimer_RemoveInternalTimer("Exec", $hash); RemoveInternalTimer( "FHEM::RandomTimer::Exec", $hash );
delete $modules{RandomTimer}{defptr}{ $hash->{NAME} }; delete $modules{RandomTimer}{defptr}{ $hash->{NAME} };
return undef; return undef;
} }
sub RandomTimer_Attr($$$) { sub Attr {
my ( $cmd, $name, $attrName, $attrVal ) = @_; my ( $cmd, $name, $attrName, $attrVal ) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
if ( $attrName ~~ ["switchmode"] ) { if ( $attrName ~~ ["switchmode"] ) {
RandomTimer_setSwitchmode($hash, $attrVal); SetSwitchmode( $hash, $attrVal );
} }
if ( $attrName ~~ [ "disable", "disableCond" ] ) { if ( $attrName ~~ [ "disable", "disableCond" ] ) {
# Schaltung vorziehen, damit bei einem disable abgeschaltet wird. # Schaltung vorziehen, damit bei einem disable abgeschaltet wird.
RandomTimer_RemoveInternalTimer("Exec", $hash); RemoveInternalTimer( "FHEM::RandomTimer::Exec", $hash );
RandomTimer_InternalTimer("Exec", time()+1, "RandomTimer_Exec", $hash, 0); InternalTimer( "Exec", time() + 1, "FHEM::RandomTimer::Exec", $hash,
0 );
} }
if ( $attrName ~~ ["offState"] ) { if ( $attrName ~~ ["offState"] ) {
my @offState = split( ' ', $attrVal ); my @offState = split( ' ', $attrVal );
@ -172,11 +187,12 @@ sub RandomTimer_Attr($$$) {
return undef; return undef;
} }
sub RandomTimer_Set($@) { sub Set {
my ( $hash, @a ) = @_; my ( $hash, @a ) = @_;
return "no set value specified" if ( int(@a) < 2 ); return "no set value specified" if ( int(@a) < 2 );
return "Unknown argument $a[1], choose one of execNow:noArg" if($a[1] eq "?"); return "Unknown argument $a[1], choose one of execNow:noArg"
if ( $a[1] eq "?" );
my $name = shift @a; my $name = shift @a;
my $v = join( " ", @a ); my $v = join( " ", @a );
@ -185,17 +201,18 @@ sub RandomTimer_Set($@) {
Log3( $hash, 3, "[$name] set $name $v" ); Log3( $hash, 3, "[$name] set $name $v" );
if ( AttrVal( $name, "disable", 0 ) ) { if ( AttrVal( $name, "disable", 0 ) ) {
Log3( $hash, 3, "[$name] is disabled, set execNow not possible" ); Log3( $hash, 3, "[$name] is disabled, set execNow not possible" );
} else { }
RandomTimer_RemoveInternalTimer("Exec", $hash); else {
RandomTimer_InternalTimer("Exec", time()+1, "RandomTimer_Exec", $hash, 0); RemoveInternalTimer( "FHEM::RandomTimer::Exec", $hash );
InternalTimer( "Exec", time() + 1,
"FHEM::RandomTimer::Exec", $hash, 0 );
} }
} }
return undef; return undef;
} }
# module Fn ################################################################### # module Fn ###################################################################
sub RandomTimer_addDays ($$) { sub AddDays {
my ( $now, $days ) = @_; my ( $now, $days ) = @_;
my @jetzt_arr = localtime($now); my @jetzt_arr = localtime($now);
@ -205,13 +222,14 @@ sub RandomTimer_addDays ($$) {
} }
sub RandomTimer_device_switch ($) { sub Device_switch {
my ($hash) = @_; my ($hash) = @_;
my $command = "set @ $hash->{COMMAND}"; my $command = "set @ $hash->{COMMAND}";
if ( $hash->{COMMAND} eq "on" ) { if ( $hash->{COMMAND} eq "on" ) {
$command = AttrVal( $hash->{NAME}, "onCmd", $command ); $command = AttrVal( $hash->{NAME}, "onCmd", $command );
} else { }
else {
$command = AttrVal( $hash->{NAME}, "offCmd", $command ); $command = AttrVal( $hash->{NAME}, "offCmd", $command );
} }
$command =~ s/@/$hash->{DEVICE}/g; $command =~ s/@/$hash->{DEVICE}/g;
@ -220,139 +238,196 @@ sub RandomTimer_device_switch ($) {
Log3 $hash, 4, "[" . $hash->{NAME} . "]" . " command: $command"; Log3 $hash, 4, "[" . $hash->{NAME} . "]" . " command: $command";
my $ret = AnalyzeCommandChain( undef, $command ); my $ret = AnalyzeCommandChain( undef, $command );
Log3 ($hash, 3, "[$hash->{NAME}] ERROR: " . $ret . " SENDING " . $command) if($ret); Log3( $hash, 3, "[$hash->{NAME}] ERROR: " . $ret . " SENDING " . $command )
if ($ret);
#Log3 $hash, 3, "[$hash->{NAME}] Value($hash->{COMMAND})=".Value($hash->{DEVICE}); #Log3 $hash, 3, "[$hash->{NAME}] Value($hash->{COMMAND})=".Value($hash->{DEVICE});
#$hash->{"$hash->{COMMAND}Value"} = Value($hash->{DEVICE}); #$hash->{"$hash->{COMMAND}Value"} = Value($hash->{DEVICE});
} }
sub RandomTimer_device_toggle ($) { sub Device_toggle {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
#my $attrOffState = AttrVal($name,"offState",undef); #my $attrOffState = AttrVal($name,"offState",undef);
my $status = Value( $hash->{DEVICE} ); my $status = Value( $hash->{DEVICE} );
if ( defined $hash->{helper}{offRegex} ) { if ( defined $hash->{helper}{offRegex} ) {
$status = ReadingsVal($hash->{DEVICE},$hash->{helper}{offReading},"off"); $status =
ReadingsVal( $hash->{DEVICE}, $hash->{helper}{offReading}, "off" );
my $attrOffState = $hash->{helper}{offRegex}; my $attrOffState = $hash->{helper}{offRegex};
$status = $status =~ /^$attrOffState$/ ? "off" : lc($status); $status = $status =~ /^$attrOffState$/ ? "off" : lc($status);
$status = $status =~ /off/ ? "off" : "on"; $status = $status =~ /off/ ? "off" : "on";
} }
if ( $status ne "on" && $status ne "off" ) { if ( $status ne "on" && $status ne "off" ) {
if ( $hash->{helper}{offRegex} ) { if ( $hash->{helper}{offRegex} ) {
Log3 $hash, 3, "[$name] result of function ReadingsVal($hash->{DEVICE},\"<offReading>\",undef) must be 'on' or 'off' or set attribute offState accordingly"; Log3 $hash, 3,
} else { "[$name] result of function ReadingsVal($hash->{DEVICE},\"<offReading>\",undef) must be 'on' or 'off' or set attribute offState accordingly";
Log3 $hash, 3, "[$name] result of function Value($hash->{DEVICE}) must be 'on' or 'off'";; }
else {
Log3 $hash, 3,
"[$name] result of function Value($hash->{DEVICE}) must be 'on' or 'off'";
} }
} }
my $sigma = ($status eq "on") my $sigma =
( $status eq "on" )
? $hash->{helper}{SIGMAWHENON} ? $hash->{helper}{SIGMAWHENON}
: $hash->{helper}{SIGMAWHENOFF}; : $hash->{helper}{SIGMAWHENOFF};
my $zufall = int( rand(1000) ); my $zufall = int( rand(1000) );
Log3 $hash, 4, "[$name] IstZustand:$status sigmaWhen-$status:$sigma random:$zufall<$sigma=>" . (($zufall < $sigma)?"true":"false"); Log3 $hash, 4,
"[$name] IstZustand:$status sigmaWhen-$status:$sigma random:$zufall<$sigma=>"
. ( ( $zufall < $sigma ) ? "true" : "false" );
if ( $zufall < $sigma ) { if ( $zufall < $sigma ) {
$hash->{COMMAND} = ( $status eq "on" ) ? "off" : "on"; $hash->{COMMAND} = ( $status eq "on" ) ? "off" : "on";
RandomTimer_device_switch($hash); Device_switch($hash);
} }
} }
sub RandomTimer_disableDown($) { sub DisableDown {
my ($hash) = @_; my ($hash) = @_;
my $disableCondCmd = AttrVal( $hash->{NAME}, "disableCondCmd", 0 ); my $disableCondCmd = AttrVal( $hash->{NAME}, "disableCondCmd", 0 );
if ( $disableCondCmd ne "none" ) { if ( $disableCondCmd ne "none" ) {
Log3 $hash, 4, "[".$hash->{NAME}."]"." setting requested disableCondCmd on $hash->{DEVICE}: "; Log3 $hash, 4,
$hash->{COMMAND} = AttrVal($hash->{NAME}, "disableCondCmd", 0) eq "onCmd" ? "on" : "off"; "["
RandomTimer_device_switch($hash); . $hash->{NAME} . "]"
} else { . " setting requested disableCondCmd on $hash->{DEVICE}: ";
Log3 $hash, 4, "[".$hash->{NAME}."]"." no action requested on $hash->{DEVICE}: "; $hash->{COMMAND} =
AttrVal( $hash->{NAME}, "disableCondCmd", 0 ) eq "onCmd"
? "on"
: "off";
Device_switch($hash);
}
else {
Log3 $hash, 4,
"["
. $hash->{NAME} . "]"
. " no action requested on $hash->{DEVICE}: ";
} }
} }
sub RandomTimer_down($) { sub Down {
my ($hash) = @_; my ($hash) = @_;
Log3 $hash, 4, "[".$hash->{NAME}."]"." setting requested keepDeviceAlive on $hash->{DEVICE}: "; Log3 $hash, 4,
$hash->{COMMAND} = AttrVal($hash->{NAME}, "keepDeviceAlive", 0) ? "on" : "off"; "["
RandomTimer_device_switch($hash); . $hash->{NAME} . "]"
. " setting requested keepDeviceAlive on $hash->{DEVICE}: ";
$hash->{COMMAND} =
AttrVal( $hash->{NAME}, "keepDeviceAlive", 0 ) ? "on" : "off";
Device_switch($hash);
} }
sub Exec {
sub RandomTimer_Exec($) {
my ($myHash) = @_; my ($myHash) = @_;
my $hash = RandomTimer_GetHashIndirekt($myHash, (caller(0))[3]); my $hash = GetHashIndirekt( $myHash, ( caller(0) )[3] );
return if ( !defined($hash) ); return if ( !defined($hash) );
my $now = time(); my $now = time();
# Wenn aktiv aber disabled, dann timer abschalten, Meldung ausgeben. # Wenn aktiv aber disabled, dann timer abschalten, Meldung ausgeben.
my $active = RandomTimer_isAktive($hash); my $active = IsAktive($hash);
my $disabled = RandomTimer_isDisabled($hash); my $disabled = IsDisabled($hash);
my $stopTimeReached = RandomTimer_stopTimeReached($hash); my $stopTimeReached = StopTimeReached($hash);
if ($active) { if ($active) {
# wenn temporär ausgeschaltet # wenn temporär ausgeschaltet
if ($disabled) { if ($disabled) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." disabled before stop-time , ending RandomTimer on $hash->{DEVICE}: " Log3 $hash, 3,
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - " "["
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); . $hash->{NAME} . "]"
RandomTimer_disableDown($hash); . " disabled before stop-time , ending RandomTimer on $hash->{DEVICE}: "
RandomTimer_setActive($hash,0); . strftime( "%H:%M:%S(%d)",
RandomTimer_setState ($hash); localtime( $hash->{helper}{startTime} ) )
. " - "
. strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{stopTime} ) );
DisableDown($hash);
SetActive( $hash, 0 );
SetState($hash);
} }
# Wenn aktiv und Abschaltzeit erreicht, dann Gerät ausschalten, Meldung ausgeben und Timer schließen # Wenn aktiv und Abschaltzeit erreicht, dann Gerät ausschalten, Meldung ausgeben und Timer schließen
if ($stopTimeReached) { if ($stopTimeReached) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." stop-time reached, ending RandomTimer on $hash->{DEVICE}: " Log3 $hash, 3,
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - " "["
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); . $hash->{NAME} . "]"
RandomTimer_down($hash); . " stop-time reached, ending RandomTimer on $hash->{DEVICE}: "
RandomTimer_setActive($hash, 0); . strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{startTime} ) )
. " - "
. strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{stopTime} ) );
Down($hash);
SetActive( $hash, 0 );
if ( AttrVal( $hash->{NAME}, "runonce", -1 ) eq 1 ) { if ( AttrVal( $hash->{NAME}, "runonce", -1 ) eq 1 ) {
Log 3, "[" . $hash->{NAME} . "]" . "runonceMode"; Log 3, "[" . $hash->{NAME} . "]" . "runonceMode";
fhem("delete $hash->{NAME}"); fhem("delete $hash->{NAME}");
} }
RandomTimer_setState($hash); SetState($hash);
return; return;
} }
} else { # !active }
else { # !active
if ($disabled) { if ($disabled) {
Log3 $hash, 4, "[".$hash->{NAME}. "] RandomTimer on $hash->{DEVICE} timer disabled - no switch"; Log3 $hash, 4,
RandomTimer_setState($hash); "["
RandomTimer_setActive($hash,0); . $hash->{NAME}
. "] RandomTimer on $hash->{DEVICE} timer disabled - no switch";
SetState($hash);
SetActive( $hash, 0 );
} }
if ($stopTimeReached) { if ($stopTimeReached) {
Log3 $hash, 4, "[".$hash->{NAME}."]"." definition RandomTimer on $hash->{DEVICE}: " Log3 $hash, 4,
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - " "["
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); . $hash->{NAME} . "]"
RandomTimer_setState ($hash); . " definition RandomTimer on $hash->{DEVICE}: "
RandomTimer_setActive($hash,0); . strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{startTime} ) )
. " - "
. strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{stopTime} ) );
SetState($hash);
SetActive( $hash, 0 );
return; return;
} }
if ( !$disabled ) { if ( !$disabled ) {
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) { if ( $now > $hash->{helper}{startTime}
Log3 $hash, 3, "[".$hash->{NAME}."]"." starting RandomTimer on $hash->{DEVICE}: " && $now < $hash->{helper}{stopTime} )
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - " {
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); Log3 $hash, 3,
RandomTimer_setActive($hash,1); "["
. $hash->{NAME} . "]"
. " starting RandomTimer on $hash->{DEVICE}: "
. strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{startTime} ) )
. " - "
. strftime( "%H:%M:%S(%d)",
localtime( $hash->{helper}{stopTime} ) );
SetActive( $hash, 1 );
} }
} }
} }
RandomTimer_setState($hash); SetState($hash);
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) { if ( $now > $hash->{helper}{startTime} && $now < $hash->{helper}{stopTime} )
RandomTimer_device_toggle($hash) if (!$disabled); {
Device_toggle($hash) if ( !$disabled );
} }
my $nextSwitch = time() + RandomTimer_getSecsToNextAbschaltTest($hash); my $nextSwitch = time() + GetSecsToNextAbschaltTest($hash);
RandomTimer_RemoveInternalTimer("Exec", $hash); RemoveInternalTimer( "FHEM::RandomTimer::Exec", $hash );
$hash->{helper}{NEXT_CHECK} = strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch)); $hash->{helper}{NEXT_CHECK} =
RandomTimer_InternalTimer("Exec", $nextSwitch, "RandomTimer_Exec", $hash, 0); strftime( "%d.%m.%Y %H:%M:%S", localtime($nextSwitch) );
InternalTimer( "Exec", $nextSwitch, "FHEM::RandomTimer::Exec", $hash, 0 );
} }
sub RandomTimer_getSecsToNextAbschaltTest($) { sub GetSecsToNextAbschaltTest {
my ($hash) = @_; my ($hash) = @_;
my $intervall = $hash->{helper}{TIMETOSWITCH}; my $intervall = $hash->{helper}{TIMETOSWITCH};
my $varDuration = $hash->{helper}{VAR_DURATION}; my $varDuration = $hash->{helper}{VAR_DURATION};
@ -365,12 +440,12 @@ sub RandomTimer_getSecsToNextAbschaltTest($) {
return $nextSecs; return $nextSecs;
} }
sub RandomTimer_isAktive ($) { sub IsAktive {
my ($hash) = @_; my ($hash) = @_;
return defined( $hash->{helper}{active} ) ? $hash->{helper}{active} : 0; return defined( $hash->{helper}{active} ) ? $hash->{helper}{active} : 0;
} }
sub RandomTimer_isDisabled($) { sub IsDisabled {
my ($hash) = @_; my ($hash) = @_;
my $disable = AttrVal( $hash->{NAME}, "disable", 0 ); my $disable = AttrVal( $hash->{NAME}, "disable", 0 );
@ -379,60 +454,70 @@ sub RandomTimer_isDisabled($) {
my $disableCond = AttrVal( $hash->{NAME}, "disableCond", "nf" ); my $disableCond = AttrVal( $hash->{NAME}, "disableCond", "nf" );
if ( $disableCond eq "nf" ) { if ( $disableCond eq "nf" ) {
return 0; return 0;
} else { }
else {
$disable = eval($disableCond); $disable = eval($disableCond);
if ($@) { if ($@) {
$@ =~ s/\n/ /g; $@ =~ s/\n/ /g;
Log3 ($hash, 3, "[$hash->{NAME}] ERROR: " . $@ . " EVALUATING " . $disableCond); Log3( $hash, 3,
"[$hash->{NAME}] ERROR: "
. $@
. " EVALUATING "
. $disableCond );
} }
return $disable; return $disable;
} }
} }
sub RandomTimer_schaltZeitenErmitteln ($$) { sub SchaltZeitenErmitteln {
my ( $hash, $now ) = @_; my ( $hash, $now ) = @_;
RandomTimer_startZeitErmitteln($hash, $now); StartZeitErmitteln( $hash, $now );
RandomTimer_stopZeitErmitteln ($hash, $now); StopZeitErmitteln( $hash, $now );
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
# readingsBulkUpdate ($hash, "Startzeit", FmtDateTime($hash->{helper}{startTime})); # readingsBulkUpdate ($hash, "Startzeit", FmtDateTime($hash->{helper}{startTime}));
# readingsBulkUpdate ($hash, "Stoppzeit", FmtDateTime($hash->{helper}{stopTime})); # readingsBulkUpdate ($hash, "Stoppzeit", FmtDateTime($hash->{helper}{stopTime}));
readingsBulkUpdate ($hash, "StartTime", FmtDateTime($hash->{helper}{startTime})); readingsBulkUpdate( $hash, "StartTime",
readingsBulkUpdate ($hash, "StopTime", FmtDateTime($hash->{helper}{stopTime})); FmtDateTime( $hash->{helper}{startTime} ) );
readingsBulkUpdate( $hash, "StopTime",
FmtDateTime( $hash->{helper}{stopTime} ) );
readingsEndUpdate( $hash, defined( $hash->{LOCAL} ? 0 : 1 ) ); readingsEndUpdate( $hash, defined( $hash->{LOCAL} ? 0 : 1 ) );
} }
sub RandomTimer_setActive($$) { sub SetActive {
my ( $hash, $value ) = @_; my ( $hash, $value ) = @_;
$hash->{helper}{active} = $value; $hash->{helper}{active} = $value;
my $trigger = (RandomTimer_isDisabled($hash)) ? 0 : 1; my $trigger = ( IsDisabled($hash) ) ? 0 : 1;
readingsSingleUpdate( $hash, "active", $value, $trigger ); readingsSingleUpdate( $hash, "active", $value, $trigger );
} }
sub RandomTimer_setState($) { sub SetState {
my ($hash) = @_; my ($hash) = @_;
if (RandomTimer_isDisabled($hash)) { if ( IsDisabled($hash) ) {
my $dotrigger = ReadingsVal($hash->{NAME},"state","none") ne "disabled" ? 1 : 0; my $dotrigger =
ReadingsVal( $hash->{NAME}, "state", "none" ) ne "disabled" ? 1 : 0;
readingsSingleUpdate( $hash, "state", "disabled", $dotrigger ); readingsSingleUpdate( $hash, "state", "disabled", $dotrigger );
} else { }
else {
my $state = $hash->{helper}{active} ? "on" : "off"; my $state = $hash->{helper}{active} ? "on" : "off";
readingsSingleUpdate( $hash, "state", $state, 1 ); readingsSingleUpdate( $hash, "state", $state, 1 );
} }
} }
sub RandomTimer_setSwitchmode ($$) { sub SetSwitchmode {
my ( $hash, $attrVal ) = @_; my ( $hash, $attrVal ) = @_;
my $mod = "[" . $hash->{NAME} . "] "; my $mod = "[" . $hash->{NAME} . "] ";
if ( !( $attrVal =~ m/^([0-9]{1,3})\/([0-9]{1,3})$/i ) ) { if ( !( $attrVal =~ m/^([0-9]{1,3})\/([0-9]{1,3})$/i ) ) {
Log3 undef, 3, $mod . "invalid switchMode <$attrVal>, use 999/999"; Log3 undef, 3, $mod . "invalid switchMode <$attrVal>, use 999/999";
} else { }
else {
my ( $sigmaWhenOff, $sigmaWhenOn ) = ( $1, $2 ); my ( $sigmaWhenOff, $sigmaWhenOn ) = ( $1, $2 );
$hash->{helper}{SWITCHMODE} = $attrVal; $hash->{helper}{SWITCHMODE} = $attrVal;
$hash->{helper}{SIGMAWHENON} = $sigmaWhenOn; $hash->{helper}{SIGMAWHENON} = $sigmaWhenOn;
@ -441,42 +526,50 @@ sub RandomTimer_setSwitchmode ($$) {
} }
} }
sub RandomTimer_SetTimer($) { sub SetTimer {
my ($myHash) = @_; my ($myHash) = @_;
my $hash = RandomTimer_GetHashIndirekt($myHash, (caller(0))[3]); my $hash = GetHashIndirekt( $myHash, ( caller(0) )[3] );
return if ( !defined($hash) ); return if ( !defined($hash) );
my $now = time(); my $now = time();
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now); my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
localtime($now);
RandomTimer_setActive($hash, 0); SetActive( $hash, 0 );
RandomTimer_schaltZeitenErmitteln($hash, $now); SchaltZeitenErmitteln( $hash, $now );
RandomTimer_setState($hash); SetState($hash);
Log3 $hash, 4, "[".$hash->{NAME}."]" . " timings RandomTimer on $hash->{DEVICE}: " Log3 $hash, 4,
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - " "["
. $hash->{NAME} . "]"
. " timings RandomTimer on $hash->{DEVICE}: "
. strftime( "%H:%M:%S(%d)", localtime( $hash->{helper}{startTime} ) )
. " - "
. strftime( "%H:%M:%S(%d)", localtime( $hash->{helper}{stopTime} ) ); . strftime( "%H:%M:%S(%d)", localtime( $hash->{helper}{stopTime} ) );
my $secToMidnight = 24 * 3600 - ( 3600 * $hour + 60 * $min + $sec ); my $secToMidnight = 24 * 3600 - ( 3600 * $hour + 60 * $min + $sec );
my $setExecTime = max( $now, $hash->{helper}{startTime} ); my $setExecTime = max( $now, $hash->{helper}{startTime} );
RandomTimer_RemoveInternalTimer("Exec", $hash); RemoveInternalTimer( "FHEM::RandomTimer::Exec", $hash );
RandomTimer_InternalTimer("Exec", $setExecTime, "RandomTimer_Exec", $hash, 0); InternalTimer( "Exec", $setExecTime, "FHEM::RandomTimer::Exec", $hash, 0 );
if ( $hash->{helper}{REP} gt "" ) { if ( $hash->{helper}{REP} gt "" ) {
my $setTimerTime = max($now+$secToMidnight + 15, my $setTimerTime =
$hash->{helper}{stopTime}) + $hash->{helper}{TIMETOSWITCH}+15; max( $now + $secToMidnight + 15, $hash->{helper}{stopTime} ) +
RandomTimer_RemoveInternalTimer("SetTimer", $hash); $hash->{helper}{TIMETOSWITCH} + 15;
RandomTimer_InternalTimer("SetTimer", $setTimerTime, "RandomTimer_SetTimer", $hash, 0); RemoveInternalTimer( "FHEM::RandomTimer::SetTimer", $hash );
InternalTimer( "SetTimer", $setTimerTime,
"FHEM::RandomTimer::SetTimer", $hash, 0 );
} }
} }
sub RandomTimer_startZeitErmitteln ($$) { sub StartZeitErmitteln {
my ( $hash, $now ) = @_; my ( $hash, $now ) = @_;
my $timespec_start = $hash->{helper}{TIMESPEC_START}; my $timespec_start = $hash->{helper}{TIMESPEC_START};
return "Wrong timespec_start <$timespec_start>, use \"[+][*]<time or func>\"" return
"Wrong timespec_start <$timespec_start>, use \"[+][*]<time or func>\""
if ( $timespec_start !~ m/^(\+)?(\*)?(.*)$/i ); if ( $timespec_start !~ m/^(\+)?(\*)?(.*)$/i );
my ( $rel, $rep, $tspec ) = ( $1, $2, $3 ); my ( $rel, $rep, $tspec ) = ( $1, $2, $3 );
@ -486,22 +579,24 @@ sub RandomTimer_startZeitErmitteln ($$) {
my $startTime; my $startTime;
if ($rel) { if ($rel) {
$startTime = $now + 3600 * $hour + 60 * $min + $sec; $startTime = $now + 3600 * $hour + 60 * $min + $sec;
} else { }
$startTime = RandomTimer_zeitBerechnen($now, $hour, $min, $sec); else {
$startTime = ZeitBerechnen( $now, $hour, $min, $sec );
} }
my $varStart = $hash->{helper}{VAR_START}; my $varStart = $hash->{helper}{VAR_START};
$startTime += int( rand($varStart) ); $startTime += int( rand($varStart) );
$hash->{helper}{startTime} = $startTime; $hash->{helper}{startTime} = $startTime;
$hash->{helper}{STARTTIME} = strftime("%d.%m.%Y %H:%M:%S",localtime($startTime)); $hash->{helper}{STARTTIME} =
strftime( "%d.%m.%Y %H:%M:%S", localtime($startTime) );
} }
sub RandomTimer_stopTimeReached($) { sub StopTimeReached {
my ($hash) = @_; my ($hash) = @_;
return ( time() > $hash->{helper}{stopTime} ); return ( time() > $hash->{helper}{stopTime} );
} }
sub RandomTimer_stopZeitErmitteln ($$) { sub StopZeitErmitteln {
my ( $hash, $now ) = @_; my ( $hash, $now ) = @_;
my $timespec_stop = $hash->{helper}{TIMESPEC_STOP}; my $timespec_stop = $hash->{helper}{TIMESPEC_STOP};
@ -515,61 +610,74 @@ sub RandomTimer_stopZeitErmitteln ($$) {
my $stopTime; my $stopTime;
if ($rel) { if ($rel) {
$stopTime = $hash->{helper}{startTime} + 3600* $hour + 60* $min + $sec; $stopTime =
} else { $hash->{helper}{startTime} + 3600 * $hour + 60 * $min + $sec;
$stopTime = RandomTimer_zeitBerechnen($now, $hour, $min, $sec); }
else {
$stopTime = ZeitBerechnen( $now, $hour, $min, $sec );
} }
if ( !AttrVal( $hash->{NAME}, "forceStoptimeSameDay", 0 ) ) { if ( !AttrVal( $hash->{NAME}, "forceStoptimeSameDay", 0 ) ) {
if ( $hash->{helper}{startTime} > $stopTime ) { if ( $hash->{helper}{startTime} > $stopTime ) {
$stopTime = RandomTimer_addDays($stopTime, 1); $stopTime = AddDays( $stopTime, 1 );
} }
} }
$hash->{helper}{stopTime} = $stopTime; $hash->{helper}{stopTime} = $stopTime;
$hash->{helper}{STOPTIME} = strftime("%d.%m.%Y %H:%M:%S",localtime($stopTime)); $hash->{helper}{STOPTIME} =
strftime( "%d.%m.%Y %H:%M:%S", localtime($stopTime) );
} }
sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()} sub Wakeup() { # {Wakeup()}
foreach my $hc ( sort keys %{ $modules{RandomTimer}{defptr} } ) { foreach my $hc ( sort keys %{ $modules{RandomTimer}{defptr} } ) {
my $hash = $modules{RandomTimer}{defptr}{$hc}; my $hash = $modules{RandomTimer}{defptr}{$hc};
my $myHash->{HASH} = $hash; my $myHash->{HASH} = $hash;
RandomTimer_SetTimer($myHash); SetTimer($myHash);
Log3 undef, 3, "RandomTimer_Wakeup() for $hash->{NAME} done!"; Log3 undef, 3, "RandomTimer_Wakeup() for $hash->{NAME} done!";
} }
Log3 undef, 3, "RandomTimer_Wakeup() done!"; Log3 undef, 3, "RandomTimer_Wakeup() done!";
} }
sub RandomTimer_zeitBerechnen ($$$$) { sub ZeitBerechnen {
my ( $now, $hour, $min, $sec ) = @_; my ( $now, $hour, $min, $sec ) = @_;
my @jetzt_arr = localtime($now); my @jetzt_arr = localtime($now);
#Stunden Minuten Sekunden #Stunden Minuten Sekunden
$jetzt_arr[2] = $hour; $jetzt_arr[1] = $min; $jetzt_arr[0] = $sec; $jetzt_arr[2] = $hour;
$jetzt_arr[1] = $min;
$jetzt_arr[0] = $sec;
my $next = timelocal_nocheck(@jetzt_arr); my $next = timelocal_nocheck(@jetzt_arr);
return $next; return $next;
} }
sub RandomTimer_InternalTimer($$$$$) { sub InternalTimer {
my ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone ) = @_; my ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone ) = @_;
my $timerName = "$hash->{NAME}_$modifier"; my $timerName = "$hash->{NAME}_$modifier";
my $mHash = { HASH=>$hash, NAME=>"$hash->{NAME}_$modifier", MODIFIER=>$modifier}; my $mHash = {
HASH => $hash,
NAME => "$hash->{NAME}_$modifier",
MODIFIER => $modifier
};
if ( defined( $hash->{TIMER}{$timerName} ) ) { if ( defined( $hash->{TIMER}{$timerName} ) ) {
Log3 $hash, 1, "[$hash->{NAME}] possible overwriting of timer $timerName - please delete first"; Log3 $hash, 1,
"[$hash->{NAME}] possible overwriting of timer $timerName - please delete first";
stacktrace(); stacktrace();
} else { }
else {
$hash->{TIMER}{$timerName} = $mHash; $hash->{TIMER}{$timerName} = $mHash;
} }
Log3 $hash, 5, "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim); Log3 $hash, 5,
InternalTimer($tim, $callback, $mHash, $waitIfInitNotDone); "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim);
main::InternalTimer( $tim, $callback, $mHash, $waitIfInitNotDone );
return $mHash; return $mHash;
} }
################################################################################ ################################################################################
sub RandomTimer_RemoveInternalTimer($$) { sub RemoveInternalTimer {
my ( $modifier, $hash ) = @_; my ( $modifier, $hash ) = @_;
my $timerName = "$hash->{NAME}_$modifier"; my $timerName = "$hash->{NAME}_$modifier";
@ -577,23 +685,24 @@ sub RandomTimer_RemoveInternalTimer($$) {
if ( defined($myHash) ) { if ( defined($myHash) ) {
delete $hash->{TIMER}{$timerName}; delete $hash->{TIMER}{$timerName};
Log3 $hash, 5, "[$hash->{NAME}] removing Timer: $timerName"; Log3 $hash, 5, "[$hash->{NAME}] removing Timer: $timerName";
RemoveInternalTimer($myHash); main::RemoveInternalTimer($myHash);
} }
} }
sub RandomTimer_GetHashIndirekt ($$) { sub GetHashIndirekt ($$) {
my ( $myHash, $function ) = @_; my ( $myHash, $function ) = @_;
if ( !defined( $myHash->{HASH} ) ) { if ( !defined( $myHash->{HASH} ) ) {
Log 3, "[$function] myHash not valid"; Log 3, "[$function] myHash not valid";
return undef; return undef;
}; }
return $myHash->{HASH}; return $myHash->{HASH};
} }
1; 1;
# commandref ################################################################## # commandref ##################################################################
=pod =pod
=encoding utf8 =encoding utf8
=item helper =item helper