Autor Thema: neue Features: ereignisgesteuertes Perl - DOIF-Perl  (Gelesen 71555 mal)

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #240 am: 09 Februar 2022, 18:09:27 »
Neue Version wurde eingecheckt.

Ich habe im Perlmodus die Option eingebaut, dass man mehrere init-Blöcke definieren kann. Ein init-Block wird automatisch beim Hochfahren des Systems ausgeführt oder unmittelbar nach der Definition eines DOIF-Devices. Damit lassen sich Templates erstellen, die alle einen eigenen init-Block brauchen.

D.h. wenn ein Block init heißt oder neuerdings mit init_ beginnt, so wird er wie ober beschrieben zusätzlich ausgeführt.

Hier ein Beispiel mit dem neuen Feature, wie man bei einem fortlaufenden Zähler, wie bei Strom, Wasser, Gas eine Tages-, Monats- und Jahresstatistik erstellen kann (die vorhanden Module zu dem Thema haben mir nicht zugesagt).


defmod di_counter DOIF DEF TPL_stat (midnight_$1_$2 { [00:01];;\
  set_Reading("$1_$2_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_day",get_Reading("$1_$2_day",0),1);;\
  set_Reading("$1_$2_day",0,1);;\
  set_Reading("$1_$2_month",get_Reading("$1_$2_month",0)+get_Reading("$1_$2_last_day",0),1);;\
  if ($mday == 1) {\
    set_Reading("$1_$2_last_month",get_Reading("$1_$2_month",0),1);;\
    set_Reading("$1_$2_month",0,1);;\
    set_Reading("$1_$2_year",get_Reading("$1_$2_year",0)+get_Reading("$1_$2_last_month",0),1);;\
  }\
  if ($yday == 1) {\
    set_Reading("$1_$2_last_year",get_Reading("$1_$2_year",0),1);;\
    set_Reading("$1_$2_year",0,1);;\
  }\
}\
\
day_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}\
\
init_$1_$2 {\
  set_Reading("$1_$2_counter",[?$1:$2]) if (!get_Reading("$1_$2_counter",""));;\
}\
\
)\
TPL_stat (Stromzaehler,total_c)\
TPL_stat (Stromzaehler,total_f)\
TPL_stat (CUL_WZ,total)


Ein Zähler wird einfach mit TPL_stat (<device>,<reading>) angegeben. Im obigen Beispiel wurden drei Zähler definiert.

Damit kann man Tages-, Monats- oder Jahres-Verbräuche loggen oder in card darstellen, siehe Anhang:

« Letzte Änderung: 09 Februar 2022, 18:24:35 von Damian »
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline gestein

  • Hero Member
  • *****
  • Beiträge: 1277
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #241 am: 16 Februar 2022, 00:31:29 »
Hallo Damian,

Danke für Dein Template für den Stromzähler.
Schön langsam verstehe ich wie das funktioniert.

Wann wird allerdings das Reading "$1_$2_day" gesetzt?
Ich weiß schon, in der Funktion „day_count_$1_$2“.
Aber wer ruft die wann auf?

Danke, Lg, Gerhard

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #242 am: 16 Februar 2022, 07:39:26 »
Hallo Damian,

Danke für Dein Template für den Stromzähler.
Schön langsam verstehe ich wie das funktioniert.

Wann wird allerdings das Reading "$1_$2_day" gesetzt?
Ich weiß schon, in der Funktion „day_count_$1_$2“.
Aber wer ruft die wann auf?

Danke, Lg, Gerhard

Zitat
day_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}

Der Trigger ist also ein Event von $1=Device $2=Reading
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline gestein

  • Hero Member
  • *****
  • Beiträge: 1277
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #243 am: 16 Februar 2022, 09:35:50 »
Verstehe. Danke. Ganz schön komplex ...

Diese Schreibweise wäre also die kürzere Version von:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
}
Richtig?

Und wenn ich den Wert von "[?$1:$2]" in dieser Funktion mehrmals benötige, wie soll man dann am besten die Funktion schreiben?
z.B.:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}
oder besser so:
day_count_$1_$2 {
   set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}

