Autor Thema: Korrekte Syntax FHEM-Befehl in Perl im ...notify... in myUtils auslagern  (Gelesen 20993 mal)

Offline TomLee

  • Hero Member
  • *****
  • Beiträge: 4148
  • ... wer sät, der erntet ...
Das mit der Definition des Hash %data hab ich gestern abend schon gelesen, aber nicht verstanden wo der genau definiert werden soll, in Initialize ?

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 18359
Na ja, ich würde behaupten, dass die Wiki-Seite schlicht nicht funktioniert, weil die Variable (nur) im lexikalischen Initialize-Kontext existiert. Sie müßte nach meinem möglicherweise begrenzten Verständnis "eine Ebene höher" deklariert sein - was aber m.E. Mist ist, weil man damit direkt im main-Namespace rumschreibt.

Kannst dasselbe ja mal mit
$data->{NewMailtime} = time;versuchen zu coden (und gleich das Wiki verbessern, wenn es läuft wie gewünscht).

Nach meinem Verständnis ist der Hash %data etwas, das fhem.pl direkt zur Verfügung stellt, und du kannst darin dann eben beliebige eigene Keys ablegen (s.o.). Wie immer, muss man dann halt nur aufpassen, dass man keine (unbewußten) Überschneidungen mit was anderem hat.
EDIT: siehe https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L254:
use vars qw(%data);             # Hash for user data
Wobei mir für sowas immer Benni's globale Fenster-Offen-Lösung einfällt (ist auch dort verlinkt)...
« Letzte Änderung: 17 März 2021, 12:37:01 von Beta-User »
Server: HP-T620@Debian 11, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Offline TomLee

  • Hero Member
  • *****
  • Beiträge: 4148
  • ... wer sät, der erntet ...
Habs denk ich, so wär die Variable global verfügbar :

Korrekt ?

Es hat keiner was dazu gesagt, schätze dann spricht nichts dagegen es so umzusetzen in der ersten sub alle weiteren zu deklarieren das die Variablen in jeder sub verfügbar sind,es bleibt aber irgendwie ein ungutes Gefühl.

Ich hab heute unverhofft die Abfall-userreadings meines Abfallkalender nach dem hier erworbenen Wissen ausgelagert.

Es klappt alles, es gibt keine Probleme, keine Meldungen im Log, aber wie gesagt ist da noch das ungute Gefühl, kann sich das wer bitte anschauen und bestätigen das es so auch wirklich korrekt umgesetzt ist ?

vorher:

attr cal_Abfallkalender userReadings nextWastedays:lastUpdate:.* {\
my $var1 = fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1);;\
my $var2 =int(($var1 + 86399 - time) / 86400);;\
return $var2},\
nextWaste:lastUpdate:.* {my $var1 =fhem('get '.$name.' events format:custom="$S" limit:from=0,count=1',1);;\
my $var2 =int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400);;\
my @tonne = split (/ /,$var1);;\
my $nwd = "$tonne[1]"."_"."$var2";;\
return $nwd},\
nextWast:lastUpdate:.* {my $var1 =fhem('get '.$name.' events format:custom="$S" limit:from=0,count=1',1);;\
my @tonne = split (/ /,$var1);;\
return $tonne[1]},\
nextWastedate:lastUpdate:.* { \
my $date = fhem('get '.$name.' events format:custom="$T1" limit:from=0,count=1');;\
my @dat = split (/ /,$date);;\
return $dat[0];;\
},\
ftui-hide:lastUpdate:.* {my $var = ReadingsVal($name,"nextWast","0") =~ "Restabfall/Wertstoffe|Bioabfall"?"1":"0";;return $var}

nachher:

attr cal_Abfallkalender userReadings nextWastedays:lastUpdate:.* {nwd($NAME)},\
nextWaste_ftui:lastUpdate:.* {nwf($NAME)},\
nextWaste:lastUpdate:.* {nw($NAME)},\
nextWastedate:lastUpdate:.* {nwda($NAME)},\
ftui-hide:lastUpdate:.* {fh($NAME)}

