Stundenmittelwerte ermitteln und in Log schreiben

Begonnen von tetzlav, 11 März 2013, 23:05:32

Vorheriges Thema - Nächstes Thema

tetzlav

Ich verzweifel an perl... :-/

Soweit habe ich verstanden, dass das average-Modul keine relativen Mittelwerte erzeugen kann. Es werden ab einem festen Wert die Readings aufsummiert und durch das Zeitintervall bis localtime() geteilt. Danach wird wird cum_XYZ wieder gelöscht und von neuem ausummiert. Dafür brauchtman keine Logs sondern immer nur die aktuellen Readings.

Möchte man aber den Mittelwert z.B. bezogen auf localtime(time-3600), also alle Werte der letzten Stunde, muss man an die Logs ran.
Das habe ich jetzt versucht und prinzipiell funktioniert das schon:


fhem> {my $period_start = strftime "%Y-%m-%d_%H:%M:%S", localtime(time-3600);;my $period_end = strftime "%Y-%m-%d_%H:%M:%S", localtime;; fhem("get FileLog_KS300 - - $period_start $period_end 8:::");;}
2013-03-11_21:48:24 2.7
2013-03-11_21:50:57 3.6
2013-03-11_21:53:29 0.2
2013-03-11_21:56:02 2.7
2013-03-11_21:58:34 1.9
2013-03-11_22:01:07 3.3
2013-03-11_22:06:12 0.8
2013-03-11_22:08:44 1.1
2013-03-11_22:11:17 0.0
2013-03-11_22:13:49 0.0
2013-03-11_22:16:22 0.0
2013-03-11_22:18:54 0.2
2013-03-11_22:21:27 1.6
2013-03-11_22:23:59 0.2
2013-03-11_22:26:32 2.5
2013-03-11_22:29:04 0.8
2013-03-11_22:31:37 1.3
2013-03-11_22:34:09 1.3
2013-03-11_22:36:42 0.8
2013-03-11_22:39:14 0.2
2013-03-11_22:41:47 0.0
2013-03-11_22:46:52 0.2
#8:::

fhem>


Jetzt scheiter ich nur noch daran die obige Ausgabe z.B. in dieser Art zu verarbeiten:


| grep ^[0-9] | perl -ane '$i += 1; $cum += $F[1]; printf ("Nr: %d: Wert: %0.1f Sum: %0.1f MW: %0.1f\n", $i, $F[1], $cum, $cum/$i)'


bzw. mir einfach nur den (letzten) Mittelwert ausgeben oder in eine Variable zu packen? Aber da hörts bei mir auf mit perl...

Wie könnte man das elegant lösen?


Beste Grüße
// tetzlav

tetzlav

Soooo... ;)

Ich habe noch ein bisschen weiter gefrickelt und nun bin ich in der Lage einen Mittelwert, hier z.B. der Windgeschwindigkeit der letzten Stunde, über einen dummy in ein Logfile zu schreiben.
So schauen meine Definition in der fhem.cfg aus:

define KS300_W dummy
define KS300_W_notify notify KS300:wind.* {\
  my $period_s = strftime("%%Y-%%m-%%d\x5f%%H:%%M:%%S", localtime(time-3600));;\
  my $period_e = strftime("%%Y-%%m-%%d\x5f%%H:%%M:%%S", localtime);;\
  my @@logdata = split("\n", fhem("get FileLog_KS300 - - $period_s $period_e 8:::"));;\
  my ($cnt,$cum,$avg) = (0)x3;;\
  foreach (@@logdata){\
    my @@line = split(" ", $_);;\
    if("$line[1]" ne ""){\
      $cnt += 1;;\
      $cum += $line[1];;\
    }\
  }\
  if("$cnt" > 0){$avg = sprintf("%%0.1f", $cum/$cnt)}\
  Log 1, ("K300_W: von $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg");;\
  fhem('trigger KS300_W Wc: '.ReadingsVal("KS300","wind","0").' Wlh: '.$avg);;\
}
define FileLog_KS300_W FileLog ./log/KS300_W-%Y.log KS300_W.*
attr FileLog_KS300_W logtype text
attr FileLog_KS300_W room Logs