Danke für Deine Geduld.
lg, Gerhard

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #244 am: 16 Februar 2022, 09:43:34 »
Verstehe. Danke. Ganz schön komplex ...

Diese Schreibweise wäre also die kürzere Version von:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
}
Richtig?
im Prinzip ja, da fehlt noch ein Semikolon hinter [$1:$2]. Da der Trigger überall im Block stehen kann, muss man den nicht gesondert angeben.
Zitat
Und wenn ich den Wert von "[?$1:$2]" in dieser Funktion mehrmals benötige, wie soll man dann am besten die Funktion schreiben?
z.B.:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}
oder besser so:
day_count_$1_$2 {
   set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}
Das ist egal, DOIF erkennt, dass es sich um den gleichen Trigger handelt, deswegen wird der Block nur einmal getriggert, egal wie oft du [$1:$2] innerhalb eines Blocks angibst.
« Letzte Änderung: 16 Februar 2022, 09:45:32 von Damian »
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline gestein

  • Hero Member
  • *****
  • Beiträge: 1277
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #245 am: 16 Februar 2022, 20:28:43 »
Danke, Damian.
So weit funktioniert das schon mal.
Ich hatte lange den Fehler gesucht, warum auf die Readings "energy" in den Shellys nicht im DOIF getriggert wird.
Ein "event-on-change" an der richtigen Stelle mit dem richtigen Wert hilft da ungemein ;)

Nun muss ich die Summen über Räume, Gruppen etc. machen.

Ist es eigentlich möglich eine Perl-Funktion ausserhalb des Templates zu definieren, die dann aus den Instanzen aufgerufen wird?
Diese Summen-Funktion soll ja nicht in jeder Instanz des Templates definiert sein.

Kann man eigentlich auf die Änderung eines Attributes des DOIF mit einem Funktionsaufruf reagieren?
Oder muss die Liste der zu bildenden Gruppen in einem Reading stehen?

Danke im Voraus
lg, Gerhard

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #246 am: 16 Februar 2022, 20:49:33 »
Natürlich kannst du eine Perlfunktion in myUtils ablegen und diese aufrufen. Am besten davor noch package DOIF; angeben, damit sie direkt angegeben werden kann, sonst musst du :: vor die Funktion setzen, da sie sich sonst im package main befindet.

Du könntest für jede Gruppe ein DOIF erstellen und das gleiche Template per IMPORT-Befehl importieren.

Dann könntest du im Template die gleiche Aggregationsfunktion nutzen, die alle Readings des gleichen Typs wie last_day oder last_month addiert.

Das Reagieren auf Attributänderungen sollte über ein global-Event funktionieren. Musst du im Eventmonitor nachschauen, wenn sich ein Attribut ändert.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline gestein

  • Hero Member
  • *****
  • Beiträge: 1277
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #247 am: 16 Februar 2022, 21:40:44 »
Verstehe. Das sollte so klappen. Danke.

Prinzipiell wäre es aber auch möglich die Funktion im DOIF zu behalten und nicht ins 99_myUtils auszulagern.
Dann müsste ich sie in den uiTable-Teil geben. Oder?
Irgendwie habe ich gerne alles beisammen.

Kann man die Funktion dann aus den Instanzen der Templates heraus aufrufen?

Lg, Gerhard
« Letzte Änderung: 16 Februar 2022, 21:42:54 von gestein »

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #248 am: 16 Februar 2022, 21:55:59 »
Verstehe. Das sollte so klappen. Danke.

Prinzipiell wäre es aber auch möglich die Funktion im DOIF zu behalten und nicht ins 99_myUtils auszulagern.
Dann müsste ich sie in den uiTable-Teil geben. Oder?
Irgendwie habe ich gerne alles beisammen.

Kann man die Funktion dann aus den Instanzen der Templates heraus aufrufen?

Lg, Gerhard

Eigene Funktionen im Block subs befinden sich im package DOIF und müssten in uiTable mit DOIF:: beginnen. Allerdings nutzen alle DOIF-Devices das gleiche package DOIF.

