From 65b0c96e95df80400a9f4cbb05e4c7816495520d Mon Sep 17 00:00:00 2001 From: tpoitzsch Date: Wed, 14 May 2014 20:10:18 +0000 Subject: [PATCH] singularReadings git-svn-id: https://svn.fhem.de/fhem/trunk@5862 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_statistics.pm | 188 +++++++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 61 deletions(-) diff --git a/fhem/FHEM/98_statistics.pm b/fhem/FHEM/98_statistics.pm index 49a8b7893..50c2018ed 100644 --- a/fhem/FHEM/98_statistics.pm +++ b/fhem/FHEM/98_statistics.pm @@ -40,7 +40,8 @@ use Time::Local; sub statistics_PeriodChange($); sub statistics_DoStatistics ($$$); sub statistics_doStatisticMinMax ($$$$$); -sub statistics_doStatisticMinMaxSingle ($$$$$$); +sub statistics_doStatisticMinMaxSingle ($$$$$$$); +sub statistics_storeSingleReadings ($$$$$$$$$$); sub statistics_doStatisticDelta ($$$$$); sub statistics_getStoredDevices($); @@ -100,18 +101,18 @@ statistics_Initialize($) { my ($hash) = @_; - $hash->{DefFn} = "statistics_Define"; - $hash->{UndefFn} = "statistics_Undefine"; - $hash->{NotifyFn} = "statistics_Notify"; + $hash->{DefFn} = "statistics_Define"; + $hash->{UndefFn} = "statistics_Undefine"; + $hash->{NotifyFn} = "statistics_Notify"; $hash->{NOTIFYDEV} = "global"; - $hash->{SetFn} = "statistics_Set"; + $hash->{SetFn} = "statistics_Set"; $hash->{NotifyOrderPrefix} = "10-"; # Want to be called before the rest $hash->{AttrList} = "disable:0,1 " ."dayChangeTime " ."excludedReadings " ."periodChangePreset " - ."singleReadings " + ."singularReadings " .$readingFnAttributes; } @@ -139,8 +140,8 @@ statistics_Define($$) RemoveInternalTimer($hash); - # Run period change procedure each full hour (1 second before). - my $periodEndTime = 3600 * ( int(gettimeofday()/3600) + 1 ) - 10 ; + # Run period change procedure next full hour (15 seconds before). + my $periodEndTime = 3600 * ( int(gettimeofday()/3600) + 1 ) - 15 ; InternalTimer( $periodEndTime, "statistics_PeriodChange", $hash, 0); return undef; @@ -249,7 +250,7 @@ statistics_Notify($$) if ($normalReadingFound==1) { statistics_DoStatistics $hash, $dev, 0; - Log3 $name,4,"$name: Notification of '".$dev->{NAME}."' received. Update statistics."; + Log3 $name,5,"$name: Notification of '".$dev->{NAME}."' received. Update statistics."; } else { Log3 $name,5,"$name: Notification of '".$dev->{NAME}."' received but for my own readings only."; } @@ -266,21 +267,34 @@ statistics_PeriodChange($) my ($hash) = @_; my $name = $hash->{NAME}; my $dummy; + my $val; my $periodChangePreset = AttrVal($name, "periodChangePreset", 10); - my $dayChangeTime = 0; + # Determine the next day change time + my @th=localtime(); + my $dayChangeDelay = 0; + my $dayChangeTime = timelocal(0,0,0,$th[3],$th[4],$th[5]+1900); if (AttrVal($name, "dayChangeTime", "00:00") =~ /(\d+):(\d+)/ && $1<24 && $1 >=0 && $2<60 && $2>=0) { - $dayChangeTime = $1 * 3600 + $2 * 60; + $dayChangeDelay = $1 * 3600 + $2 * 60; + $dayChangeTime += $dayChangeDelay; } - + RemoveInternalTimer($hash); - # Run period change procedure each full hour (1 second before). - my $periodEndTime = 3600 * ( int(gettimeofday()/3600) + 1 ) - $periodChangePreset ; - InternalTimer( $periodEndTime, "statistics_PeriodChange", $hash, 0); - Log3 $name,5,"$name: Next period change will be calculated at ".strftime ("%H:%M:%S", localtime($periodEndTime)); + # Run period change procedure each full hour ("periodChangePreset" second before). + my $periodEndTime = 3600 * ( int((gettimeofday()+1800)/3600) + 1 ) - $periodChangePreset ; + # Run procedure also for given dayChangeTime + $val = ""; + if ( gettimeofday() < $dayChangeTime && $dayChangeTime < $periodEndTime) { + $periodEndTime = $dayChangeTime; + $val = " (Day Change)"; + } + $val = strftime ("%Y-%m-%d %H:%M:%S", localtime($periodEndTime)) . $val; + InternalTimer( $periodEndTime, "statistics_PeriodChange", $hash, 1); + readingsSingleUpdate($hash, "nextPeriodChangeCalc", $val, 0); + Log3 $name,4,"$name: Next period change will be calculated at ".strftime ("%H:%M:%S", localtime($periodEndTime)); return if( AttrVal($name, "disable", 0 ) == 1 ); - + # Determine if time period switched (day, month, year) # Get deltaValue and Tariff of previous call @@ -288,12 +302,14 @@ statistics_PeriodChange($) my $yearLast; my $monthLast; my $dayLast; + my $minuteNow; + my $hourNow; my $dayNow; my $monthNow; my $yearNow; ($dummy, $dummy, $dummy, $dayLast, $monthLast, $yearLast) = localtime (gettimeofday() - 1800); - ($dummy, $dummy, $dummy, $dayNow, $monthNow, $yearNow) = localtime (gettimeofday() + 10 + $periodChangePreset); + ($dummy, $minuteNow, $hourNow, $dayNow, $monthNow, $yearNow) = localtime (gettimeofday() + 10 + $periodChangePreset); if ($yearNow != $yearLast) { $periodSwitch = 4; } elsif ($monthNow != $monthLast) { $periodSwitch = 3; } @@ -404,20 +420,21 @@ statistics_doStatisticMinMax ($$$$$) { my ($hash, $dev, $readingName, $decPlaces, $periodSwitch) = @_; my $name = $hash->{NAME}; + my $devName = $dev->{NAME}; return if not exists ($dev->{READINGS}{$readingName}); - + # Get reading, cut out first number without units my $value = $dev->{READINGS}{$readingName}{VAL}; $value =~ s/^[\D]*([\d.]*).*/$1/eg; - Log3 $name, 5, "Calculating min/avg/max statistics for '$readingName=$value'"; + Log3 $name, 4, "Calculating min/avg/max statistics for '".$dev->{NAME}.":$readingName = $value'"; # statistics_doStatisticMinMaxSingle: $hash, $readingName, $value, $saveLast, decPlaces # Daily Statistic - statistics_doStatisticMinMaxSingle $hash, $dev, $readingName."Day", $value, ($periodSwitch >= 2), $decPlaces; + statistics_doStatisticMinMaxSingle $hash, $dev, $readingName, "Day", $value, ($periodSwitch >= 2), $decPlaces; # Monthly Statistic - statistics_doStatisticMinMaxSingle $hash, $dev, $readingName."Month", $value, ($periodSwitch >= 3), $decPlaces; + statistics_doStatisticMinMaxSingle $hash, $dev, $readingName, "Month", $value, ($periodSwitch >= 3), $decPlaces; # Yearly Statistic - statistics_doStatisticMinMaxSingle $hash, $dev, $readingName."Year", $value, ($periodSwitch == 4), $decPlaces; + statistics_doStatisticMinMaxSingle $hash, $dev, $readingName, "Year", $value, ($periodSwitch == 4), $decPlaces; return ; @@ -425,19 +442,20 @@ statistics_doStatisticMinMax ($$$$$) # Calculates single MaxMin Values and informs about end of day and month sub ######################################## -statistics_doStatisticMinMaxSingle ($$$$$$) +statistics_doStatisticMinMaxSingle ($$$$$$$) { - my ($hash, $dev, $readingName, $value, $saveLast, $decPlaces) = @_; + my ($hash, $dev, $readingName, $period, $value, $saveLast, $decPlaces) = @_; my $result; - my $hiddenReadingName = ".".$dev->{NAME}.":".$readingName; + my $hiddenReadingName = ".".$dev->{NAME}.":".$readingName.$period; my $name=$hash->{NAME}; + my $devName = $dev->{NAME}; my $statReadingName = $hash->{PREFIX}; - $statReadingName .= ucfirst($readingName); + $statReadingName .= ucfirst($readingName).$period; my @hidden; my @stat; my $firstRun = not exists($hash->{READINGS}{$hiddenReadingName}); - + if ( $firstRun ) { # Show since-Value $hidden[1] = 0; $hidden[3] = 0; $hidden[9] = 1; @@ -469,17 +487,28 @@ statistics_doStatisticMinMaxSingle ($$$$$$) # Store current reading readingsBulkUpdate($dev, $statReadingName, $result, 0); - Log3 $name, 5, "Set '$statReadingName'='$result'"; - + Log3 $name, 5, "Set '$statReadingName'='$result'"; + + # Store single readings + my $singularReadings = AttrVal($name, "singularReadings", ""); + if ($singularReadings ne "") { + # statistics_storeSingleReadings $hashName,$singleReading,$dev,$statReadingName,$readingName,$statType,$period,$statValue,$value,$saveLast + my $statValue = sprintf "%.".$decPlaces."f", $stat[1]; + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Min",$period,$statValue,$value,$saveLast); + $statValue = sprintf "%.".$decPlaces."f", $stat[3]; + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Avg",$period,$statValue,$value,$saveLast); + $statValue = sprintf "%.".$decPlaces."f", $stat[5]; + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Max",$period,$statValue,$value,$saveLast); + } + # Store hidden reading $result = "Sum: $hidden[1] Time: $hidden[3] LastValue: ".$value." LastTime: ".int(gettimeofday())." ShowDate: $hidden[9]"; readingsSingleUpdate($hash, $hiddenReadingName, $result, 0); - Log3 $name, 5, "Set '$hiddenReadingName'='$result'"; + Log3 $name, 5, "Set '$hiddenReadingName'='$result'"; return; } - # Calculates deltas for day, month and year sub ######################################## statistics_doStatisticDelta ($$$$$) @@ -495,7 +524,7 @@ statistics_doStatisticDelta ($$$$$) # Get reading, cut out first number without units my $value = $dev->{READINGS}{$readingName}{VAL}; $value =~ s/^[\D]*([\d.]*).*/$1/eg; - Log3 $name, 5, "Calculating delta statistics for '$readingName=$value'"; + Log3 $name, 4, "Calculating delta statistics for '".$dev->{NAME}.":$readingName = $value'"; my $hiddenReadingName = ".".$dev->{NAME}.":".$readingName; @@ -585,6 +614,16 @@ statistics_doStatisticDelta ($$$$$) readingsBulkUpdate($dev,$statReadingName."Last",$result, 1); Log3 $name,4,"$name: Set '".$statReadingName."Last'='$result'"; } + + # Store single readings + my $singularReadings = AttrVal($name, "singularReadings", ""); + if ($singularReadings ne "") { + # statistics_storeSingleReadings $hashName,$singularReadings,$dev,$statReadingName,$readingName,$statType,$period,$statValue,$value,$saveLast + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Hour",$stat[1],$last[1],$periodSwitch >= 1); + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Day",$stat[1],$last[1],$periodSwitch >= 2); + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Month",$stat[1],$last[1],$periodSwitch >= 3); + statistics_storeSingleReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Year",$stat[1],$last[1],$periodSwitch >= 4); + } # Store hidden reading $result = "LastValue: $value ShowDate: $showDate "; @@ -594,6 +633,30 @@ statistics_doStatisticDelta ($$$$$) return ; } + +sub #################### +statistics_storeSingleReadings ($$$$$$$$$$) +{ + my ($hashName,$singularReadings,$dev,$statReadingName,$readingName,$statType,$period,$statValue,$value,$saveLast) = @_; + return if $singularReadings eq ""; + + if ($statType eq "Delta") { $statReadingName .= $period;} + else { $statReadingName .= $statType;} + my $devName=$dev->{NAME}; + if ("$devName:$readingName:$statType:$period" =~ /^($singularReadings)$/) { + if ($saveLast) { + readingsBulkUpdate($dev, $statReadingName."Last", $statValue, 1); + Log3 $hashName, 5, "Set ".$statReadingName."Last = $statValue"; + readingsBulkUpdate($dev, $statReadingName, $value, 1); + Log3 $hashName, 5, "Set ".$statReadingName."Last = $value"; + } else { + readingsBulkUpdate($dev, $statReadingName, $statValue, 1); + Log3 $hashName, 5, "Set ".$statReadingName." = $statValue"; + } + } +} + + sub #################### statistics_getStoredDevices ($) { @@ -620,6 +683,12 @@ statistics_getStoredDevices ($)

statistics

@@ -658,15 +720,22 @@ statistics_getStoredDevices ($)
- + Attributes @@ -678,6 +747,13 @@ statistics_getStoredDevices ($)

statistics

@@ -708,21 +779,17 @@ statistics_getStoredDevices ($)
Get -