Jetzt wollte ich das auch gerne für andere Logs verwenden und eine eigene Funktion in 99_MyUlils.pm ablegen.
Meine 99_MyUlils.pm schaut erstmal angelehnt an obigen Code wie folgt aus:

package main;
use strict;
use warnings;
use POSIX;

sub
MyUtils_Initialize($$)
{
  my ($hash) = @_;
}

##########################################################
# myAverage
# berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum

sub
myAverage($$$)
{
  my ($offset,$logfile,$cspec) = @_;
  my $period_s = strftime("%Y-%m-%d\x5f%H:%M:%S", localtime(time-$offset));
  my $period_e = strftime("%Y-%m-%d\x5f%H:%M:%S", localtime);
  my @logdata = split("\n", {fhem("get $logfile - - $period_s $period_e $cspec")});
  open(DEBUG, ">>log/DEBUG.log");
  printf DEBUG "Logdata: %s\n", @logdata;
  close(DEBUG);
  my ($cnt,$cum,$avg) = (0)x3;
  foreach (@logdata){
    my @line = split(" ", $_);
    if("$line[1]" ne ""){
      $cnt += 1;
      $cum += $line[1];
    }
  }
  if("$cnt" > 0){$avg = sprintf("%0.1f", $cum/$cnt)};
  Log 1, ("myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg");
  return $avg;
}

1;


Jetzt habe ich nur das Problem, dass das Array @logdata leider leer bleibt. Das liegt vermutlich daran, dass ich den Aufruf von
fhem("get $logfile - - $period_s $period_e $cspec")
in {} packen muss und dann stimmt der Ausgabepfad nicht.

Generell würde ich ja lieber die Funktion FileLog_Get() aus 92_FileLog.pm direkt aufrufen, aber da scheitere ich an der hash-Tabelle und bin mit meinem perl am Ende...


Kann mir mal bitte jmd. auf die Sprünge helfen? :)
// tetzlav

Niko

Hallo tetzlav,

kannst Du noch mal posten wie Du die Routine aus FHEM aufrufst?

Viele Grüße
Niko

tetzlav

Hallo Nico,

Naja, vorerst zum testen vorerst über die fhem-telnet-Console. Z.B. so:
fhem> {myAverage("3600", "FileLog_KS300", "8:::")}
Odd number of elements in anonymous hash at ./FHEM/99_MyUtils.pm line 22.
1
fhem>

Als Rückgabewert würde ich den Durchschnittswert erwarten, wobei mir jetzt auch das erste mal diese Fehlermeldung untergekommen ist.
Kommt wohl darauf an, auf welcher Console der fhem-Server gestartet wurde...


Grüße

Niko

Hallo tetzlav,

zunächst einmal vorab, ich bin noch relativ neu hier, kenne mich also mit FHEM und Perl noch nicht so richtig gut aus. Gerade deshalb hat mich Deine Funktion aber interessiert, weil ich hier noch etwas lernen konnte.

Ich habe das Ganze über die FHEM Oberfläche probiert, also nicht wie Du über Telnet.

Hier gibt mir Dein Statement "my @logdata = split("\n", {fhem("get $logfile - - $period_s $period_e $cspec")});"