nachher:

package main;

use strict;
use warnings;
use POSIX;

sub Abfall_myUtils_Initialize {
  my $hash = shift//return;
  return;
}

# Enter you functions below _this_ line.
sub nwd {
my $NAME = shift;
my $var1 = int((fhem('get '.$NAME.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400);
my $var2 = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=1',1);
my $var3 = ReadingsVal($NAME,"nextWaste","0") =~ "Restabfall/Wertstoffe|Bioabfall"?"1":"0";
my $var4 = fhem('get '.$NAME.' events format:custom="$T1" limit:from=0,count=1',1);
my @tonne = split (/ /,$var2);
my $nwd = "$tonne[1]"."_"."$var1";
my @dat = split (/ /,$var4);

return $var1;

sub nwf {return $nwd;}
sub nw {return $tonne[1];}
sub nwda {return $dat[0];}
sub fh {return $var3;}
}
1;
« Letzte Änderung: 26 März 2021, 15:13:17 von TomLee »

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 18359
Es hat keiner was dazu gesagt, schätze dann spricht nichts dagegen es so umzusetzen in der ersten sub alle weiteren zu deklarieren das die Variablen in jeder sub verfügbar sind,es bleibt aber irgendwie ein ungutes Gefühl.
M.E. ist es so nicht richtig. Grundsätzlich leben alle Variablen nur im selben lexikalischen Kontext, in dem sie stehen, die große Ausnahme sind diese Subs...

Aber das ist "dreckiger Code" und wird direkt von Perlcritic (zurecht!) verrissen.

Kurze "anonyme" Funktionsnamen in $main sind m.E. auch was, was man vermeiden sollte; wenn es da kracht, wirst du die nie mehr wiederfinden (ausgenommen, stacktrace hilft). Das darfst du gerne machen, wenn du das in ein package packst, aber eben (m.E.) nicht in main.

Und "use POSIX;" ist immer noch ein nogo! (Weg damit an der Stelle. Es ist völlig "ausreichend", dass das (um Rudi zu zitieren: leider so pauschal) in fhem.pl steht, aber (falls es je in fhem.pl mal rausfliegen sollte:) man importiert sich damit (nochmal) "alles mögliche", ohne näher nachgedacht zu haben, ob man es braucht.

Und was die subs überhaupt machen sollen, habe ich auch nicht verstanden (aber auch nicht im Detail versucht zu verstehen).
Server: HP-T620@Debian 11, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Offline TomLee

  • Hero Member
  • *****
  • Beiträge: 4148
  • ... wer sät, der erntet ...
Zitat
M.E. ist es so nicht richtig. Grundsätzlich leben alle Variablen nur im selben lexikalischen Kontext, in dem sie stehen,

Naja, darum ja auch die Frage aus 101 ob das so korrekt sei, weil durch ausprobieren hatte ich festgestellt das die Variablen nicht nur im lexikalischen Kontext leben, deshalb hab ich es wie jetzt gezeigt umgesetzt, meine beabsichtigten Readings werden schließlich erstellt, wie gesagt ohne Meldungen im Log.

Zitat
die große Ausnahme sind diese Subs...

Komm nicht mit wie das gemeint ist.

Zitat
Aber das ist "dreckiger Code" und wird direkt von Perlcritic (zurecht!) verrissen.

Wie schon erwähnt hab ich das mit %hash noch nicht begriffen, ich wüsste nicht wie ich es umsetzen kann ohne das ich bspw. die Variable mit dem Inhalt
int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400)zweimal definieren muss, nämlich in jeder sub (hier in zweien dann) einmal in der ich den Inhalt benötige und auf das war ich aus mir zu sparen, zweimal die gleiche Definition einer Variablen in einer myUtils.

Zitat
Kurze "anonyme" Funktionsnamen in $main sind m.E. auch was, was man vermeiden sollte; wenn es da kracht, wirst du die nie mehr wiederfinden (ausgenommen, stacktrace hilft). Das darfst du gerne machen, wenn du das in ein package packst, aber eben (m.E.) nicht in main.

Steh ich auf dem Schlauch wie das gemeint ist, hab wohl noch viel zu lernen.

Zitat
Und "use POSIX;" ist immer noch ein nogo! (Weg damit an der Stelle. Es ist völlig "ausreichend", dass das (um Rudi zu zitieren: leider so pauschal) in fhem.pl steht, aber (falls es je in fhem.pl mal rausfliegen sollte:) man importiert sich damit (nochmal) "alles mögliche", ohne näher nachgedacht zu haben, ob man es braucht.

Das use POSIX;, seh ich jetzt, ist gestern erst aus der Beispiel-Datei entfernt worden, an was soll ich mich orientieren, mit wenig Programmierkenntnissen, wenn nicht an der, hab ich jetzt rausgenommen.

Zitat
Und was die subs überhaupt machen sollen, habe ich auch nicht verstanden (aber auch nicht im Detail versucht zu verstehen).

Naja, was soll ich dazu jetzt sagen, wenn sie genau das machen was ich will, sie erstellen mir meine userReadings wie ich es vorhatte.

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 18359
Naja, darum ja auch die Frage aus 101 ob das so korrekt sei, weil durch ausprobieren hatte ich festgestellt das die Variablen nicht nur im lexikalischen Kontext leben, deshalb hab ich es wie jetzt gezeigt umgesetzt, meine beabsichtigten Readings werden schließlich erstellt, wie gesagt ohne Meldungen im Log.

Komm nicht mit wie das gemeint ist.
Will sagen: Normalerweise geht das nicht, aber eben mit subs ausnamsweise schon. Aber das ist kein "guter" Code, jedenfalls nach der Auffassung der in "Perlcritic" enthaltenen formalisierten Analyse. Wenn man also nicht genau weiß, was man tut, sollte man solche Konstruktionen nicht bauen, selbst, wenn sie funktionieren.

Zitat
Wie schon erwähnt hab ich das mit %hash noch nicht begriffen, ich wüsste nicht wie ich es umsetzen kann ohne das ich bspw. die Variable mit dem Inhalt
int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400)
Für Code ist %data mAn. nicht der passende Ort.
Dafür gibt es myUtils und die generelle Leitlinie, dass man eigenen Code so kennzeichnen (benennen) sollte, dass man auch im Fehlerfall schnell findet, woran es gehapert hat (empfehle, myUtils tendenziell auch mit "my..." zu belabeln.)

DENN: Funktionsnamen müssen eindeutig sein, die neuere Definition überschreibt die ältere, deswegen findet man auch entsprechende Meldungen im Log, wenn man z.B. eine myUtils-Datei editiert hat. Das kann aber auch Datei- und Modulübergreifend passieren, weswegen es in nicht gepackagten Modulen Usus ist, den Modulnamen vor die Funktion zu schreiben.
Falls nicht klar ist, wie das gemeint ist, schau dir die devStateIcon an, die Color benutzen. Da steht der package-Name davor...

Zitat
Das use POSIX;, seh ich jetzt, ist gestern [...]
Das war evtl. gestern vor einem Jahr :P ...
Server: HP-T620@Debian 11, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Offline TomLee

  • Hero Member
  • *****
  • Beiträge: 4148
  • ... wer sät, der erntet ...
Also keine Spirenzien machen, $Name in jeder sub übergeben und die eine Variable die ich erwähnt habe halt zweimal in der myUtils definieren ?

use strict;
use warnings;

sub Abfall_Utils_Initialize {
  my $hash = shift//return;
  return;
}

# Enter you functions below _this_ line.

sub au_nwd {
my $NAME = shift;
my $var1 = int((fhem('get '.$NAME.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400);
return $var1;
}

sub au_nwf {
my $NAME = shift;
my $var1 = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=1',1);
my $var2 = int((fhem('get '.$NAME.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time) / 86400);
my @tonne = split (/ /,$var1);
my $nwd = "$tonne[1]"."_"."$var2";
return $nwd;
}

sub au_nw {
my $NAME = shift;
my $var1 = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=1',1);
my @tonne = split (/ /,$var1);
return $tonne[1];
}

sub au_nwda {
my $NAME = shift;
my $var1 = fhem('get '.$NAME.' events format:custom="$T1" limit:from=0,count=1',1);
my @dat = split (/ /,$var1);
return $dat[0];
}

sub au_fh {
my $NAME = shift;
my $var1 = ReadingsVal($NAME,"nextWaste","0") =~ "Restabfall/Wertstoffe|Bioabfall"?"1":"0";
return $var1;
}

1;
« Letzte Änderung: 27 März 2021, 12:30:57 von TomLee »

Offline frober

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 1107
  • Was man nicht kann, kann man lernen...
Da ich gerade mitlesen, wäre es verkehrt/ungünstig die sub einmal aufzurufen und mit setReading die Werte zu setzen?
Raspi 3b mit Raspbian Stretch und relativ aktuellem Fhem,  FS20, LGW, PCA301, MySensors mit RS485(CAN-Receiver), etc.,
einiges umgesetzt, vieles in Planung :-)

********************************************
...man wächst mit der Herausforderung...

Offline TomLee

  • Hero Member
  • *****
  • Beiträge: 4148
  • ... wer sät, der erntet ...
setreading wollte ich vermeiden, aber wenns "richtiger" ist, lass ich mich auch davon überzeugen.
Zu setreading auf das selbe Device in userReadings gibts diesen Thread.
Gerade die Tage gelesen aber gestern Abend nicht dran gedacht.
« Letzte Änderung: 27 März 2021, 08:21:49 von TomLee »

Offline frober

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 1107
  • Was man nicht kann, kann man lernen...
setreading wollte ich vermeiden, aber wenns "richtiger" ist, lass ich mich auch davon überzeugen.
Das müssen andere beantworten.

Du springst 5x von Fhem nach Perl und wieder zurück. Ich habe schon mehrfach gelesen, wo so etwas bemängelt wurde.
Ich lerne aber auch noch...
Raspi 3b mit Raspbian Stretch und relativ aktuellem Fhem,  FS20, LGW, PCA301, MySensors mit RS485(CAN-Receiver), etc.,
einiges umgesetzt, vieles in Planung :-)

********************************************
...man wächst mit der Herausforderung...

Offline hydrotec

  • Full Member
  • ***
  • Beiträge: 132
Da kommen Erinnerungen auf  ;)
99_myUtils_calendar - Perl Code

Schöne Grüße an alle, und Danke noch einmal.
Der Code läuft bis heute noch  :D

Gruß, Karsten

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 18359
Also keine Spirenzien machen, $Name in jeder sub übergeben und die eine Variable die ich erwähnt habe halt zweimal in der myUtils definieren ?
Klingt für mich besser.

Das setreading-nogo in userReadings habt ihr ja gefunden.

Vielleicht nochmal eine Anmerkung zu eine sub vs. viele: Grundsätzlich ist es m.E. effizienter, als Reaktion auf ein Event eine sub aufzurufen und darin dann alles zu erledigen, was man z.B. aus einem notify raus erledigen will, und das nicht auf mehrere notify zu verteilen. Die Krux hier ist allerdings, dass der Kontext eben userReadings ist, und da sind das  eigentlich eben schon subs innerhalb dieses "globalen" userReadings-Aufrufs => hier klappt das nicht in der Form, weil eine bestimmte Rückgabe erwartet wird, und "normale" Funktionen unterbunden werden.
Server: HP-T620@Debian 11, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Offline frober

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 1107
  • Was man nicht kann, kann man lernen...
Das setreading-nogo in userReadings habt ihr ja gefunden.

Vielleicht nochmal eine Anmerkung zu eine sub vs. viele: Grundsätzlich ist es m.E. effizienter, als Reaktion auf ein Event eine sub aufzurufen und darin dann alles zu erledigen, was man z.B. aus einem notify raus erledigen will, und das nicht auf mehrere notify zu verteilen. Die Krux hier ist allerdings, dass der Kontext eben userReadings ist, und da sind das  eigentlich eben schon subs innerhalb dieses "globalen" userReadings-Aufrufs => hier klappt das nicht in der Form, weil eine bestimmte Rückgabe erwartet wird, und "normale" Funktionen unterbunden werden.

Ich muss nochmal nachfragen:

Da hier 5 mal der gleiche Trigger benutzt wird, könnte man doch 4 mal die Werte mit setreading setzen und den 5. per return ans userReading liefern.
Oder spricht dagegen auch noch etwas?
Raspi 3b mit Raspbian Stretch und relativ aktuellem Fhem,  FS20, LGW, PCA301, MySensors mit RS485(CAN-Receiver), etc.,
einiges umgesetzt, vieles in Planung :-)

********************************************
...man wächst mit der Herausforderung...

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 18359
Da spricht m.E. dagegen, dass wir es hier
a) nicht mit einem notify-trigger zu tun haben (da funktioniert es ggf. etwas anders), und
b) setreading generell für userReadings tabu ist (solange das bulkUpdate läuft).

