From 585e6f221a889227f4d996eb86ebfec753ada093 Mon Sep 17 00:00:00 2001 From: grompo <> Date: Fri, 25 Mar 2016 15:04:17 +0000 Subject: [PATCH] statistics: new feature, attribute specialDeltaPeriod enhanced git-svn-id: https://svn.fhem.de/fhem/trunk@11122 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_statistics.pm | 133 ++++++++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 33 deletions(-) diff --git a/fhem/FHEM/98_statistics.pm b/fhem/FHEM/98_statistics.pm index 004dd9859..4fdaef598 100644 --- a/fhem/FHEM/98_statistics.pm +++ b/fhem/FHEM/98_statistics.pm @@ -3,6 +3,7 @@ # # 98_statistic.pm # +# (c) 2014 Torsten Poitzsch # (c) 2014-2016 tupol http://forum.fhem.de/index.php?action=profile;u=5432 # # This module computes statistic data of and for readings of other modules @@ -135,7 +136,7 @@ sub statistics_Initialize($) ."minAvgMaxReadings " ."periodChangePreset " ."specialDeltaPeriodHours " - ."specialPeriod " + ."specialDeltaPeriod " ."singularReadings " ."tendencyReadings " .$readingFnAttributes; @@ -727,16 +728,18 @@ sub statistics_doStatisticDelta ($$$$) if ($showDate >= 2) { $showDate = 1; $last[9] = $stat[9]; } # Shows the "since:" value for the first year change statistics_Log $hash, 4, "Shifting current year in last value of '$statReadingName'."; } - # If change of month, change monthly statistic + # If change of month, change monthly statistic and check for special periods if ($periodSwitch >= 3 || $periodSwitch <= -3){ + statistics_doStatisticSpecialPeriod2 ($hash, $dev, $readingName, "Month", $decPlaces, $stat[5]); $last[5] = sprintf "%.".$decPlaces."f", $stat[5]; $stat[5] = 0; 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 statistics_Log $hash, 4, "Shifting current month in last value of '$statReadingName'."; } - # If change of day, change daily statistic + # If change of day, change daily statistic and check for special periods if ($periodSwitch >= 2 || $periodSwitch <= -2){ + statistics_doStatisticSpecialPeriod2 ($hash, $dev, $readingName, "Day", $decPlaces, $stat[3]); $last[3] = sprintf "%.".$decPlaces."f", $stat[3]; $stat[3] = 0; if ($showDate == 5) { $showDate = 4; } # Do not show the "since:" value for day changes anymore @@ -753,8 +756,9 @@ sub statistics_doStatisticDelta ($$$$) } statistics_Log $hash,4,"Shifting current day in last value of '$statReadingName'."; } - # If change of hour, change hourly statistic + # If change of hour, change hourly statistic and check for special periods if ($periodSwitch >= 1){ + statistics_doStatisticSpecialPeriod2 ($hash, $dev, $readingName, "Hour", $decPlaces, $stat[1]); $last[1] = sprintf "%.".$decPlaces."f", $stat[1]; $stat[1] = 0; if ($showDate == 7) { $showDate = 6; } # Do not show the "since:" value for day changes anymore @@ -787,13 +791,13 @@ sub statistics_doStatisticDelta ($$$$) if ($singularReadings ne "") { # statistics_storeSingularReadings $hashName,$singularReadings,$dev,$statReadingName,$readingName,$statType,$period,$statValue,$lastValue,$saveLast my $statValue = sprintf "%.".$decPlaces."f", $stat[1]; - statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Hour",$statValue,$last[1],$periodSwitch >= 1); + statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName, $readingName, "Delta", "Hour", $statValue, $last[1], $periodSwitch >= 1); $statValue = sprintf "%.".$decPlaces."f", $stat[3]; - statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Day",$statValue,$last[3],$periodSwitch >= 2 || $periodSwitch <= -2); + statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName, $readingName, "Delta", "Day", $statValue, $last[3], $periodSwitch >= 2 || $periodSwitch <= -2); $statValue = sprintf "%.".$decPlaces."f", $stat[5]; - statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Month",$statValue,$last[5],$periodSwitch >= 3 || $periodSwitch <= -3); + statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName, $readingName, "Delta", "Month", $statValue, $last[5], $periodSwitch >= 3 || $periodSwitch <= -3); $statValue = sprintf "%.".$decPlaces."f", $stat[7]; - statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName,$readingName,"Delta","Year",$statValue,$last[7],$periodSwitch == 4 || $periodSwitch == -4); + statistics_storeSingularReadings ($name,$singularReadings,$dev,$statReadingName, $readingName, "Delta", "Year", $statValue, $last[7], $periodSwitch == 4 || $periodSwitch == -4); } return ; @@ -829,7 +833,8 @@ sub statistics_doStatisticSpecialPeriod ($$$$$) my $result = 0; foreach (@hidden) { $result += $_; } $result = sprintf "%.".$decPlaces."f", $result; - $result .= " (".$#hidden.".hours)" if $#hidden != $specialPeriod-1; + $result .= " (".($#hidden+1).".hours)" if $#hidden != $specialPeriod-1; + statistics_Log $hash, 4, "Set '$statReadingName = $result'"; readingsBulkUpdate($dev, $statReadingName, $result, 1); # Store hidden stack @@ -841,19 +846,29 @@ sub statistics_doStatisticSpecialPeriod ($$$$$) # Calculates deltas for period of several hours ######################################## -sub statistics_doStatisticSpecialPeriod2 ($$$$$) +sub statistics_doStatisticSpecialPeriod2 ($$$$$$) { - my ($hash, $dev, $readingName,$statType, $period, $decPlaces, $value) = @_; + my ($hash, $dev, $readingName, $periodText, $decPlaces, $value) = @_; my $name = $hash->{NAME}; + my $pattern; - my $specialPeriod = AttrVal($name, "specialPeriod", ""); + my $specialDeltaPeriod = AttrVal($name, "specialDeltaPeriod", ""); + return unless $specialDeltaPeriod; + +#Check if reading occures in attribute specialDeltaPeriod, extract period numbers + my $devName = $dev->{NAME}; + $pattern = $devName . ":" . $readingName . ":" . $periodText . ':([\d:]+)'; + return unless $specialDeltaPeriod =~ $pattern; - return unless $specialPeriod; - - # if ("$devName:$readingName:$statType:$period=([\d:]+)" =~ /^($specialPeriod)$/) { - - my $statReadingName = $hash->{PREFIX} . ucfirst($readingName) . ucfirst($statType) . ucfirst($period); - my $hiddenReadingName = ".".$dev->{NAME} . ":" . $readingName . ":" . $statType . ":" . $period; +#Determine number of periods and maximal number + my @periods = split /:/, $1; + my $maxNumber=0; + @periods = sort { $a <=> $b } @periods; + $maxNumber = $periods[$#periods]; + +#Determine reading names + my $statReadingName = $hash->{PREFIX} . ucfirst($readingName) . ucfirst($periodText); + my $hiddenReadingName = ".".$devName . ":" . $readingName . $periodText; # Update hidden stack my @hidden = (); @@ -862,17 +877,34 @@ sub statistics_doStatisticSpecialPeriod2 ($$$$$) unshift @hidden, $value; statistics_Log $hash, 4, "Add $value to $hiddenReadingName"; - while ( $#hidden > $specialPeriod ) { + while ( $#hidden > $maxNumber ) { my $lastValue = pop @hidden; statistics_Log $hash, 4, "Remove last value '$lastValue' from '$hiddenReadingName'"; } - # Calculate specialPeriodValue +#Calculate and write specialPeriodValues my $result = 0; - foreach (@hidden) { $result += $_; } - $result = sprintf "%.".$decPlaces."f", $result; - if ($#hidden != $specialPeriod) { $result .= " (".$#hidden.".hours)"; } - readingsBulkUpdate($dev, $statReadingName, $result, 1); + my $counterHidden = 0; + my $counterPeriods = 0; + foreach (@hidden) { + $result += $_; + $counterHidden++; + if ( $counterHidden == $periods[$counterPeriods] ) { + $counterPeriods++; + my $rName = $statReadingName.$counterHidden; + my $rValue = sprintf "%.".$decPlaces."f", $result; + statistics_Log $hash, 4, "Set '$rName = $rValue'"; + readingsBulkUpdate($dev, $rName, $rValue, 1); + } + } + +#write specialPeriodValues for periods not reached yet + for (my $i = $counterPeriods; $i <= $#periods; $i++) { + my $rName = $statReadingName . $periods[$i]; + my $rValue = sprintf "%.".$decPlaces."f (%d %s)", $result, $#hidden+1, $periodText; + statistics_Log $hash, 4, "Set '$rName = $rValue'"; + readingsBulkUpdate($dev, $rName, $rValue, 1); + } # Store hidden stack $result = join( " ", @hidden ); @@ -1237,15 +1269,33 @@ sub statistics_UpdateDevReading($$$$)
Regulare expression of statistic values, which for which singular readings are created additionally to the summary readings. Eases the creation of plots. For duration readings the name of the state has to be used as statTypes. +
Example:
+
+ Wettersensor:rain:Delta:(Hour|Day)|(FritzDect:(current|power):(Avg|Max|Delta):(Hour|Day)
- Example: Wettersensor:rain:Delta:(Hour|Day)|(FritzDect:(current|power):(Avg|Max|Delta):(Hour|Day) -
- Badfenster:Window:(Open|Open_Count):Month -
+ Badfenster:Window:(Open|Open_Count):Month +

-
  • specialDeltaPeriodHours <hours> +
  • specialDeltaPeriod <Device:Reading:Period:count1:count2:...>
    - Adds, for readings of delta statistics, a singular reading for the given period of hours (e.g. for the rain of the last 72 hours) + Creates for the given delta reading additional singular readings of the given numbers of a period (Hour, Day, Month) +
    + Regular expressions cannot be used. More readings and/or period can be added but have to be separated by comma (without spaces). +
    +
    Example:
    +
    + attr Statistik specialDeltaPeriod Wettersensor:rain:Hour:48:72:96 +
    + This will add 3 additional readings for the rain of the last 48, 72, 96 hours. +
    + attr Statistik specialDeltaPeriod Wettersensor:rain:Hour:48,Wettersensor:rain:Day:30,EZaehler:energy:Month:6:12 +
    + This will add 4 additional readings for the rain of the last 48 hours and the last 30 Days and the energy consumtion of the last 6 and 12 months. +
    +

  • +
  • specialDeltaPeriodHours +
    + depreciated

  • tendencyReadings <readings>
    @@ -1387,12 +1437,29 @@ sub statistics_UpdateDevReading($$$$) Erleichtert die Erzeugung von Plots und anderer Auswertungen (notify).
    Für "duration"-Gerätewerte muss der Name des jeweiligen Statuswertes als Statistiktyp eingesetzt werden. +
    Beispiel:
    +
    + Wettersensor:rain:Delta:(Hour|Day)|FritzDect:power:Delta:Day
    - Beispiel: + Wettersensor:rain:Delta:(Hour|Day)|FritzDect:power:Delta:Day +
    +

  • +
  • specialDeltaPeriod <Gerät:Gerätewert:Zeitraum:Anzahl1:Anzahl2:...>
    - Wettersensor:rain:Delta:(Hour|Day)|FritzDect:power:Delta:Day + Erzeugt fügt die angegebenen "delta"-Gerätewert zusätzliche Einzelwerte für den angegebene Zeitraum (Hour, Day, Month) und der angegebenen Anzahl.
    - Badfenster:Window:(Open|Open_Count):Month + Reguläre Ausdrücke können nicht genutzt werden. Es können auch mehrere Gerätewert und/oder Zeiträume hinzugefügt werden. Diese müssen durch Kommas (ohne Leerzeichen) getrennt werden. +
    +
    Beispiel:
    +
    + attr Statistik specialDeltaPeriod Wettersensor:rain:Hour:48:72:96 +
    + Dies erzeugt 3 zusätzliche Werte für die Regenmenge in den letzten 48, 72, 96 Stunden. +
    + attr Statistik specialDeltaPeriod Wettersensor:rain:Hour:48,Wettersensor:rain:Day:30,EZaehler:energy:Month:6:12 +
    + Dies erzeugt 4 zusätzliche Werte für die Regenmenge in den letzten 48 Stunden und den letzten 30 tagen und den Energieverbrauch der letzten 6 und 12 Monate. +

  • specialDeltaPeriodHours <Stunden>