Autor Thema: Erweiterung: movingAverage  (Gelesen 535 mal)

Offline peter_w

  • Jr. Member
  • **
  • Beiträge: 91
Erweiterung: movingAverage
« am: 13 September 2019, 20:48:46 »
Hallo zusammen,
ich konnte den Codeschnipsel aus dem WIKI:
https://wiki.fhem.de/wiki/Gleitende_Mittelwerte_berechnen_und_loggen
prima brauchen und habe den bei mir eingebaut. Da ich kein Perl Spezialist bin habe ich das darin versteckte "Problem" nicht sofort gesehen und mich über die Ergebnisse gewundert:
Die Funktion geht davon aus das maximal 25 Werte in der gewählten Zeit herein kommen.
Sollten mehr kommen, dann wird der Mittelwert über 25 Werte gebildet egal wie lange die Zeit gewählt wurde.
Da bei mir die 25 locker überschritten wurden, habe ich eine Konstante eingefügt mit der man das Limit ändern kann und eine Warnung in der LOG datei wenn das Limit überschritten wurde.
Vielleicht hilft es ja Jemandem.
sub movingAverage($$$)
{
   use constant MAXARRSIZE => 25;
   my ($name,$reading,$avtime) = @_;
   my $hash = $defs{$name};
   my @new = my ($val,$time) = ($hash->{READINGS}{$reading}{VAL},$hash->{READINGS}{$reading}{TIME});
   my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;
   my $ctime = $csec+60*$cmin+3600*$chour;
   my $num;
   my $arr;
   #-- initialize if requested
   if( ($avtime eq "-1") ){
     $hash->{READINGS}{$reading}{"history"}=undef;
   }
   #-- test for existence
   if( !$hash->{READINGS}{$reading}{"history"}){
      #Log 1,"ARRAY CREATED";
      push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      $num = 1;
      $arr=\@{$hash->{READINGS}{$reading}{"history"}};
   } else {
      $num = int(@{$hash->{READINGS}{$reading}{"history"}});
      $arr=\@{$hash->{READINGS}{$reading}{"history"}};
      my $starttime = $arr->[0][1];
      my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;
      my $stime = $ssec+60*$smin+3600*$shour;
      #-- correct for daybreak
      $stime-=86400
        if( $stime > $ctime);
      if( ($num < MAXARRSIZE)&&( ($ctime-$stime)<$avtime) ){
        #Log 1,"ARRAY has $num elements, adding another one";
        push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      }else{
        shift(@{$hash->{READINGS}{$reading}{"history"}});
        push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      }
    }
    #-- output and average
    my $average = 0;
    for(my $i=0;$i<$num;$i++){
      $average+=$arr->[$i][0];
      Log 1,"$i: [$name moving average] Value = ".$arr->[$i][0]." Time = ".$arr->[$i][1];
    }
if($num == MAXARRSIZE-1)
{
  Log 4,"[$name moving average] maximum array size reached, maybe logging is to fast ?";
}
    $average=sprintf( "%5.3f", $average/$num);
    #--average
    Log 4,"[$name moving average] calculated over $num values is $average"; 
    return $average;
 }

Release  : 5.8
Raspberry Pi 3
CUL V 1.63 CSM868 HomeMatic (SCC)
HM-CC-RT-DN,HM-LC-Bl1PBU-FM,HM-LC-Sw1PBU-FM,HM-SEC-SCo,HM-WDS10-TH-O

Offline Prof. Dr. Peter Henning

  • Developer
  • Hero Member
  • ****
  • Beiträge: 6805
Antw:Erweiterung: movingAverage
« Antwort #1 am: 01 Oktober 2019, 21:25:54 »
Zitat
Die Funktion geht davon aus das maximal 25 Werte in der gewählten Zeit herein kommen.
Sollten mehr kommen, dann wird der Mittelwert über 25 Werte gebildet egal wie lange die Zeit gewählt wurde.

Wieso sollte das ein Problem sein ? Im Gegenteil, ein gleitender Mittelwert über mehr als 25 Werte ist ein Problem - die Werte kommen dann viel zu häufig rein.

Eine Erweiterung oder Verbesserung sehe ich in dieser trivialen Änderung nicht.

LG

pah