Integralwertberechnung + Median über Zeitraum

Begonnen von jensb, 24 Juni 2015, 22:38:46

Vorheriges Thema - Nächstes Thema

jensb

Hallo knxhm,

du hast wahrscheinlich weiter neue Updates auf das Reading bekommen, während du die holdTime geändert hast, denn gegen Ende werden die Werte betragsmäßig größer.

TimeSeries arbeitet zeitbasiert. Die holdTime stellt keine feste Anzahl von Werten ein, sondern das Alter für das älteste zu erhaltende Sample. Je nach dem, in welchem Takt die Reading-Updates erfolgen, hat man also mal mehr oder mal weniger Samples zur Verfügung.

Der Abstand zwischen zwei "sortdev" Logs ist bei dir nicht immer gleich. Um eine ungefähr konstante Anzahl zu verarbeiten, müsste man äquidistant sampeln. Zum Filtern vereinzelter Ausreißer reicht es aber sicherlich, wenn man eine holdTime einstellt, die im Normalfall eine Mindestanzahl von 5 (oder mehr) Samples sicherstellt, denn es ist bei der Median-Bestimmung kein Nachteil, wenn es vorübergehend auch mal mehr Samples werden.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

knxhm

Hallo Jens,
der gpio4 liefert mir per default ungefähr jede Minute eine Messung und das ist mir auch recht so. Wenn es also einen neuen Messwert gibt, dann sollte der älteste alt genug sein um zu verschwinden.
Deswegen habe ich normalerweise bei Zeitintervall 600 auch 10 Werte im Puffer von denen dann der Median genommen wird. Alles ok.

Wenn ich das Zeitinterval ändere dann erzeuge ich doch wohl keine neuen Messwerte, die kommen doch immer im gleichen Takt, oder ?
Deswegen kann ich mir die Erhöhung der Anzahl nach der Zeitänderung nicht recht erklären. Aber nachdem es sich nach einer Zeit eh wieder einpendelt, ist es wohl egal.

Heute hat er mir jedenfalls eine plausible Kurve gezeichnet, ohne die Nadelspitzen die ich loswerden wollte und abgestürzt ist er auch nicht. Alles gut.

lg
knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

jensb

Hallo knxhm,

freut mich, dass das so schon mal grundsätzlich funktioniert.

ZitatWenn ich das Zeitinterval ändere dann erzeuge ich doch wohl keine neuen Messwerte, die kommen doch immer im gleichen Takt, oder ?
Das Zeitintervall ist nur ein Wert der TimeSeries-Klasseninstanz und wirkt sich erst aus, wenn wieder neue Messwerte hinzugefügt werden.

Wenn du herausfinden willst, was wirklich passiert, dann dopple über ein notify zuerst das Original-Reading vom Sensor ohne event-aggregator auf einen 2. Reading-Namen und setze auf diesen den event-aggregator. Wenn du jetzt im Event-Monitor zusiehst oder beide Readings in ein Logfile schreibst, kannst du herausfinden, was wirklich passiert.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

knxhm

Hallo Jens,

hab einen dummy angelegt und mit einem notify ein userreading gesetzt, was ich dabei gesehen habe ist jedoch verwirrend.
Das ADD in TimeSeries.pm wird bei jedem Event 2mal aufgerufen und ich versteh nicht warum. Wobei beim 2. Aufruf ein Element mehr in der Series steht. Kannst du dir das erklären ?

config

pi@knxdfhem /opt/fhem $ grep Aussente fhem.cfg
define Aussentemp GPIO4 28-00000656fa4e
attr Aussentemp model DS18B20
attr Aussentemp room temperatur
define FileLog_Aussentemp FileLog ./log/Aussentemp-%Y-%W.log Aussentemp:temperature.*
attr FileLog_Aussentemp logtype text
define SVG_FileLog_Aussentemp_1 SVG FileLog_Aussentemp:SVG_FileLog_Aussentemp_1:CURRENT
attr SVG_FileLog_Aussentemp_1 nrAxis 1
attr SVG_FileLog_Aussentemp_1 room svg
define duAussentemp dummy
attr duAussentemp event-aggregator temp:300:none:median
attr duAussentemp room temperatur
attr duAussentemp userReadings temp
define noAussentemp notify Aussentemp setreading duAussentemp temp {(ReadingsVal("Aussentemp","temperature",""))}
attr noAussentemp disable 0


fhem.pl Auszug:

        require "TimeSeries.pm";
        if($function eq "median") {
          $ts= TimeSeries->new( { method => $method, holdTime => $duration } );
        } else {
          $ts= TimeSeries->new( { method => $method, autoreset => $duration } );
        }
        $readings->{".ts"}= $ts;
        # access from command line:
        # { $defs{"myClient"}{READINGS}{"myValue"}{".ts"}{max} }
        #Debug "TimeSeries created.";
      }
      my $now = $hash->{".updateTime"};
      my $val = $value; # save value
      $changed = $ts->elapsed($now);
      $value = $ts->{$function} if($changed);
