FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: gestein am 18 Februar 2022, 13:05:03

Titel: Funktionsaufrufe im DEF-Block?
Beitrag von: gestein am 18 Februar 2022, 13:05:03
Hallo,

ich bräuchte bei meinem Projekt noch bitte ein paar Schubser in die richtige Richtung.

Soweit scheint mein DOIF zur Berechnung des Stromverbrauchs schon mal zu funktionieren.
Momentan noch sehr rudimentär mit etlichen Baustellen:
defmod di_counter DOIF DEF TPL_stat (midnight_$1_$2 { [00:00:05];;\
  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);;\
  }\
}\
\
hour_$1_$2 { [:00];;\
  set_Reading("$1_$2_hour_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_hour",get_Reading("$1_$2_hour",0),1);;\
  set_Reading("$1_$2_hour",0);;\
}\
\
quarter_$1_$2 { [+:15];;\
  set_Reading("$1_$2_quarter_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_quarter",get_Reading("$1_$2_quarter",0),1);;\
  set_Reading("$1_$2_quarter",0);;\
}\
\
update_counters_$1_$2 {\
##  Log 1, "update_counters_$1_$2: [?$1:$2];;".get_Reading("$1_$2_counter",0).";;".get_Reading("$1_$2_hour_counter",0).";;".get_Reading("$1_$2_quarter_counter",0);;\
  set_Reading("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;\
  set_Reading("$1_$2_hour",int(([$1:$2,0]-get_Reading("$1_$2_hour_counter",0))),1);;\
  set_Reading("$1_$2_quarter",int(([$1:$2,0]-get_Reading("$1_$2_quarter_counter",0))),1);;\
}\
\
init_$1_$2 {\
  if (!get_Reading("$1_$2_counter","")) {\
    set_Reading("$1_$2_quarter_counter",[?$1:$2]);;\
set_Reading("$1_$2_hour_counter",[?$1:$2]);;\
    set_Reading("$1_$2_counter",[?$1:$2]);;\
set_Reading ("$1_$2_quarter",0);;\
set_Reading ("$1_$2_hour",0);;\
    set_Reading ("$1_$2_day",0);;\
    set_Reading ("$1_$2_month",0);;\
    set_Reading ("$1_$2_year",0);;\
set_Reading ("$1_$2_last_quarter",0);;\
set_Reading ("$1_$2_last_hour",0);;\
set_Reading ("$1_$2_last_day",0);;\
    set_Reading ("$1_$2_last_month",0);;\
    set_Reading ("$1_$2_last_year",0);;\
set_Reading ("last_quarter_sum",0);;\
set_Reading ("last_hour_sum",0);;\
set_Reading ("last_day_sum",0);;\
  } \
}\
)\
CalculateSums {\
  my $Reading=::AttrVal("$SELF","EnergyReading","");;\
  my $Prefix=::AttrVal("$SELF","SummaryPrefix","");;\
\
##  my $readings = $::defs{$d}->{READINGS};;\
  my @Categories=split /,/, ::AttrVal("$SELF","SummaryList","");;\
\
  if (@Categories > 0) {\
    foreach my $Category (@Categories) {\
  my ($Name,$Filter)=split /;;/, $Category;;\
  my @Devices = ::devspec2array($Filter);;\
      my $counter_temp=0;;\
      my $hour_temp=0;;\
      my $hour_counter_temp=0;;\
      my $quarter_temp=0;;\
      my $quarter_counter_temp=0;;\
\
      foreach my $Device (@Devices) {\
        $counter_temp+=get_Reading("$Device\_$Reading\_counter",0);;\
        $hour_temp+=get_Reading("$Device\_$Reading\_hour",0);;\
        $hour_counter_temp+=get_Reading("$Device\_$Reading\_hour_counter",0);;\
        $quarter_temp+=get_Reading("$Device\_$Reading\_quarter",0);;\
        $quarter_counter_temp+=get_Reading("$Device\_$Reading\_quarter_counter",0);;\
  }\
      set_Reading($Prefix."$Name\_counter",$counter_temp);;\
      set_Reading($Prefix."$Name\_hour",$hour_temp);;\
      set_Reading($Prefix."$Name\_hour_counter",$hour_counter_temp);;\
      set_Reading($Prefix."$Name\_quarter",$quarter_temp);;\
      set_Reading($Prefix."$Name\_quarter_counter",$quarter_counter_temp);;\
##foreach my $readingname (keys %{$hash->{READINGS}}) { \
## loop über readings mit $readingname zur Weiterverarbeitung\
##  }\
  }\
  }\
}\
\
##https://forum.fhem.de/index.php/topic,84969.msg1208710.html#msg1208710\
CalculateQuarterSums { [([+:15]+[00:01])];;\
set_Reading("Summary_Total_last_quarter_sum",[?#sum:"^$SELF$":"last_quarter$"]);;\
CalculateSums();;\
}\
CalculateHourSums { [:01];;\
set_Reading("Summary_Total_last_hour_sum",[?#sum:"^$SELF$":"last_hour$"]);;\
CalculateSums();;\
}\
\
FOR(::devspec2array("MQTT2_shelly.*:FILTER=group=Haushaltsgeräte"), TPL_stat ($_,energy_total))\
##FOR(::devspec2array("MQTT2_shelly.*:FILTER=group=Haushaltsgeräte"), TPL_stat ($_,::AttrVal("$SELF","EnergyReading","energy")))\
##TPL_stat (MQTT2_shellyswitch25_E098068CF1A1,energy_total)\
##TPL_stat (MQTT2_shellyswitch25_E098068CF1A1_CH2,energy_total)
attr di_counter userattr SummaryList SummaryPrefix EnergyReading
attr di_counter EnergyReading energy_total
attr di_counter SummaryList Wohnzimmer;;room=Wohnzimmer,Schlafzimmer;;room=Schlafzimmer,Badezimmer;;room=Badezimmer,Vorzimmer;;room=Vorzimmer,Kueche;;room=Küche,Haushaltsgeraete;;group=Haushaltsgeräte
attr di_counter SummaryPrefix Summary_
attr di_counter comment https://forum.fhem.de/index.php/topic,126199.msg1208225.html#msg1208225
attr di_counter room Verbrauch
attr di_counter uiTable {package ui_Table;;}\
\
card([[MQTT2_shelly1pm_8CAAB50568DC:relay_0_power:144col1d]],"Leistung in kW","fa_bolt\@silver",-3.6,3.6,0,90,["Solar","Netz"],[(-1,0,-0.01,30,1,60,3.6,90)],"2","130,,1,0,1,0","1,,1,0,1")|\
card([[$SELF:MQTT2_shelly1pm_8CAAB50568DC_relay_0_power_day:col1w]],"Energie in kWh pro Tag","fa_bolt\@silver",-20,20,0,90,["Ertrag","Bezug"],undef,"1","130,,1,0,1","0,0,0,0,2")|\
card([[$SELF:MQTT2_shelly1pm_8CAAB50568DC_relay_0_power_month:col365d]],"Energie in kWh pro Monat","fa_bolt\@silver",-300,600,0,90,["Ertrag","Bezug"],undef,"1","130,,1,0,1","0,0,0,0,2")


Folgendes klappt noch nicht:
- Aufruf einer Subroutine (in dem Fall "CalculateSums ") aus einer anderen heraus (z.B. "CalculateQuarterSums").
  Ich bekomme immer den Fehler: "block_CalculateHourSums; condition c03: Undefined subroutine &DOIF::CalculateSums called, line 3."
- ich würde gerne beim Erstellen der Instanzen der Templates den Wert eines Attributs übergeben.
  Wie muss ich "::AttrVal" angeben?

Danke für die vielen Hilfe bisher und natürlich im Voraus
lg, Gerhard
Titel: Antw:Funktionsaufrufe im DEF-Block?
Beitrag von: Damian am 18 Februar 2022, 13:28:41
CalculateSums {...

ist keine sub-Routine, sondern ein DOIF-Block.

Den kann man mit dem FHEM-Befehl set <DOIF-Device> <blockname> ausführen.

Besser wäre es, eine echte Perl-Sub-Routine im Block subs zu erstellen. Und die wiederum aufrufen:

subs {

sub mysub {...}

}

CalculateSums { mysub ([$1:$2],...)}

mysub kann man dann auch gesondert aufrufen. Zu bedenken ist, dass Perl-Routinen keine DOIF-spezifische Syntax kennen, die muss man beim Aufruf, wegen der notwendigen Trigger angeben (wie im Beispiel).