einen Wert / Verweis in der Art "HASH(0xbf7628)" zurück (Geprüft mit "foreach(@logdata) {Log 2, "$_";}.

Lasse ich die {} in Deinem Statement weg, also "my @logdata = split("\n", fhem("get $logfile - - $period_s $period_e $cspec"));"
bekomme ich die Werte und damit auch den Mittelwert.

Ich habe FHEM auf einer Fritzbox 7390 laufen.

Ich hoffe dies hilft Dir weiter.
Viele Grüße
Niko

tetzlav

Vielen Dank!
Die geschweiften Klammern waren das Problem. Ich dachte die sind notwendig und ich war der Meinung es auch ohne getestet zu haben.
Naja, wie auch immer, es funktioniert jetzt bestens.

Dokumentiert habe ich meine Funktion und Vorhaben im Wiki.


Grüße
// tetzlav

Johannes

Hallo tetzlav,

Es kommt vermutlich etwas spät, aber vielleicht hilft dir in Zukunft das hier weiter:
Link

Grüße,
Johannes

oniT

Hallo,

ich habe den Code myAverage() von tetzlav in die 99_myUtils.pm angelegt und bin soweit begeistert. Allerdings wird mir bei jeder Ausführung das Logfile mit allen Werten aus der Logdatei vollgeschrieben.


2013-06-02_17:59:36 14::: : 2013-06-02_17:00:03 23.5
2013.06.02 17:59:36 3: get A_WaermepumpeLog - - 2013-06-02_16:59:36
2013-06-02_17:00:33 23.5
2013-06-02_17:01:03 23.5
2013-06-02_17:01:33 23.5
2013-06-02_17:02:03 23.5
2013-06-02_17:02:33 23.5
2013-06-02_17:03:03 23.5
..............



package main;
use strict;
use warnings;
use POSIX;
sub
MyUtils_Initialize($$)
{
 my ($hash) = @_;
}
##########################################################
# myAverage
# berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum
sub
myAverage($$$)
{
 my ($offset,$logfile,$cspec) = @_;
 my $period_s = strftime "%Y-%m-%d\x5f%H:%M:%S", localtime(time-$offset);
 my $period_e = strftime "%Y-%m-%d\x5f%H:%M:%S", localtime;
 my @logdata = split("\n", fhem("get $logfile - - $period_s $period_e $cspec"));
 my ($cnt, $cum, $avg) = (0)x3;
 foreach (@logdata){
  my @line = split(" ", $_);
  if(defined $line[1] && "$line[1]" ne ""){
   $cnt += 1;
   $cum += $line[1];
  }
 }
 if("$cnt" > 0){$avg = sprintf("%0.1f", $cum/$cnt)};
 Log 4, ("myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg");
 return $avg;
}
##########################################################
1;

Jetzt dachte ich mir, wenn man diese Zeile entnimmt:

 Log 4, ("myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg");

bleiben die Einträge dann weg. Tut es aber nicht. Ich gehe jetzt davon aus, es kommt von der Zeile:

fhem("get $logfile - - $period_s $period_e $cspec")


Gibt es hier eine Möglichkeit, dass die Einträge im Logfile ausbleiben?

Danke

Gruß,
TinoB

BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

Puschel74

Hallo,

für mich als Laien sieht das

fhem("get $logfile - - $period_s $period_e $cspec")

so aus das fhem nur aus der Datei liest.

Hast du nach dem auskommentieren des Log 4,"( ...
mal ein reload der 99_myUtils.pm durchgeführt?

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

oniT

Hallo Puschel,

ja ein Reload hatte ich durchgeführt. Auch zur Vorsicht ein shutdown restart. Hat nichts gebracht. Habe dann auch mehrfach geprüft, dass der Eintrag auch wirklich entfernt ist, manchmal denkt man ja es hat nicht funktioniert ;-)

Für mich sieht es ebenfalls so aus, als werden die Daten nur mit

fhem("get $logfile - - $period_s $period_e $cspec")

gelesen. Und mit dem Log Eintrag in's Logfile geschrieben. Aber das Entfernen hat bisher nichts bewirkt.

Danke

Gruß,
TinoB
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

Puschel74

Hallo,

Auszug aus deinem Logfile-Post:

Zitat2013-06-02_17:59:36 14::: : 2013-06-02_17:00:03 23.5
2013.06.02 17:59:36 3: get A_WaermepumpeLog - - 2013-06-02_16:59:36

Wenn ich das richtig deute wird bei dir einmal ein Logeintrag mit
Log 14,(" ....") und einmal mit
Log 3,(" ....") erzeugt.
Bei ersterem kann ich mich täuschen da ich 14 noch nicht gesehen habe.
Bei zweiterem bin ich mir ziemlich sicher.