Debug("$name voradd ");
      $ts->add($now, $val);

TimeSeries.pm Auszug

    # median
    if(defined($self->{holdTime})) {
      my @sortedVSeries = sort {$TimeSeries::a <=> $TimeSeries::b} @{$self->{vSeries}};
      my $center = int($self->{count} / 2);
  main::Debug("vSeries (@{$self->{vSeries}})");  ###
  main::Debug("center ($center)");  ###
  main::Debug("sortedv (@sortedVSeries)");  ###
      if($self->{count} % 2 == 0) {
        $self->{median} = (@sortedVSeries[$center - 1] + @sortedVSeries[$center]) / 2;
      } else {
        $self->{median} = @sortedVSeries[$center];
      }
  main::Debug("median ($self->{median})");  ###
    }
  } else {
    # time-weighting


debuglog


2016.01.29 08:03:48 5: Notify loop for HMLAN1 loadLvl: low
2016.01.29 08:04:01 5: Triggering Aussentemp (2 changes)
2016.01.29 08:04:01 5: Notify loop for Aussentemp T: 6
2016.01.29 08:04:01 5: Triggering noAussentemp
2016.01.29 08:04:01 4: noAussentemp exec setreading duAussentemp temp {(ReadingsVal("Aussentemp","temperature",""))}
2016.01.29 08:04:01 5: Cmd: >setreading duAussentemp temp {(ReadingsVal("Aussentemp","temperature",""))}<
2016.01.29 08:04:01 1: DEBUG>duAussentemp voradd
2016.01.29 08:04:01 1: DEBUG>vSeries (6 6 6 6 6 6 6 6 6)
2016.01.29 08:04:01 1: DEBUG>center (4)
2016.01.29 08:04:01 1: DEBUG>sortedv (6 6 6 6 6 6 6 6 6)
2016.01.29 08:04:01 1: DEBUG>median (6)
2016.01.29 08:04:01 5: Triggering duAussentemp (1 changes)
2016.01.29 08:04:01 5: Notify loop for duAussentemp temp: 6
2016.01.29 08:04:01 5: Triggering noAussentemp
2016.01.29 08:04:01 4: noAussentemp exec setreading duAussentemp temp {(ReadingsVal("Aussentemp","temperature",""))}
2016.01.29 08:04:01 5: Cmd: >setreading duAussentemp temp {(ReadingsVal("Aussentemp","temperature",""))}<
2016.01.29 08:04:01 1: DEBUG>duAussentemp voradd
2016.01.29 08:04:01 1: DEBUG>vSeries (6 6 6 6 6 6 6 6 6 6)
2016.01.29 08:04:01 1: DEBUG>center (5)
2016.01.29 08:04:01 1: DEBUG>sortedv (6 6 6 6 6 6 6 6 6 6)
2016.01.29 08:04:01 1: DEBUG>median (6)
2016.01.29 08:04:13 5: HMLAN_Send:  HMLAN1 I:K


lg
knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

jensb

Hallo knxhm,

das notify triggert ein 2. Mal, wenn der Dummy beschrieben wird:
Zitat2016.01.29 08:04:01 5: Notify loop for duAussentemp temp: 6
2016.01.29 08:04:01 5: Triggering noAussentemp
Könnte mir vorstellen, dass das notify reagiert, weil der Dummy den gleichen Teilstring enthält wie die Datenquelle, also "Aussentemp". Ändere mal den Namen vom Dummy auf "duAussenTemp", dann wird das vermutlich nicht mehr passieren.

Dass die Werte in diesem Fall mehr werden, ist nicht verwunderlich. Da ja kaum eine Sekunde vergangen ist, greift die eingestellte holdTime von 300 Sekunden nicht.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

jensb

Hallo Knxhm,

hier mein Vorschlag für die Änderung an fhem.pl:

      my (undef, $duration, $method, $function, $holdTime) = split(":", $v[0], 5);
      my $ts;
      if(defined($readings->{".ts"})) {
        $ts= $readings->{".ts"};
      } else {
        require "TimeSeries.pm";
        $ts= TimeSeries->new( { method => $method, autoreset => $duration, holdTime => $holdTime } );
        $readings->{".ts"}= $ts;
        # access from command line:
        # { $defs{"myClient"}{READINGS}{"myValue"}{".ts"}{max} }
        #Debug "TimeSeries created.";
      }


Mit diesem Ansatz kann man alle Features von TimeSeries nutzen. Du müsstest dann aber den event-aggregator auf "temp::none:median:300" ändern.

Bitte probier das mal aus - es sollte sich dadurch nichts an deiner Auswertung ändern.

Grüße,
Jens

FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

jensb

Hallo Knxhm,

habe mir das Zusammenspiel von TimeSeries und fhem.pl noch einmal angesehen. Derzeit würde es trotzdem zu einem Downsampling kommen, wenn man die holdTime setzt. Das ist aber nicht immer gewünscht, gerade wenn man eine gleitende Berechnung durchführen will. Anbei eine neue Version von TimeSeries mit entsprechend geänderter elapsed-Methode. Dadurch kann man das Downsampling und die Haltezeit getrennt vorgeben.

Beispiele:

  • event-aggregator "temp::none:median:300" -> kein Downsampling, aber 300 Sekunden Haltezeit
  • event-aggregator "temp:0:none:median:300" -> auch kein Downsampling, aber 300 Sekunden Haltezeit
  • event-aggregator "temp:30:none:median:300" -> Downsampling mit Update alle 30 Sekunden und 300 Sekunden Haltezeit

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

knxhm

Hallo Jens,

die letzte Vers. läuft ab jetzt im Test.

lg
knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

knxhm

Hallo Jens,

ich hab wieder Ausreisser.

Mit den Änderungen von:
am: 29 Januar 2016, 23:38:53 »
am: 29 Januar 2016, 22:03:25 »

Die letzte Änderung war wohl nicht so gut.

Konfiguriert habe ich so:
event-aggregator temp::none:median:600

lg
knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

jensb

Hallo knxhm,

die beiden Aenderungen haben vor allem damit zu tun, wie die Konfigurationsparameter uebergeben werden - an der eigentlichen Mathematik fuer die Median-Berechnung aendern sie nichts. Die in TimeSeries integrierte Selbttest-Funktion zeigt, dass die Beispielberechnungen einwandfrei ausgefuehrt werden. Um das gleiche Verhalten wie vor den Updates zu erhalten, kannst du 'temp:600:none:median:600' ausprobieren, denn da wurde nur alle 600 Sekunden ein neuer Messwert generiert. Dann hast du aber keinen gleitenden Median sondern einen geblockten 

Hast du z.B. zu bestimmten Zeiten mehrere Fehlmessungen dicht beieinander, schlagen die auf den Median durch. Verwendest man eine Blockberechnung, beeinflusst man die Wahrscheinlichkeit, dass man einen von solchen Ausreissern beeinflussten Median erhaelt - aber eine Garantie gegen Ausreisser ist das trotzdem nicht. Vielleicht sind bei deiner relativ geringen Datenrate auch die 600 Sekunden noch zu wenig, denn du muss sicher stellen, dass in jedem Zeitraum die Anzahl der Gutwerte ueberwiegt.

Es waere hilfreich, wenn du sowohl die Rohmesswerte als auch die berechneten Mediane in einem Log aufzeichnest. Noch besser ist ein Log, wie du es schon mal gemacht hat, wo die gepufferten Messwerte aus TimeSeries ausgegeben werden.

Gruesse,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

knxhm

Hallo Jens,
ja das hatte ich mir eh schon vorgenommen fürs We. Ich hatte aber im den alten logs nie mehr als einzelne falsche Werte ,da sollte der median immer gut gehen. Aber ich werde sehen. Vielleicht müssen wir nur noch etwas herumdoktern .
LG
Knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

knxhm

Hallo Jens,
das war wohl ein Eigentor, das kommt von zuviel c&p, reading Name in der config war falsch, dann gibts kein match und auch keinen event-aggregator :-(
Lass ma's jetzt berichtigt weiterlaufen.
lg
knxhm
KNX, HM, HMLAN, RPi 2 mit Raspbian Jessie, knxd und FHEM, 1w Temperaturmessung mit gpio4, Dämmerungssensor, autom. Rolladensteuerung

jensb

Hallo knxhm,

freue mich, wenn es sich so lösen lässt.

Für die erweiterte Funktionalität des event-aggregators fehlt nun noch die Anpassung der Hilfetexte. Es wird nicht ganz einfach, die vielen möglichen Konfigurationsvarianten so zu beschreiben, dass man sie ohne zusätzlichen Blick in den Perl-Code versteht. Werde erst mal einen Entwurf machen.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

jensb

Hallo Boris,

die Median-Berechnung scheint wie gewünscht zu funktionieren. Anbei die Patches für TimeSeries, fhem und commandref für die Unterstützung der Median-Berechnung per Event-Aggregator. Wenn gewünscht, kann ich das Einchecken übernehmen, aber ich hätte vorher gerne ein OK, da auch eine Änderung von fhem.pl erforderlich ist.

Grüße,
Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

Dr. Boris Neubert

Hallo Jens,

vielen Dank für Deine Arbeit!

Die überarbeitete Version ist abwärtskompatibel? Das heißt, dass wir keine Störungen bei laufenden Konfigurationen haben werden?

Ich bin nur autorisiert, TimeSeries.pm einzuchecken. Für die drei anderen Dateien musst Du bitte Rudi fragen. Wenn er die Patches heute bis 19 Uhr anwendet und das Ergebnis eincheckt, werde ich auch TimeSeries.pm einchecken. Sonst muss es bis zum nächsten Wochenende warten.

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!