diff --git a/fhem/FHEM/98_HourCounter.pm b/fhem/FHEM/98_HourCounter.pm index cc21b80f3..58dbe3198 100644 --- a/fhem/FHEM/98_HourCounter.pm +++ b/fhem/FHEM/98_HourCounter.pm @@ -42,185 +42,162 @@ # official part of fhem # adjusting log-output # update documentation - - +# 14.11.14 - 1.0.0.5 +# minor fixes for logging in HourCounter_Set: thanks kubuntufan +# reformating #################################################################################################### package main; use strict; use warnings; - use vars qw(%defs); use vars qw($readingFnAttributes); use vars qw(%attr); use vars qw(%modules); - -my $HourCounter_Version="1.0.0.4 - 23.10.2014"; - -my @HourCounter_cmdQeue =(); - +my $HourCounter_Version = "1.0.0.5 - 14.11.2014"; +my @HourCounter_cmdQeue = (); ########################## sub HourCounter_Log($$$) { my ( $hash, $loglevel, $text ) = @_; - my $xline = (caller(0))[2]; - - my $xsubroutine = (caller(1))[3]; - my $sub = (split( ':', $xsubroutine ))[2]; + my $xline = ( caller(0) )[2]; + my $xsubroutine = ( caller(1) )[3]; + my $sub = ( split( ':', $xsubroutine ) )[2]; $sub =~ s/HourCounter_//; - my $instName = ( ref($hash) eq "HASH" ) ? $hash->{NAME} : "HourCounter"; Log3 $hash, $loglevel, "HourCounter $instName $sub.$xline " . $text; } - ########################## -sub HourCounter_AddLog($$$) +sub HourCounter_AddLog($$$) { - my ($logdevice, $readingName,$value) = @_; - - my $cmd=''; - if ($readingName =~ m,state,i) - { - $cmd="trigger $logdevice $value << addLog"; - } - else - { - $cmd="trigger $logdevice $readingName: $value << addLog"; - } - - HourCounter_Log '',3,$cmd; - fhem ($cmd); + my ( $logdevice, $readingName, $value ) = @_; + my $cmd = ''; + if ( $readingName =~ m,state,i ) + { + $cmd = "trigger $logdevice $value << addLog"; + } else + { + $cmd = "trigger $logdevice $readingName: $value << addLog"; + } + HourCounter_Log '', 3, $cmd; + fhem($cmd); } - ########################## # execute the content of the given parameter sub HourCounter_Exec($) { - my $doit = shift; - my $ret=''; - eval $doit; - $ret = $@ if ($@); - return $ret; -} + my $doit = shift; + my $ret = ''; + eval $doit; + $ret = $@ if ($@); + return $ret; +} ########################## # add command to queue sub HourCounter_cmdQueueAdd($$) { - my ($hash,$cmd)= @_; - push(@{$hash->{helper}{cmdQueue}},$cmd); -} - + my ( $hash, $cmd ) = @_; + push( @{ $hash->{helper}{cmdQueue} }, $cmd ); +} ########################## # execute command queue sub HourCounter_ExecQueue($) { - my ($hash)=@_; - my $result; - - my $cnt=$#{$hash->{helper}{cmdQueue}}; - my $loops =0; - my $cntAll=0; - - HourCounter_Log $hash,4,"cnt: $cnt"; - - while ($cnt>=0) - { - for my $i (0 .. $cnt) - { - my $cmd = ${$hash->{helper}{cmdQueue}}[$i]; - ${$hash->{helper}{cmdQueue}}[$i]=''; - $result=HourCounter_Exec($cmd); - if ($result) - { - HourCounter_Log $hash,2,"$result"; - } - else { - HourCounter_Log $hash,4,"exec ok:$cmd"; - } - $cntAll++; - } - - # bearbeitete eintraege loeschen - for (my $i = $cnt; $i > -1; $i--) - { - splice (@{$hash->{helper}{cmdQueue}}, $i, 1) - } - - $cnt=$#HourCounter_cmdQeue; - $loops++; - if ($loops >= 5 || $cntAll>100) - { - HourCounter_Log $hash,2, "!!! too deep recursion"; - last; - } - } + my ($hash) = @_; + my $result; + my $cnt = $#{ $hash->{helper}{cmdQueue} }; + my $loops = 0; + my $cntAll = 0; + HourCounter_Log $hash, 4, "cnt: $cnt"; + while ( $cnt >= 0 ) + { + + for my $i ( 0 .. $cnt ) + { + my $cmd = ${ $hash->{helper}{cmdQueue} }[$i]; + ${ $hash->{helper}{cmdQueue} }[$i] = ''; + $result = HourCounter_Exec($cmd); + if ($result) + { + HourCounter_Log $hash, 2, "$result"; + } else + { + HourCounter_Log $hash, 4, "exec ok:$cmd"; + } + $cntAll++; + } + + # bearbeitete eintraege loeschen + for ( my $i = $cnt ; $i > -1 ; $i-- ) + { + splice( @{ $hash->{helper}{cmdQueue} }, $i, 1 ); + } + $cnt = $#HourCounter_cmdQeue; + $loops++; + if ( $loops >= 5 || $cntAll > 100 ) + { + HourCounter_Log $hash, 2, "!!! too deep recursion"; + last; + } + } } - - ########################## # round off the date passed to the hour sub HourCounter_RoundHour($) { - my ($sec,$min,$hour,$mday,$mon,$year) = localtime(shift); - return mktime(0, 0, $hour, $mday, $mon, $year); + my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(shift); + return mktime( 0, 0, $hour, $mday, $mon, $year ); } - ########################## # round off the date passed to the day sub HourCounter_RoundDay($) { - my ($sec,$min,$hour,$mday,$mon,$year) = localtime(shift); - return mktime(0, 0, 0, $mday, $mon, $year); + my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(shift); + return mktime( 0, 0, 0, $mday, $mon, $year ); } - ########################## # round off the date passed to the week sub HourCounter_RoundWeek($) { - my ($time) = @_; - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + my ($time) = @_; + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime($time); + # wday 0 Sonntag 1 Montag ... - $time-=$wday * 86400; + $time -= $wday * 86400; return HourCounter_RoundDay($time); } - ########################## # returns the seconds since the start of the day sub HourCounter_SecondsOfDay() { my $timeToday = gettimeofday(); - return int($timeToday - HourCounter_RoundDay($timeToday)); + return int( $timeToday - HourCounter_RoundDay($timeToday) ); } - ########################## # round off the date passed to the month sub HourCounter_RoundMonth($) { - my ($sec,$min,$hour,$mday,$mon,$year) = localtime(shift); - return mktime(0, 0, 0, 1, $mon, $year); + my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(shift); + return mktime( 0, 0, 0, 1, $mon, $year ); } ########################## # round off the date passed to the year sub HourCounter_RoundYear($) { - my ($sec,$min,$hour,$mday,$mon,$year) = localtime(shift); - return mktime(0, 0, 0, 1, 1, $year); + my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(shift); + return mktime( 0, 0, 0, 1, 1, $year ); } - ########################## sub HourCounter_Initialize($) { my ($hash) = @_; - $hash->{DefFn} = "HourCounter_Define"; - $hash->{UndefFn} = "HourCounter_Undef"; - - $hash->{SetFn} = "HourCounter_Set"; + $hash->{DefFn} = "HourCounter_Define"; + $hash->{UndefFn} = "HourCounter_Undef"; + $hash->{SetFn} = "HourCounter_Set"; $hash->{GetFn} = "HourCounter_Get"; $hash->{NotifyFn} = "HourCounter_Notify"; - $hash->{AttrList} = "disable:0,1 ". $readingFnAttributes; - + $hash->{AttrList} = "disable:0,1 " . $readingFnAttributes; HourCounter_Log "", 3, "Init Done with Version $HourCounter_Version"; } - ########################## sub HourCounter_Define($$$) { @@ -230,11 +207,10 @@ sub HourCounter_Define($$$) HourCounter_Log $hash, 4, "parameters: @a"; if ( @a < 3 ) { - return "wrong syntax: define HourCounter []"; + return "wrong syntax: define HourCounter []"; } - my $onRegexp = $a[2]; - - my $offRegexp = (@a==4)?$a[3]:undef; + my $onRegexp = $a[2]; + my $offRegexp = ( @a == 4 ) ? $a[3] : undef; # Checking for misleading regexps eval { "Hallo" =~ m/^$onRegexp/ }; @@ -244,33 +220,28 @@ sub HourCounter_Define($$$) eval { "Hallo" =~ m/^$offRegexp/ }; return "Bad regexp_for_ON : $@" if ($@); } - - $hash->{helper}{ON_Regexp} = $onRegexp; - $hash->{helper}{OFF_Regexp} = $offRegexp; - $hash->{helper}{isFirstRun} = 1; - $hash->{helper}{value} = -1; + $hash->{helper}{ON_Regexp} = $onRegexp; + $hash->{helper}{OFF_Regexp} = $offRegexp; + $hash->{helper}{isFirstRun} = 1; + $hash->{helper}{value} = -1; $hash->{helper}{forceHourChange} = ''; - $hash->{helper}{forceDayChange} = ''; + $hash->{helper}{forceDayChange} = ''; $hash->{helper}{forceWeekChange} = ''; - $hash->{helper}{forceMonthChange} = ''; + $hash->{helper}{forceMonthChange} = ''; $hash->{helper}{forceYearChange} = ''; - - $hash->{helper}{forceClear} = ''; - $hash->{helper}{calledByEvent} = ''; - $hash->{helper}{changedTimestamp} = ''; - @{$hash->{helper}{cmdQueue}} = (); - - $modules{HourCounter}{defptr}{$name}=$hash; + $hash->{helper}{forceClear} = ''; + $hash->{helper}{calledByEvent} = ''; + $hash->{helper}{changedTimestamp} = ''; + @{ $hash->{helper}{cmdQueue} } = (); + $modules{HourCounter}{defptr}{$name} = $hash; RemoveInternalTimer($name); - InternalTimer( int(gettimeofday() + 15), "HourCounter_Run", $name, 0 ); + InternalTimer( int( gettimeofday() + 15 ), "HourCounter_Run", $name, 0 ); return undef; - } ########################## sub HourCounter_Undef($$) { my ( $hash, $arg ) = @_; - HourCounter_Log $hash, 3, "Done"; return undef; } @@ -278,135 +249,121 @@ sub HourCounter_Undef($$) sub HourCounter_Get($@) { my ( $hash, @a ) = @_; - my $name = $hash->{NAME}; - - my $ret = "Unknown argument $a[1], choose one of version:noArg"; - my $cmd = lc( $a[1] ); - - if ($cmd eq 'version') + my $name = $hash->{NAME}; + my $ret = "Unknown argument $a[1], choose one of version:noArg"; + my $cmd = lc( $a[1] ); + if ( $cmd eq 'version' ) { $ret = "Version : $HourCounter_Version\n"; } - return $ret; - } ########################### sub HourCounter_Set($@) { my ( $hash, @a ) = @_; my $name = $hash->{NAME}; - my $reINT = '^([\\+,\\-]?\\d+$)'; # int - + my $reINT = '^([\\+,\\-]?\\d+$)'; # int + # determine userReadings beginning with app - my @readingNames = keys (%{$hash->{READINGS}}); + my @readingNames = keys( %{ $hash->{READINGS} } ); my @userReadings = (); foreach (@readingNames) { - if ($_ =~ m/app.*/) + if ( $_ =~ m/app.*/ ) { - push (@userReadings,$_); + push( @userReadings, $_ ); } } - my $strUserReadings = join(" ",@userReadings)." "; - + my $strUserReadings = join( " ", @userReadings ) . " "; + # standard commands with parameter - my @cmdPara =( - "countsOverall","countsPerDay", - "pauseTimeIncrement","pauseTimePerDay","pauseTimeOverall", - "pulseTimeIncrement","pulseTimePerDay","pulseTimeOverall"); - + my @cmdPara = ( + "countsOverall", "countsPerDay", "pauseTimeIncrement", "pauseTimePerDay", + "pauseTimeOverall", "pulseTimeIncrement", "pulseTimePerDay", "pulseTimeOverall" + ); + # standard commands with no parameter - my @cmdNoPara =("clear","forceHourChange","forceDayChange","forceWeekChange","forceMonthChange","forceYearChange"); - - my @allCommands = (@cmdPara,@cmdNoPara,@userReadings); - my $strAllCommands = join(" ",(@cmdPara,@userReadings))." ".join(":noArg ",@cmdNoPara).":noArg "; + my @cmdNoPara = ( + "clear", "forceHourChange", "forceDayChange", "forceWeekChange", + "forceMonthChange", "forceYearChange" + ); + my @allCommands = ( @cmdPara, @cmdNoPara, @userReadings ); + my $strAllCommands = + join( " ", ( @cmdPara, @userReadings ) ) . " " . join( ":noArg ", @cmdNoPara ) . ":noArg "; + #HourCounter_Log $hash, 2, "strAllCommands : $strAllCommands"; - # stop:noArg - my $usage = - "Unknown argument $a[1], choose one of " - .$strAllCommands; - - # we need at least 2 parameters + my $usage = "Unknown argument $a[1], choose one of " . $strAllCommands; + + # we need at least 2 parameters return "Need a parameter for set" if ( @a < 2 ); - my $cmd = $a[1]; - if ($cmd eq "?") + if ( $cmd eq "?" ) { return $usage; } my $value = $a[2]; - + # is command defined ? - if ( (grep { /$cmd/ } @allCommands) <= 0) + if ( ( grep { /$cmd/ } @allCommands ) <= 0 ) { - HourCounter_Log $hash, 2, "cmd:$cmd no match for : @allCommands"; - return return "unknown command : $cmd"; + HourCounter_Log $hash, 2, "cmd:$cmd no match for : @allCommands"; + return return "unknown command : $cmd"; } - + # need we a parameter ? my $hits = scalar grep { /$cmd/ } @cmdNoPara; - my $needPara = ($hits > 0) ? '' : 1; + my $needPara = ( $hits > 0 ) ? '' : 1; HourCounter_Log $hash, 4, "hits: $hits needPara:$needPara"; - - # if parameter needed, it must be an integer - return "Value must be an integer" if ($needPara && !($value =~ m/$reINT/)); - - HourCounter_Log $hash, 4, "$cmd $value"; - my $doRun=''; - if($needPara) + # if parameter needed, it must be an integer + return "Value must be an integer" if ( $needPara && !( $value =~ m/$reINT/ ) ); + my $info = "command : ".$cmd; + $info .= " ".$value if ($needPara); + HourCounter_Log $hash, 4, $info; + my $doRun = ''; + if ($needPara) { - readingsSingleUpdate( $hash, $cmd, $value, 1 ); - } - elsif ($cmd eq "forceHourChange") + readingsSingleUpdate( $hash, $cmd, $value, 1 ); + } elsif ( $cmd eq "forceHourChange" ) { - $hash->{helper}{forceHourChange}=1; - $doRun=1; - } - elsif ($cmd eq "forceDayChange") + $hash->{helper}{forceHourChange} = 1; + $doRun = 1; + } elsif ( $cmd eq "forceDayChange" ) { - $hash->{helper}{forceDayChange}=1; - $doRun=1; - } - elsif ($cmd eq "forceWeekChange") + $hash->{helper}{forceDayChange} = 1; + $doRun = 1; + } elsif ( $cmd eq "forceWeekChange" ) { - $hash->{helper}{forceWeekChange}=1; - $doRun=1; - } - elsif ($cmd eq "forceMonthChange") + $hash->{helper}{forceWeekChange} = 1; + $doRun = 1; + } elsif ( $cmd eq "forceMonthChange" ) { - $hash->{helper}{forceMonthChange}=1; - $doRun=1; - } - elsif ($cmd eq "forceYearChange") + $hash->{helper}{forceMonthChange} = 1; + $doRun = 1; + } elsif ( $cmd eq "forceYearChange" ) { - $hash->{helper}{forceYearChange}=1; - $doRun=1; - } - elsif ($cmd eq "clear") + $hash->{helper}{forceYearChange} = 1; + $doRun = 1; + } elsif ( $cmd eq "clear" ) { - $hash->{helper}{forceClear}=1; - $doRun=1; - } - else + $hash->{helper}{forceClear} = 1; + $doRun = 1; + } else { return "unknown command (2): $cmd"; } - if ($doRun) { - $hash->{helper}{value}=-1; - $hash->{helper}{calledByEvent}=1; - HourCounter_Run($hash->{NAME}); + $hash->{helper}{value} = -1; + $hash->{helper}{calledByEvent} = 1; + HourCounter_Run( $hash->{NAME} ); } - - return; - + return; } ########################## -sub HourCounter_Notify($$) +sub HourCounter_Notify($$) { my ( $hash, $dev ) = @_; my $name = $hash->{NAME}; @@ -426,342 +383,302 @@ sub HourCounter_Notify($$) { my $s = $dev->{CHANGED}[$i]; # read changed reading $s = "" if ( !defined($s) ); - my $isOnReading = ( "$devName:$s" =~ m/^$onRegexp$/ ); - my $isOffReading = ($offRegexp) ? ( "$devName:$s" =~ m/^$offRegexp$/ ):''; - + my $isOnReading = ( "$devName:$s" =~ m/^$onRegexp$/ ); + my $isOffReading = ($offRegexp) ? ( "$devName:$s" =~ m/^$offRegexp$/ ) : ''; HourCounter_Log $hash, 5, "devName:$devName; CHANGED:$s; isOnReading:$isOnReading; isOffReading:$isOffReading;"; - next if ( !( $isOnReading || ($isOffReading && $offRegexp) ) ); - + next if ( !( $isOnReading || ( $isOffReading && $offRegexp ) ) ); $hash->{helper}{value} = 1 if ($isOnReading); $hash->{helper}{value} = 0 if ($isOffReading); - $hash->{helper}{calledByEvent}=1; - HourCounter_Run($hash->{NAME}); + $hash->{helper}{calledByEvent} = 1; + HourCounter_Run( $hash->{NAME} ); } } - ########################## # converts the seconds in the date format sub HourCounter_Seconds2HMS($) { - my ( $seconds) = @_; - my ($Sekunde, $Minute, $Stunde, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime($seconds); - my $days = int($seconds/86400); - return sprintf( "%d Tage %02d:%02d:%02d", $days,$Stunde - 1, $Minute, $Sekunde ); + my ($seconds) = @_; + my ( $Sekunde, $Minute, $Stunde, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit ) + = localtime($seconds); + my $days = int( $seconds / 86400 ); + return sprintf( "%d Tage %02d:%02d:%02d", $days, $Stunde - 1, $Minute, $Sekunde ); } - ########################## # rounds the timestamp do the beginning of the week sub HourCounter_weekBase($) { - my ($time) = @_; - my $dayDiff = 60*60*24; - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + my ($time) = @_; + my $dayDiff = 60 * 60 * 24; + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime($time); + # wday 0 Sonntag 1 Montag ... - my $a=$time-$wday*$dayDiff; - my $b=int($a/$dayDiff); # auf tage gehen - my $c=$b*$dayDiff; + my $a = $time - $wday * $dayDiff; + my $b = int( $a / $dayDiff ); # auf tage gehen + my $c = $b * $dayDiff; return $c; } - ########################## sub HourCounter_Run($) { - # print "xxx TAG A\n" ; + # print "xxx TAG A\n" ; my ($name) = @_; - my $hash = $defs{$name}; - - return if (!defined($hash->{TYPE}) || $hash->{TYPE} ne 'HourCounter'); - - delete($hash->{CHANGETIME}); # timestamps for event-log-file-entries older, than current time - - my $calledByEvent = $hash->{helper}{calledByEvent}; - $hash->{helper}{calledByEvent} = ''; - - # if call was made by timer force value to -1 - my $valuePara = ($calledByEvent)? $hash->{helper}{value}:-1; - - $hash->{helper}{changedTimestamp} = ReadingsTimestamp( $name, "value", TimeNow() ) - if (!$hash->{helper}{changedTimestamp}); - my $sdValue = time_str2num($hash->{helper}{changedTimestamp}); - my $sdCurTime = gettimeofday(); - - my $isOffDefined = ($hash->{helper}{OFF_Regexp})? 1: ''; - - my $timeIncrement = int( $sdCurTime - $sdValue ); # time diff - $timeIncrement = 0 if ($timeIncrement<0); # wrong time offset in case of summer/winter time - - my $valueOld = ReadingsVal( $name, 'value', 0 ); # get the old value + my $hash = $defs{$name}; + return if ( !defined( $hash->{TYPE} ) || $hash->{TYPE} ne 'HourCounter' ); + delete( $hash->{CHANGETIME} ); # timestamps for event-log-file-entries older, than current time + my $calledByEvent = $hash->{helper}{calledByEvent}; + $hash->{helper}{calledByEvent} = ''; + + # if call was made by timer force value to -1 + my $valuePara = ($calledByEvent) ? $hash->{helper}{value} : -1; + $hash->{helper}{changedTimestamp} = ReadingsTimestamp( $name, "value", TimeNow() ) + if ( !$hash->{helper}{changedTimestamp} ); + my $sdValue = time_str2num( $hash->{helper}{changedTimestamp} ); + my $sdCurTime = gettimeofday(); + my $isOffDefined = ( $hash->{helper}{OFF_Regexp} ) ? 1 : ''; + my $timeIncrement = int( $sdCurTime - $sdValue ); # time diff + $timeIncrement = 0 if ( $timeIncrement < 0 ); # wrong time offset in case of summer/winter time + my $valueOld = ReadingsVal( $name, 'value', 0 ); # get the old value # variable for reading update - my $value = undef; - my $countsPerDay=undef; - my $countsOverall=undef; - - my $pulseTimeIncrement=undef; - my $pulseTimePerDay=undef; - my $pulseTimeOverall=undef; - - my $pauseTimePerDay=undef; - my $pauseTimeOverall=undef; - my $pauseTimeIncrement=undef; + my $value = undef; + my $countsPerDay = undef; + my $countsOverall = undef; + my $pulseTimeIncrement = undef; + my $pulseTimePerDay = undef; + my $pulseTimeOverall = undef; + my $pauseTimePerDay = undef; + my $pauseTimeOverall = undef; + my $pauseTimeIncrement = undef; + my $state = undef; + my $clearDate = undef; + my $sdRoundHour = HourCounter_RoundHour($sdCurTime); + my $sdRoundHourLast = $hash->{helper}{sdRoundHourLast}; + $sdRoundHourLast = $sdRoundHour if ( !$sdRoundHourLast ); + my $isHourChanged = ( $sdRoundHour != $sdRoundHourLast ) || $hash->{helper}{forceHourChange}; + my $sdRoundDayCurTime = HourCounter_RoundDay($sdCurTime); + my $sdRoundDayValue = HourCounter_RoundDay($sdRoundHourLast); + my $isDayChanged = ( $sdRoundDayCurTime != $sdRoundDayValue ) || $hash->{helper}{forceDayChange}; + my $sdRoundWeekCurTime = HourCounter_RoundWeek($sdCurTime); + my $sdRoundWeekValue = HourCounter_RoundWeek($sdRoundHourLast); + my $isWeekChanged = + ( $sdRoundWeekCurTime != $sdRoundWeekValue ) || $hash->{helper}{forceWeekChange}; + my $sdRoundMonthCurTime = HourCounter_RoundMonth($sdCurTime); + my $sdRoundMonthValue = HourCounter_RoundMonth($sdRoundHourLast); + my $isMonthChanged = + ( $sdRoundMonthCurTime != $sdRoundMonthValue ) || $hash->{helper}{forceMonthChange}; + my $sdRoundYearCurTime = HourCounter_RoundYear($sdCurTime); + my $sdRoundYearValue = HourCounter_RoundYear($sdRoundHourLast); + my $isYearChanged = + ( $sdRoundYearCurTime != $sdRoundYearValue ) || $hash->{helper}{forceYearChange}; - my $state=undef; - my $clearDate = undef; - - my $sdRoundHour = HourCounter_RoundHour($sdCurTime); - my $sdRoundHourLast = $hash->{helper}{sdRoundHourLast}; - $sdRoundHourLast = $sdRoundHour if (!$sdRoundHourLast); - my $isHourChanged = ($sdRoundHour != $sdRoundHourLast) || $hash->{helper}{forceHourChange}; - - my $sdRoundDayCurTime = HourCounter_RoundDay($sdCurTime); - my $sdRoundDayValue = HourCounter_RoundDay($sdRoundHourLast); - my $isDayChanged = ($sdRoundDayCurTime != $sdRoundDayValue) || $hash->{helper}{forceDayChange}; - - my $sdRoundWeekCurTime = HourCounter_RoundWeek($sdCurTime); - my $sdRoundWeekValue = HourCounter_RoundWeek($sdRoundHourLast); - my $isWeekChanged = ($sdRoundWeekCurTime != $sdRoundWeekValue) || $hash->{helper}{forceWeekChange}; - - my $sdRoundMonthCurTime = HourCounter_RoundMonth($sdCurTime); - my $sdRoundMonthValue = HourCounter_RoundMonth($sdRoundHourLast); - my $isMonthChanged = ($sdRoundMonthCurTime != $sdRoundMonthValue) || $hash->{helper}{forceMonthChange}; - - my $sdRoundYearCurTime = HourCounter_RoundYear($sdCurTime); - my $sdRoundYearValue = HourCounter_RoundYear($sdRoundHourLast); - my $isYearChanged = ($sdRoundYearCurTime != $sdRoundYearValue) || $hash->{helper}{forceYearChange}; #HourCounter_Log $hash, 0,"sdRoundYearCurTime : $sdRoundYearCurTime"; - while (1) { - # stop if disabled - last if ( AttrVal( $name, 'disable', '0' ) eq '1' ); - - # variables for controlling - my $resetDayCounter=''; - - HourCounter_Log $hash, 5, "value:$valuePara changedTimestamp:".$hash->{helper}{changedTimestamp} ; - + # stop if disabled + last if ( AttrVal( $name, 'disable', '0' ) eq '1' ); + + # variables for controlling + my $resetDayCounter = ''; + HourCounter_Log $hash, 5, + "value:$valuePara changedTimestamp:" . $hash->{helper}{changedTimestamp}; + # --------------- basic init after startup of fhem or reload - if ( $hash->{helper}{isFirstRun} ) + if ( $hash->{helper}{isFirstRun} ) { - $hash->{helper}{isFirstRun}=undef; + $hash->{helper}{isFirstRun} = undef; $hash->{helper}{sdRoundHourLast} = $sdRoundHourLast; HourCounter_Log $hash, 4, "first run done"; } - + # ------------ basic init, when first run after initial definition in fhem.cfg - if ( !defined(ReadingsVal( $name, 'value', undef)) || $hash->{helper}{forceClear} ) + if ( !defined( ReadingsVal( $name, 'value', undef ) ) || $hash->{helper}{forceClear} ) { - HourCounter_Log $hash, 4, "counters cleared " - ."forceClear:$hash->{helper}{forceClear}" - ." def(valueOld)".defined($valueOld); - - if (!defined($valueOld)) - { # create readings without triggering - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, 'tickHour', 0); - readingsBulkUpdate( $hash, 'tickDay', 0); - readingsBulkUpdate( $hash, 'tickWeek', 0); - readingsBulkUpdate( $hash, 'tickMonth',0); - readingsEndUpdate( $hash, 1 ); + HourCounter_Log $hash, 4, + "counters cleared " + . "forceClear:$hash->{helper}{forceClear}" + . " def(valueOld)" + . defined($valueOld); + if ( !defined($valueOld) ) + { # create readings without triggering + readingsBeginUpdate($hash); + readingsBulkUpdate( $hash, 'tickHour', 0 ); + readingsBulkUpdate( $hash, 'tickDay', 0 ); + readingsBulkUpdate( $hash, 'tickWeek', 0 ); + readingsBulkUpdate( $hash, 'tickMonth', 0 ); + readingsEndUpdate( $hash, 1 ); } - - if (! ($hash->{helper}{forceClear})) # set value at basic init + if ( !( $hash->{helper}{forceClear} ) ) # set value at basic init { - $valueOld = 0; - $value = 0; + $valueOld = 0; + $value = 0; } - - $timeIncrement = 0; - $hash->{helper}{forceClear} = ''; - $countsPerDay = 0; - $countsOverall = 0; - - $pulseTimeIncrement = 0; - $pulseTimePerDay = 0; - $pulseTimeOverall = 0; - - $pauseTimeIncrement = 0; - $pauseTimePerDay = 0; - $pauseTimeOverall = 0; - - $state = 0; - $clearDate = TimeNow(); + $timeIncrement = 0; + $hash->{helper}{forceClear} = ''; + $countsPerDay = 0; + $countsOverall = 0; + $pulseTimeIncrement = 0; + $pulseTimePerDay = 0; + $pulseTimeOverall = 0; + $pauseTimeIncrement = 0; + $pauseTimePerDay = 0; + $pauseTimeOverall = 0; + $state = 0; + $clearDate = TimeNow(); } - - # ------------------------- handling of transitions - - my $hasValueChanged = ( $isOffDefined && $valuePara == $valueOld ) ? '' :1; - + + # ------------------------- handling of transitions + my $hasValueChanged = ( $isOffDefined && $valuePara == $valueOld ) ? '' : 1; + # -------------- positive edge if ( $hasValueChanged && $valuePara == 1 ) { $hash->{helper}{changedTimestamp} = TimeNow(); + $value = $valuePara; + $valueOld = $valuePara; - $value = $valuePara; - $valueOld = $valuePara; - # handling of counters - $countsPerDay = ReadingsVal( $name, "countsPerDay", 0 ) + 1; # counter inkrementieren + $countsPerDay = ReadingsVal( $name, "countsPerDay", 0 ) + 1; # counter inkrementieren $countsOverall = ReadingsVal( $name, "countsOverall", 0 ) + 1; # counter inkrementieren - - if ($isOffDefined) # handling of pause + if ($isOffDefined) # handling of pause { - $pauseTimeIncrement = $timeIncrement; - - $pauseTimePerDay = ReadingsVal( $name, "pauseTimePerDay", 0 ) + $pauseTimeIncrement; - $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 )+ $pauseTimeIncrement; - my $pulsInc = ReadingsVal( $name, "pulseTimeIncrement", 0 ); - } + $pauseTimeIncrement = $timeIncrement; + $pauseTimePerDay = ReadingsVal( $name, "pauseTimePerDay", 0 ) + $pauseTimeIncrement; + $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 ) + $pauseTimeIncrement; + my $pulsInc = ReadingsVal( $name, "pulseTimeIncrement", 0 ); + } HourCounter_Log $hash, 4, "rising edge; countPerDay:$countsPerDay"; } - + # ------------ negative edge - elsif ($isOffDefined && $hasValueChanged && $valuePara == 0 ) + elsif ( $isOffDefined && $hasValueChanged && $valuePara == 0 ) { $hash->{helper}{changedTimestamp} = TimeNow(); - $value = $valuePara; - $valueOld = $valuePara; - + $value = $valuePara; + $valueOld = $valuePara; + # handling of pulse time - $pulseTimeIncrement = $timeIncrement; - $pulseTimePerDay = ReadingsVal( $name, "pulseTimePerDay", 0 ) + $pulseTimeIncrement; - $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) + $pulseTimeIncrement; - + $pulseTimeIncrement = $timeIncrement; + $pulseTimePerDay = ReadingsVal( $name, "pulseTimePerDay", 0 ) + $pulseTimeIncrement; + $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) + $pulseTimeIncrement; HourCounter_Log $hash, 4, "falling edge pulseTimeIncrement:$pulseTimeIncrement"; } - - - # --------------- Day change, update pauseTime and pulseTime + + # --------------- Day change, update pauseTime and pulseTime if ($isDayChanged) { HourCounter_Log $hash, 4, "day change isDayChanged:$isDayChanged"; - - ### accumulate incurred times until day change - if ($valueOld==0) + ### accumulate incurred times until day change + if ( $valueOld == 0 ) { - $pauseTimeIncrement = $timeIncrement; - $pauseTimePerDay = ReadingsVal( $name, "pauseTimePerDay", 0 ) + $timeIncrement; - $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 ) + $timeIncrement; - } - elsif ($valueOld==1) + $pauseTimeIncrement = $timeIncrement; + $pauseTimePerDay = ReadingsVal( $name, "pauseTimePerDay", 0 ) + $timeIncrement; + $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 ) + $timeIncrement; + } elsif ( $valueOld == 1 ) { - $pulseTimeIncrement = $timeIncrement; - $pulseTimePerDay = ReadingsVal( $name, "pulseTimePerDay", 0 ) + $timeIncrement; - $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) + $timeIncrement; + $pulseTimeIncrement = $timeIncrement; + $pulseTimePerDay = ReadingsVal( $name, "pulseTimePerDay", 0 ) + $timeIncrement; + $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) + $timeIncrement; } - + # update timestamp of reading value with current time - $hash->{helper}{changedTimestamp}=TimeNow(); - + $hash->{helper}{changedTimestamp} = TimeNow(); + # logabriss vermeiden - $pulseTimeIncrement = ReadingsVal( $name, "pulseTimeIncrement", 0 ) if (!defined($pulseTimeIncrement)); - $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) if (!defined($pulseTimeOverall)); - - $pauseTimeIncrement = ReadingsVal( $name, "pauseTimeIncrement", 0 ) if (!defined($pauseTimeIncrement)); - $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 ) if (!defined($pauseTimeOverall)); - - $countsOverall = ReadingsVal( $name, "countsOverall", 0 ) if (!defined($countsOverall)); - - $value = $valueOld; - - HourCounter_Log $hash, 4, "pulseTimeIncrement:$pulseTimeIncrement pauseTimeIncrement:$pauseTimeIncrement"; - $resetDayCounter=1; + $pulseTimeIncrement = ReadingsVal( $name, "pulseTimeIncrement", 0 ) + if ( !defined($pulseTimeIncrement) ); + $pulseTimeOverall = ReadingsVal( $name, "pulseTimeOverall", 0 ) + if ( !defined($pulseTimeOverall) ); + $pauseTimeIncrement = ReadingsVal( $name, "pauseTimeIncrement", 0 ) + if ( !defined($pauseTimeIncrement) ); + $pauseTimeOverall = ReadingsVal( $name, "pauseTimeOverall", 0 ) + if ( !defined($pauseTimeOverall) ); + $countsOverall = ReadingsVal( $name, "countsOverall", 0 ) if ( !defined($countsOverall) ); + $value = $valueOld; + HourCounter_Log $hash, 4, + "pulseTimeIncrement:$pulseTimeIncrement pauseTimeIncrement:$pauseTimeIncrement"; + $resetDayCounter = 1; } - - $state =$countsPerDay if (defined($countsPerDay) && ReadingsVal( $name, "state", 0 ) !=$countsPerDay); - - - ### -------------- update readings + $state = $countsPerDay + if ( defined($countsPerDay) && ReadingsVal( $name, "state", 0 ) != $countsPerDay ); + ### -------------- update readings readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "countsPerDay", $countsPerDay ) if defined($countsPerDay); - readingsBulkUpdate( $hash, "countsOverall", $countsOverall ) if defined($countsOverall); - - readingsBulkUpdate( $hash, "pulseTimeIncrement",$pulseTimeIncrement ) if defined($pulseTimeIncrement); - readingsBulkUpdate( $hash, "pulseTimePerDay", $pulseTimePerDay ) if defined($pulseTimePerDay); - readingsBulkUpdate( $hash, "pulseTimeOverall", $pulseTimeOverall) if defined($pulseTimeOverall); - - readingsBulkUpdate( $hash, "pauseTimeIncrement",$pauseTimeIncrement) if defined($pauseTimeIncrement); - readingsBulkUpdate( $hash, "pauseTimePerDay", $pauseTimePerDay) if defined($pauseTimePerDay); - readingsBulkUpdate( $hash, "pauseTimeOverall", $pauseTimeOverall) if defined($pauseTimeOverall); - - readingsBulkUpdate( $hash, "value", $value) if defined($value); - readingsBulkUpdate( $hash, 'state', $state) if defined($state); - readingsBulkUpdate( $hash, 'clearDate', $clearDate) if defined($clearDate); + readingsBulkUpdate( $hash, "countsPerDay", $countsPerDay ) if defined($countsPerDay); + readingsBulkUpdate( $hash, "countsOverall", $countsOverall ) if defined($countsOverall); + readingsBulkUpdate( $hash, "pulseTimeIncrement", $pulseTimeIncrement ) + if defined($pulseTimeIncrement); + readingsBulkUpdate( $hash, "pulseTimePerDay", $pulseTimePerDay ) if defined($pulseTimePerDay); + readingsBulkUpdate( $hash, "pulseTimeOverall", $pulseTimeOverall ) + if defined($pulseTimeOverall); + readingsBulkUpdate( $hash, "pauseTimeIncrement", $pauseTimeIncrement ) + if defined($pauseTimeIncrement); + readingsBulkUpdate( $hash, "pauseTimePerDay", $pauseTimePerDay ) if defined($pauseTimePerDay); + readingsBulkUpdate( $hash, "pauseTimeOverall", $pauseTimeOverall ) + if defined($pauseTimeOverall); + readingsBulkUpdate( $hash, "value", $value ) if defined($value); + readingsBulkUpdate( $hash, 'state', $state ) if defined($state); + readingsBulkUpdate( $hash, 'clearDate', $clearDate ) if defined($clearDate); readingsEndUpdate( $hash, 1 ); - + # --------------- fire time interval ticks for hour,day,month if ($isHourChanged) { - $hash->{helper}{forceHourChange} = ''; - $hash->{helper}{sdRoundHourLast} = $sdRoundHour; - readingsSingleUpdate( $hash, 'tickHour', 1,1); - HourCounter_Log $hash, 4, "tickHour fired"; - } - + $hash->{helper}{forceHourChange} = ''; + $hash->{helper}{sdRoundHourLast} = $sdRoundHour; + readingsSingleUpdate( $hash, 'tickHour', 1, 1 ); + HourCounter_Log $hash, 4, "tickHour fired"; + } if ($isDayChanged) { - $hash->{helper}{forceDayChange}= ''; - readingsSingleUpdate( $hash, 'tickDay', 1,1); - HourCounter_Log $hash, 4, "tickDay fired"; + $hash->{helper}{forceDayChange} = ''; + readingsSingleUpdate( $hash, 'tickDay', 1, 1 ); + HourCounter_Log $hash, 4, "tickDay fired"; } - if ($isWeekChanged) { - $hash->{helper}{forceWeekChange}= ''; - readingsSingleUpdate( $hash, 'tickWeek', 1,1); - HourCounter_Log $hash, 4, "tickWeek fired"; + $hash->{helper}{forceWeekChange} = ''; + readingsSingleUpdate( $hash, 'tickWeek', 1, 1 ); + HourCounter_Log $hash, 4, "tickWeek fired"; } - if ($isMonthChanged) { - $hash->{helper}{forceMonthChange}= ''; - readingsSingleUpdate( $hash, 'tickMonth', 1,1); - HourCounter_Log $hash, 4, "tickMonth fired"; + $hash->{helper}{forceMonthChange} = ''; + readingsSingleUpdate( $hash, 'tickMonth', 1, 1 ); + HourCounter_Log $hash, 4, "tickMonth fired"; } - if ($isYearChanged) { - $hash->{helper}{forceYearChange}= ''; - readingsSingleUpdate( $hash, 'tickYear', 1,1); - HourCounter_Log $hash, 4, "tickYear fired"; + $hash->{helper}{forceYearChange} = ''; + readingsSingleUpdate( $hash, 'tickYear', 1, 1 ); + HourCounter_Log $hash, 4, "tickYear fired"; } - - HourCounter_ExecQueue($hash); # execute command queue - + HourCounter_ExecQueue($hash); # execute command queue + # ----------- pending request for resetting all day counters if ($resetDayCounter) { - $resetDayCounter=undef; - - ### reset all day counters - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "countsPerDay", 0 ); - readingsBulkUpdate( $hash, "pulseTimePerDay", 0 ); - readingsBulkUpdate( $hash, "pauseTimePerDay", 0 ); - readingsEndUpdate( $hash, 1 ); + $resetDayCounter = undef; + ### reset all day counters + readingsBeginUpdate($hash); + readingsBulkUpdate( $hash, "countsPerDay", 0 ); + readingsBulkUpdate( $hash, "pulseTimePerDay", 0 ); + readingsBulkUpdate( $hash, "pauseTimePerDay", 0 ); + readingsEndUpdate( $hash, 1 ); } - - - last; - } - + last; + } + # ------------ calculate seconds until next hour starts - my $actTime = int(gettimeofday()); - my ($sec,$min,$hour) = localtime($actTime); - my $nextHourTime = int(($actTime + 3600)/3600)*3600; # round to next hour start - my $nextCall = $nextHourTime - $actTime; - - HourCounter_Log $hash, 5, "nextCall:$nextCall changedTimestamp:" - .$hash->{helper}{changedTimestamp}; - + my $actTime = int( gettimeofday() ); + my ( $sec, $min, $hour ) = localtime($actTime); + my $nextHourTime = int( ( $actTime + 3600 ) / 3600 ) * 3600; # round to next hour start + my $nextCall = $nextHourTime - $actTime; + HourCounter_Log $hash, 5, + "nextCall:$nextCall changedTimestamp:" . $hash->{helper}{changedTimestamp}; RemoveInternalTimer($name); InternalTimer( gettimeofday() + $nextCall, "HourCounter_Run", $hash->{NAME}, 0 ); - return undef; } - - 1; =pod @@ -927,4 +844,3 @@ sub HourCounter_Run($) =end html =cut -