Poste mal bitte den Code mit dem du die Subroutine aufrufst.

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

oniT

Hallo Puschel,

hier mein Code zum Aufruf. Jede Stunde wird ein Mittelwert aus den Einträgen der letzten Stunde im Logfile ermittelt:

define h_mittelwert_aufruf at +*01:00:00 {\
 my $avg_h_at = myAverage("3600", "A_WaermepumpeLog", "4:::");;\
   fhem("set A_H_AVG_AT $avg_h_at °C");;\
 my $avg_h_rlt = myAverage("3600", "A_WaermepumpeLog", "6:::");;\
   fhem("set A_H_AVG_RLT $avg_h_rlt °C");;\
 my $avg_h_wwt = myAverage("3600", "A_WaermepumpeLog", "8:::");;\
   fhem("set A_H_AVG_WWT $avg_h_wwt °C");;\
 my $avg_h_vlt = myAverage("3600", "A_WaermepumpeLog", "10:::");;\
   fhem("set A_H_AVG_VLT $avg_h_vlt °C");;\
 my $avg_h_rt = myAverage("3600", "A_WaermepumpeLog", "12:::");;\
   fhem("set A_H_AVG_RT $avg_h_rt °C");;\
 my $avg_h_rls = myAverage("3600", "A_WaermepumpeLog", "14:::");;\
   fhem("set A_H_AVG_RLS $avg_h_rls °C");;\
  my $wert= "AT $avg_h_at RLT $avg_h_rlt WWT $avg_h_wwt VLT $avg_h_vlt RT $avg_h_rt RLS $avg_h_rls";;\
   fhem("trigger A_H_AVG $wert");;\
}

Die ermittelten Werte werden dann wiederum in ein eigens Logfile geschrieben.

Die 14 wie auch die 4, 6, 8, 10, 12 ist die Spalte aus dem Logeintrag wo der Wert zur Berechnung entnommen wird.

Danke

Gruß,
TinoB
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

Puschel74

Hallo,

fast wär ich drauf rein gefallen ;-)

Zitat2013-06-02_17:59:36 14::: : 2013-06-02_17:00:03 23.5
2013.06.02 17:59:36 3: get A_WaermepumpeLog - - 2013-06-02_16:59:36
2013-06-02_17:00:33 23.5
2013-06-02_17:01:03 23.5
2013-06-02_17:01:33 23.5
2013-06-02_17:02:03 23.5
2013-06-02_17:02:33 23.5
2013-06-02_17:03:03 23.5
Also die Zeitpunkte der Einträge sehen ja sehr eigenartig aus.
Erst um 17:59 und dann ab 17:00 aufwärts.

Welche Logeinträge stören dich den jetzt genau (und warum stören die)?

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

oniT

Hallo,

im Prinzip alle :-)

Also um 17:59:36 ist gerade eine Stunde um und da wird der Aufruf ausgeführt. Dann werden alle Einträge aus dem Logfile "A_WaermepumpeLog" der letzten Stunde (in diesem Beispiel von 16:59 bis 17:59) abgefragt und daraus der Mittelwert gebildet. Allerdings, und das ist das Problem, werden alle Werte aus dem gespeicherten Logfile "A_WaermepumpeLog" in das allgemeine fhem Logfile ebenfalls übernommen und aufgelistet. Was ja wiederum bedeutet, dass die Größe des Files bei jeder Abfrage zunimmt und das in diesem Fall jede Stunde. Das ist natürlich unschön und muss nicht sein.

Danke

Gruß,
TinoB
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

Puschel74

Hallo,

ZitatDas ist natürlich unschön und muss nicht sein.

Dem stimme ich dir zu - aber ich weiß dafür keine Lösung.

Versuch mal
attr global verbose 2
zu setzen.
Evtl. ist ja dann Ruhe (wobei die Logeinträge ja keine Nummer haben und daher evtl. nicht unterdrückt werden können).

Sorry, aber da bin ich mal aufgrund Unwissenheit leider raus (aber ich les noch mit weil ich gerne dazu lerne).

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.