2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-21 07:56:03 +00:00

statistics: new module to create MinMaxAvg + Delta Readings

git-svn-id: https://svn.fhem.de/fhem/trunk@5755 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
tpoitzsch 2014-05-05 20:29:46 +00:00
parent 094a8fc68b
commit 8b7267809b

View File

@ -38,9 +38,10 @@ use warnings;
use Time::Local; use Time::Local;
sub statistics_PeriodChange($); sub statistics_PeriodChange($);
sub statistics_DoStatistics ($$$);
sub statistics_doStatisticMinMax ($$$$$); sub statistics_doStatisticMinMax ($$$$$);
sub statistics_doStatisticMinMaxSingle ($$$$$$); sub statistics_doStatisticMinMaxSingle ($$$$$$);
sub statistics_DoStatistics ($$$); sub statistics_doStatisticDelta ($$$$$);
# Modul Version for remote debugging # Modul Version for remote debugging
my $modulVersion = "2014-05-04"; my $modulVersion = "2014-05-04";
@ -166,7 +167,7 @@ statistics_PeriodChange($)
{ {
if ($r =~ /^monitoredDevices.*/) { if ($r =~ /^monitoredDevices.*/) {
Log3 $name,5,"$name: Starting period change statistics (Type: $periodSwitch) for all devices of reading $r"; Log3 $name,5,"$name: Starting period change statistics (Type: $periodSwitch) for all devices of reading $r";
my $devNameArray = split /,/, $r; my $devNameArray = split /,/, $hash->{READINGS}{$r};
foreach my $devName ($devNameArray) { foreach my $devName ($devNameArray) {
Log3 $name,5,"$name: Doing period change statistics for device $devName"; Log3 $name,5,"$name: Doing period change statistics for device $devName";
# statistics_DoStatistics($hash, $defs{$devName}, $periodSwitch); # statistics_DoStatistics($hash, $defs{$devName}, $periodSwitch);
@ -197,13 +198,19 @@ statistics_DoStatistics($$$)
my $max = int(@{$dev->{CHANGED}}); my $max = int(@{$dev->{CHANGED}});
my $readingName; my $readingName;
my $value; my $value;
my $exclReadings = AttrVal($hashName, "excludedReadings", "");
# Loop through all known device types and readings # Loop through all known device types and readings
foreach my $f (@knownDeviceReadings) foreach my $f (@knownDeviceReadings)
{ {
$readingName = $$f[1]; $readingName = $$f[1];
# notifing device type is known and the device has also the known reading # notifing device type is known and the device has also the known reading
if ($$f[0] eq $devType ) { # No statistic for excluded Readings
my $completeReadingName = $devName.":".$readingName;
if ($$f[0] eq $devType && $completeReadingName !~ m/^($exclReadings)$/ ) {
if ($$f[2] == 1) { statistics_doStatisticMinMax ($hash, $dev, $readingName, $$f[3], $periodSwitch);} if ($$f[2] == 1) { statistics_doStatisticMinMax ($hash, $dev, $readingName, $$f[3], $periodSwitch);}
if ($$f[2] == 2) { statistics_doStatisticDelta ($hash, $dev, $readingName, $$f[3], $periodSwitch);}
} }
} }
@ -250,7 +257,7 @@ statistics_doStatisticMinMaxSingle ($$$$$$)
{ {
my ($hash, $dev, $readingName, $value, $saveLast, $decPlaces) = @_; my ($hash, $dev, $readingName, $value, $saveLast, $decPlaces) = @_;
my $result; my $result;
my $hiddenReadingName = ".".$dev->{NAME}.".".$readingName; my $hiddenReadingName = ".".$dev->{NAME}.":".$readingName;
my $statReadingName = $hash->{PREFIX}; my $statReadingName = $hash->{PREFIX};
$statReadingName .= ucfirst($readingName); $statReadingName .= ucfirst($readingName);
@ -267,7 +274,7 @@ statistics_doStatisticMinMaxSingle ($$$$$$)
# Do calculations if hidden reading exists # Do calculations if hidden reading exists
@hidden = split / /, $hash->{READINGS}{$hiddenReadingName}{VAL}; # Internal values @hidden = split / /, $hash->{READINGS}{$hiddenReadingName}{VAL}; # Internal values
@stat = split / /, $dev->{READINGS}{$statReadingName}{VAL}; @stat = split / /, $dev->{READINGS}{$statReadingName}{VAL};
my $timeDiff = gettimeofday()-$hidden[7]; my $timeDiff = int(gettimeofday())-$hidden[7];
$hidden[1] += $hidden[5] * $timeDiff; # sum $hidden[1] += $hidden[5] * $timeDiff; # sum
$hidden[3] += $timeDiff; # time $hidden[3] += $timeDiff; # time
if ($value < $stat[1]) { $stat[1]=$value; } # Min if ($value < $stat[1]) { $stat[1]=$value; } # Min
@ -292,7 +299,7 @@ statistics_doStatisticMinMaxSingle ($$$$$$)
readingsSingleUpdate($dev, $statReadingName, $result,0); readingsSingleUpdate($dev, $statReadingName, $result,0);
# Store hidden reading # Store hidden reading
$result = "Sum: $hidden[1] Time: $hidden[3] LastValue: ".$value." LastTime: ".gettimeofday()." ShowDate: $hidden[9]"; $result = "Sum: $hidden[1] Time: $hidden[3] LastValue: ".$value." LastTime: ".int(gettimeofday())." ShowDate: $hidden[9]";
readingsSingleUpdate($hash, $hiddenReadingName, $result,0); readingsSingleUpdate($hash, $hiddenReadingName, $result,0);
return; return;
@ -301,148 +308,108 @@ statistics_doStatisticMinMaxSingle ($$$$$$)
# Calculates deltas for day, month and year # Calculates deltas for day, month and year
sub ######################################## sub ########################################
statistics_doStatisticDelta ($$$$) statistics_doStatisticDelta ($$$$$)
{ {
my ($hash, $dev, $readingName, $decPlaces) = @_; my ($hash, $dev, $readingName, $decPlaces, $periodSwitch) = @_;
my $dummy; my $dummy;
my $result; my $result;
my $deltaValue;
my $previousTariff;
my $showDate; my $showDate;
return if not exists ($dev->{READINGS}{$readingName});
# Get reading, cut out first number without units
my $value = $dev->{READINGS}{$readingName}{VAL}; my $value = $dev->{READINGS}{$readingName}{VAL};
$value =~ s/^([\d.]*).*/$1/eg;
# Determine if time period switched (day, month, year) my $hiddenReadingName = ".".$dev->{NAME}.":".$readingName;
# Get deltaValue and Tariff of previous call
my $periodSwitch = 0; my $statReadingName = $hash->{PREFIX};
my $yearLast; my $monthLast; my $dayLast; my $hourLast; my $hourNow; my $dayNow; my $monthNow; my $yearNow; $statReadingName .= ucfirst($readingName);
if (exists($hash->{READINGS}{"." . $readingName . "Before"})) {
($yearLast, $monthLast, $dayLast, $hourLast) = ($hash->{READINGS}{"." . $readingName . "Before"}{TIME} =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d)/); my @hidden; my @stat; my @last;
$yearLast -= 1900; my $firstRun = not exists($hash->{READINGS}{$hiddenReadingName});
$monthLast --;
($dummy, $deltaValue, $dummy, $showDate) = split / /, $hash->{READINGS}{"." . $readingName . "Before"}{VAL} || "";
$deltaValue = $value - $deltaValue; if ( $firstRun ) {
} else { # Show since-Value and initialize all readings
($dummy, $dummy, $hourLast, $dayLast, $monthLast, $yearLast) = localtime;
$deltaValue = 0;
$previousTariff = 0;
$showDate = 8; $showDate = 8;
} @stat = split / /, "Hour: 0 Day: 0 Month: 0 Year: 0";
($dummy, $dummy, $hourNow, $dayNow, $monthNow, $yearNow) = localtime; $stat[9] = strftime ("%Y-%m-%d_%H:%M:%S",localtime() );
@last = split / /, "Hour: - Day: - Month: - Year: -";
if ($yearNow != $yearLast) { $periodSwitch = 4; }
elsif ($monthNow != $monthLast) { $periodSwitch = 3; }
elsif ($dayNow != $dayLast) { $periodSwitch = 2; }
elsif ($hourNow != $hourLast) { $periodSwitch = 1; }
# Determine if "since" value has to be shown in current and last reading
if ($periodSwitch == 4) {
if ($showDate == 1) { $showDate = 0; } # Do not show the "since:" value for year changes anymore
if ($showDate >= 2) { $showDate = 1; } # Shows the "since:" value for the first year change
}
if ($periodSwitch >= 3){
if ($showDate == 3) { $showDate = 2; } # Do not show the "since:" value for month changes anymore
if ($showDate >= 4) { $showDate = 3; } # Shows the "since:" value for the first month change
}
if ($periodSwitch >= 2){
if ($showDate == 5) { $showDate = 4; } # Do not show the "since:" value for day changes anymore
if ($showDate >= 6) { $showDate = 5; } # Shows the "since:" value for the first day change
}
if ($periodSwitch >= 1){
if ($showDate == 7) { $showDate = 6; } # Do not show the "since:" value for day changes anymore
if ($showDate >= 8) { $showDate = 7; } # Shows the "since:" value for the first hour change
}
# statistics_doStatisticDeltaSingle; $hash, $readingName, $deltaValue, $periodSwitch, $showDate, $firstCall
statistics_doStatisticDeltaSingle ($hash, $readingName, $deltaValue, $periodSwitch, $showDate);
# Hidden storage of current values for next call(before values)
$result = "Value: $value ShowDate: $showDate ";
readingsBulkUpdate($hash, ".".$readingName."Before", $result);
return ;
}
sub ########################################
statistics_doStatisticDeltaSingle ($$$$$)
{
my ($hash, $readingName, $deltaValue, $periodSwitch, $showDate) = @_;
my $dummy;
my $result;
# get existing statistic reading
my @curr;
if (exists($hash->{READINGS}{$readingName}{VAL})) {
@curr = split / /, $hash->{READINGS}{$readingName}{VAL} || "";
if ($curr[0] eq "Day:") { $curr[9]=$curr[7]; $curr[7]=$curr[5]; $curr[5]=$curr[3]; $curr[3]=$curr[1]; $curr[1]=0; }
} else { } else {
$curr[1] = 0; $curr[3] = 0; $curr[5] = 0; $curr[7] = 0; # Do calculations if hidden reading exists
$curr[9] = strftime "%Y-%m-%d_%H:%M:%S", localtime(); # start @stat = split / /, $dev->{READINGS}{$statReadingName}{VAL};
} @hidden = split / /, $hash->{READINGS}{$hiddenReadingName}{VAL}; # Internal values
$showDate = $hidden[3];
# get statistic values of previous period if (exists ($dev->{READINGS}{$readingName."Last"})) {
my @last; @last = split / /, $dev->{READINGS}{$readingName."Last"}{VAL};
if ($periodSwitch >= 1) {
if (exists ($hash->{READINGS}{$readingName."Last"})) {
@last = split / /, $hash->{READINGS}{$readingName."Last"}{VAL};
if ($last[0] eq "Day:") { $last[9]=$last[7]; $last[7]=$last[5]; $last[5]=$last[3]; $last[3]=$last[1]; $last[1]="-"; }
} else { } else {
@last = split / /, "Hour: - Day: - Month: - Year: -"; @last = split / /, "Hour: - Day: - Month: - Year: -";
} }
} my $deltaValue = $value - $hidden[1];
# Do statistic # Do statistic
$curr[1] += $deltaValue; $stat[1] += $deltaValue;
$curr[3] += $deltaValue; $stat[3] += $deltaValue;
$curr[5] += $deltaValue; $stat[5] += $deltaValue;
$curr[7] += $deltaValue; $stat[7] += $deltaValue;
# Determine if "since" value has to be shown in current and last reading
# If change of year, change yearly statistic # If change of year, change yearly statistic
if ($periodSwitch == 4) { if ($periodSwitch == 4) {
$last[7] = $curr[7]; $last[7] = $stat[7];
$curr[7] = 0; $stat[7] = 0;
if ($showDate == 1) { $last[9] = $curr[9]; } if ($showDate == 1) { $showDate = 0; } # Do not show the "since:" value for year changes anymore
if ($showDate >= 2) { $showDate = 1; $last[9] = $stat[9]; } # Shows the "since:" value for the first year change
} }
# If change of month, change monthly statistic # If change of month, change monthly statistic
if ($periodSwitch >= 3){ if ($periodSwitch >= 3){
$last[5] = $curr[5]; $last[5] = $stat[5];
$curr[5] = 0; $stat[5] = 0;
if ($showDate == 3) { $last[9] = $curr[9];} if ($showDate == 3) { $showDate = 2; } # Do not show the "since:" value for month changes anymore
if ($showDate >= 4) { $showDate = 3; $last[9] = $stat[9]; } # Shows the "since:" value for the first month change
} }
# If change of day, change daily statistic # If change of day, change daily statistic
if ($periodSwitch >= 2){ if ($periodSwitch >= 2){
$last[3] = $curr[3]; $last[3] = $stat[3];
$curr[3] = 0; $stat[3] = 0;
if ($showDate == 5) { if ($showDate == 5) { $showDate = 4; } # Do not show the "since:" value for day changes anymore
$last[9] = $curr[9]; if ($showDate >= 6) { # Shows the "since:" value for the first day change
$showDate = 5;
$last[9] = $stat[9];
# Next monthly and yearly values start at 00:00 and show only date (no time) # Next monthly and yearly values start at 00:00 and show only date (no time)
$curr[5] = 0; $stat[5] = 0;
$curr[7] = 0; $stat[7] = 0;
$curr[9] = strftime "%Y-%m-%d", localtime(); # start $stat[9] = strftime "%Y-%m-%d", localtime(); # start
} }
} }
# If change of hour, change hourly statistic # If change of hour, change hourly statistic
if ($periodSwitch >= 1){ if ($periodSwitch >= 1){
$last[1] = $curr[1]; $last[1] = $stat[1];
$curr[1] = 0; $stat[1] = 0;
if ($showDate == 7) { $last[9] = $curr[9];} if ($showDate == 7) { $showDate = 6; } # Do not show the "since:" value for day changes anymore
if ($showDate >= 8) { $showDate = 7; $last[9] = $stat[9]; } # Shows the "since:" value for the first hour change
}
} }
# Store visible statistic readings (delta values) # Store visible statistic readings (delta values)
$result = "Hour: $curr[1] Day: $curr[3] Month: $curr[5] Year: $curr[7]"; $result = "Hour: $stat[1] Day: $stat[3] Month: $stat[5] Year: $stat[7]";
if ( $showDate >=2 ) { $result .= " (since: $curr[9] )"; } if ( $showDate >=2 ) { $result .= " (since: $stat[9] )"; }
readingsBulkUpdate($hash,$readingName,$result); readingsSingleUpdate($dev,$statReadingName,$result,0);
# if changed, store previous visible statistic (delta) values # if changed, store previous visible statistic (delta) values
if ($periodSwitch >= 1) { if ($periodSwitch >= 1) {
$result = "Hour: $last[1] Day: $last[3] Month: $last[5] Year: $last[7]"; $result = "Hour: $last[1] Day: $last[3] Month: $last[5] Year: $last[7]";
if ( $showDate =~ /1|3|5|7/ ) { $result .= " (since: $last[9] )";} if ( $showDate =~ /1|3|5|7/ ) { $result .= " (since: $last[9] )";}
readingsBulkUpdate($hash,$readingName."Last",$result); readingsSingleUpdate($dev,$statReadingName."Last",$result,0);
} }
# Store hidden reading
$result = "LastValue: $value ShowDate: $showDate ";
readingsSingleUpdate($hash, $hiddenReadingName, $result,0);
return ;
} }
1; 1;