Im Detail: Die Auswertung von userReadings erfolgt in readingsEndUpdate() (aktuelle svn-Zeile): https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L4761

a) Da werden für ein readingsEndUpdate() alle userReadings durchgesehen, der "trigger" ist also kein echter Auslöser, sondern tatsächlich eine Begrenzung der Häufigkeit der Ausführung des eigentlichen weiteren Codes, indem "irrelevante Updates" ignoriert werden.

b) siehe dazu https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L4707 + https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L2469. readingsBeginUpdate setzt einen Marker, der die direkte Ausführung von setreading verhindert => das klappt nur, wenn man wissentlich ausbricht (was man aber lassen sollte! Es hat seinen Grund, warum das nicht erwünscht ist...).
Server: HP-T620@Debian 11, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Offline frober

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 1107
  • Was man nicht kann, kann man lernen...
Da spricht m.E. dagegen, dass wir es hier
a) nicht mit einem notify-trigger zu tun haben (da funktioniert es ggf. etwas anders), und
b) setreading generell für userReadings tabu ist (solange das bulkUpdate läuft).

Im Detail: Die Auswertung von userReadings erfolgt in readingsEndUpdate() (aktuelle svn-Zeile): https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L4761

a) Da werden für ein readingsEndUpdate() alle userReadings durchgesehen, der "trigger" ist also kein echter Auslöser, sondern tatsächlich eine Begrenzung der Häufigkeit der Ausführung des eigentlichen weiteren Codes, indem "irrelevante Updates" ignoriert werden.

b) siehe dazu https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L4707 + https://svn.fhem.de/trac/browser/trunk/fhem/fhem.pl#L2469. readingsBeginUpdate setzt einen Marker, der die direkte Ausführung von setreading verhindert => das klappt nur, wenn man wissentlich ausbricht (was man aber lassen sollte! Es hat seinen Grund, warum das nicht erwünscht ist...).

Danke, für die ausführliche Erklärung. Ich werde es mir in Ruhe anschauen.
Raspi 3b mit Raspbian Stretch und relativ aktuellem Fhem,  FS20, LGW, PCA301, MySensors mit RS485(CAN-Receiver), etc.,
einiges umgesetzt, vieles in Planung :-)

********************************************
...man wächst mit der Herausforderung...