Wenn es um die Summation geht. Dafür reicht ja eine Zeile, wie ich sie dir bereits über die Aggregation aufgezeigt habe, dafür braucht man keine Funktion zu definieren.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #249 am: 16 Februar 2022, 22:14:09 »
So könnte das Codeschnipsel um einen sum-Block erweitert werden, der nach Mitternacht entsprechende Readings des DOIF-Devices zusammenaddiert.

defmod di_zaehler DOIF DEF TPL_stat (midnight_$1_$2 { [00:01];;\
  set_Reading("$1_$2_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_day",get_Reading("$1_$2_day",0),1);;\
  set_Reading("$1_$2_day",0,1);;\
  set_Reading("$1_$2_month",get_Reading("$1_$2_month",0)+get_Reading("$1_$2_last_day",0),1);;\
  \
  if ($mday == 1) {\
    set_Reading("$1_$2_last_month",get_Reading("$1_$2_month",0),1);;\
    set_Reading("$1_$2_month",0,1);;\
    set_Reading("$1_$2_year",get_Reading("$1_$2_year",0)+get_Reading("$1_$2_last_month",0),1);;\
  }\
  if ($yday == 1) {\
    set_Reading("$1_$2_last_year",get_Reading("$1_$2_year",0),1);;\
    set_Reading("$1_$2_year",0,1);;\
  }\
}\
\
day_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}\
\
init_$1_$2 {\
  set_Reading("$1_$2_counter",[?$1:$2]) if (!get_Reading("$1_$2_counter",""));;\
  #set_Reading ("$1_$2_day",0);;\
  #set_Reading ("$1_$2_last_day",0);;\
  #set_Reading ("$1_$2_last_month",0);;\
  #set_Reading ("$1_$2_last_year",0);;\
}\
)\
\
sum {[00:02];;set_Reading("last_day_sum",[?#sum:"^$SELF$":"last_day$"],1);;\
  if ($mday == 1) {\
    set_Reading("last_month_sum",[?#sum:"^$SELF$":"last_month$"],1);;\
  }\
  if ($yday == 1) {\
    set_Reading("last_year_sum",[?#sum:"^$SELF$":"last_year$"],1);;\
  }\
}\
TPL_stat (test,state)\
TPL_stat (test,r1)\
TPL_stat (test,r2)
« Letzte Änderung: 16 Februar 2022, 22:17:54 von Damian »
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline gestein

  • Hero Member
  • *****
  • Beiträge: 1277
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #250 am: 16 Februar 2022, 22:17:44 »
Das wollte ich gerade fragen.
Wie immer bist Du schnell, diesmal sogar die Antwort bevor ich die Frage stellen konnte  ;)

Lg, Gerhard

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
« Letzte Änderung: 18 Februar 2022, 18:37:15 von Damian »
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #252 am: 20 Februar 2022, 10:25:20 »
Neue Version wurde eingecheckt: Nun werden die gesammelten Daten für card nicht gelöscht, wenn man die Definition per defmod ändert. So kann die Definition erweitert werden, ohne dass Datenverläufe in bestehenden cards verloren gehen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #253 am: 01 März 2022, 13:19:26 »
Energie wird nun teuer, da lohnt sich eine Analyse des eigenen Verbrauchs.

Der Wikieintrag zu dem Thema wurde aktualisiert:

https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Offline Damian

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 10148
Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
« Antwort #254 am: 07 März 2022, 16:29:03 »
Energie wird nun teuer, da lohnt sich eine Analyse des eigenen Verbrauchs.

Der Wikieintrag zu dem Thema wurde aktualisiert:

https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler

Ich habe den Code weiter verfeinert.
Dieser funktioniert nun auch, wenn der Zähler seinen aktuellen Zählerstand verliert, wie z. B. beim ESP8266.
Es werden jetzt zusätzlich automatisch Logs für Tages-, Monats- und Jahresverbräuche erzeugt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

 

decade-submarginal