Korrekte Syntax FHEM-Befehl in Perl im ...notify... in myUtils auslagern

Begonnen von TomLee, 10 Juli 2020, 12:34:40

Vorheriges Thema - Nächstes Thema

TomLee

@Jörg

Was das ein/verbauen von Hardware angeht bin ich sehr eigen, eher verzicht ich darauf wie das man sie sieht/sehen könnte oder annehmbar aussieht.

Mit dem WLED-Controller (ja WLAN, aber dazu hab ich mich ja schon länger entschieden und ja jetzt zwei Geräte zu einem vereint) als "IR-Gateway" hab ich die Lösung "gefunden" (die man nicht sehen wird (noch nicht umgesetzt, das wird noch etwas Arbeit)), die ich mir schon länger wünsche.

Beim umstellen von meiner "Sensorkrake" (die ich bisher immer nur zum testen rausholte, den ungefähren Code hier also nie wirklich nutzen konnte und ja zigbee wäre auch eine Lösung, mich stört aber die zusätzliche FB, obwohl mir zigbee angenehmer wäre) auf das WLED-Gateway fällt mir eins auf:

Das ich dir sehr sehr dankbar bin diesen Code mit Hilfe deiner Geduld (und ohne spitze Bemerkungen) zu lernen und zu verstehen, im Prinzip sind es nur zwei Anpassungen in dem notify (Gerätename und auslösendes Ereignis) um all die Geräte weiterhin zu steuern.

Zusätzliche Arbeit war nur das anpassen der IR-Codes von Groß.- auf Kleinschreibung (die kommen bei WLED klein rein).




Ein großes, dickes, wiederholtes Danke dafür.

TomLee

Kann mir wer hier nochmal behilflich sein bitte.

Bisher hatte ich mit folgendem DOIF die Möglichkeit per Sprache die Einkaufsliste auszudrucken, direkt im Anschluß wurde die Liste gelöscht (das war keine praxistaugliche Lösung mit dem direkt löschen, kein Papier im Drucker, Drucker aus oder Papierstau und die Liste war weg)
DOIF damals deshalb weil es die dummy/notify Lösung erspart hatte.

defmod doif_Echo_Einkaufsliste DOIF ($SELF eq "on")( {system("lpr -P HL-2035 -o media=Custom.95x138mm /opt/fhem/einkaufsliste.txt")},{my @array = split(",",ReadingsVal("Echo","list_SHOPPING_ITEM",""));; foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}})
attr doif_Echo_Einkaufsliste alexaName einkaufsliste
attr doif_Echo_Einkaufsliste cmdState on|off
attr doif_Echo_Einkaufsliste devStateIcon on:general_an:off off|initialize.*:general_aus:on
attr doif_Echo_Einkaufsliste do always
attr doif_Echo_Einkaufsliste genericDeviceType switch
attr doif_Echo_Einkaufsliste group Einkaufsliste
attr doif_Echo_Einkaufsliste room Sprachsteuerung
attr doif_Echo_Einkaufsliste setList on off


Per Sprache gefällt mir nicht mehr darum jetzt mal der Versuch es mit IR zu versuchen und das direkte löschen anders zu lösen (wenn man selbst löscht), wenn jemand aber einen besseren Vorschlag die Liste automatisiert zu löschen, schlag ich den natürlich nicht aus.

Mein bisheriger Gedanke ist die Liste erst zu löschen wenn man einen bestimmten Button drückt.

Dazu hab ich mir überlegt die Schleife erst nach diesem Event auszuführen, mit sleep in dem FHEM-Befehl der Variablen $sound:

if ($dudevstate eq 'Einkaufsliste') {

# blue button 1x

#my $sound = sub {fhem("set $kecho sounds Glocken");};
my @array = split(",",ReadingsVal('Echo','list_SHOPPING_ITEM',''));
my $sound = sub {fhem("set $kecho sounds Glocken;sleep MQTT2_WLED_FR:ircode:0x20df827d;{foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}}");};


my $a1 = sub { system('lpr -P HL-2035 -o media=Custom.95x138mm /opt/fhem/einkaufsliste.txt &');};

my $sr2cmnd = {
'0x20df22dd' => \&$a1};

return fhem("set $kecho speak $dudevstate") if $rcCode eq "0x20df55aa";
return $sr2cmnd->{$rcCode}->().$sound->() if ref $sr2cmnd->{$rcCode} eq 'CODE';
return;
}


Wenn ich die my Utils aber speichern möchte kommt diese Meldung:
Global symbol "$sk" requires explicit package name (did you forget to declare "my $sk"?) at ./FHEM/99_Remotes_myUtils.pm line 295. syntax error at ./FHEM/99_Remotes_myUtils.pm line 295, near ""set $kecho sounds Glocken;sleep MQTT2_WLED_FR:ircode:0x20df827d;{foreach my $sk (@array) {fhem ("set Echo " Global symbol "$sk" requires explicit package name (did you forget to declare "my $sk"?) at ./FHEM/99_Remotes_myUtils.pm line 295.

Ich habs auch schon auf anderen Wegen versucht es hängt immer an my $sk.

Wie macht mans richtig ?

TomLee

Bin etwas weiter.

Das my @array = split(",",ReadingsVal("Echo","list_SHOPPING_ITEM",""));
foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}

hab ich in so eine anonyme sub gesteckt und die in eine Variable, diese wiederum einfach an das sleep angehängt.

if ($dudevstate eq 'Einkaufsliste') {

# blue button 1x -> Einkaufsliste

my $fee = sub {my @array = split(",",ReadingsVal("Echo","list_SHOPPING_ITEM",""));
foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}};

my $sound = sub {fhem("set $kecho sounds Glocken;sleep MQTT2_WLED_FR:ircode:.0x20dfda25;$fee");};

my $a1 = sub { system('lpr -P HL-2035 -o media=Custom.95x138mm /opt/fhem/einkaufsliste.txt &');};

my $sr2cmnd = {
'0x20df22dd' => \&$a1};

return fhem("set $kecho speak $dudevstate") if $rcCode eq "0x20df55aa";
return $sr2cmnd->{$rcCode}->().$sound->() if ref $sr2cmnd->{$rcCode} eq 'CODE';
return;
}


Jetzt wird korrekt die Datei ausgedruckt (auch schon zuvor), es wird das eventbasierte sleep/at (wie auch immer) angelegt, welches mit cancel angezeigt wird .sleep_2919198 MQTT2_WLED_FR:ircode:.0x20dfda25 CODE(0x843f920) und wenn ich die 0x20dfda25 drücke wird es wieder gelöscht.
Aber die Liste wird nicht gelöscht, merkwürdig kommt mir das CODE(0x843f920) in dem .sleep_2919198 vor .

edit:

auch wenn ich $fee->() verwende:

my $sound = sub {fhem("set $kecho sounds Glocken;sleep MQTT2_WLED_FR:ircode:.0x20dfda25;$fee->()");};

.sleep_4818  MQTT2_WLED_FR:ircode:.0x20dfda25 CODE(0x22d8500)->()

Im Log steht:

After sleep: Unknown command CODE(0x22d8500)->(), try help.

edit2:
Mit
{my $fee = sub {my @array = split(",",ReadingsVal("Echo","list_SHOPPING_ITEM",""));;foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}};;return $fee->()}
aus der Kommandozeile wird die Liste gelöscht.

TomLee

OK, OK, es muss gar nicht von hinten durch die Brust sein, der Grund wird wohl sein das ich mich erst wieder eindenken musste und vor der Frage zu wenig mit beschäftigt habe.

So klappts wie ich mir das vorgestellt habe, mit Bestätigungston, der war bei meinem vorherigen Gedanken gar nicht vorgesehen/beachtet gewesen:

if ($dudevstate eq 'Einkaufsliste') {

# blue button 1x -> Einkaufsliste

my $sound = sub {fhem("set $kecho sounds Glocken");};
my $a1 = sub { system('lpr -P HL-2035 -o media=Custom.95x138mm /opt/fhem/einkaufsliste.txt &');};
my $a2 = sub {my @array = split(",",ReadingsVal("Echo","list_SHOPPING_ITEM",""));
foreach my $sk (@array) {fhem ("set Echo item_shopping_delete $sk")}};

my $sr2cmnd = {
'0x20df22dd' => \&$a1,
'0x20dfda25' => \&$a2};

return fhem("set $kecho speak $dudevstate") if $rcCode eq "0x20df55aa";
return $sr2cmnd->{$rcCode}->().$sound->() if ref $sr2cmnd->{$rcCode} eq 'CODE';
return;
}





Was jetzt hier bei dem Thema Einkaufsliste drucken immer noch nicht passt ist die Meldung:

ERROR evaluating my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $NAME=   $evalSpecials->{'%NAME'};my $SELF=   $evalSpecials->{'%SELF'};my $TYPE=   $evalSpecials->{'%TYPE'};{FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1))}: Global symbol "$EVTPART1" requires explicit package name (did you forget to declare "my $EVTPART1"?) at (eval 10719) line 1.

die beim löschen der Liste von diesem notify kommt:

defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:.* {FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1))}

Damals hatte keiner eine Idee wie man das verhindern könnte, mein Gedanke ist jetzt nix_machen wenn Echo:list_SHOPPING_ITEM:.* leer/nix ist ?

Damit beschäftige ich mich als nächstes, aber auch hier schlag ich einen Vorschlag nicht aus, der mir zuvorkommt.

Otto123

Hallo Tom,

Eigentlich in solchen Fällen besser nicht mit evtpart arbeiten sondern den $EVENT selbst splitten?

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee


TomLee

Also aus den Infos aus dem anderen Thread ziehe ich das !defined auf $EVTPART1 die richtige Variante ist (mir auch gefällt) und wenn das mit der Meldung des notify nur mit no strict zu umgehen ist dann ist das halt so.

Mit split hatte ich mich gestern Abend schon beschäftigt (mein erster Gedanke war es mit defined anzugehen), wenn man sich dazu im Forum einliest hat Betateilchen auch mal selbst diesen Lösungsweg vorgeschlagen gehabt, heute halt unless auf $EVTPART1.

Ich fass nur mal der Vollständigkeit und zum nachvollziehen (in erster Linie für mich in Zukunft) zusammen, hab das jetzt mehrfach getestet und bin zufrieden damit:


if ($dudevstate eq 'Einkaufsliste') {

# blue button 1x -> Einkaufsliste

my $sound = sub {fhem("set $kecho sounds Glocken");};
my $a1 = sub { system('lpr -P HL-2035 -o media=Custom.95x138mm /opt/fhem/einkaufsliste.txt &');};
my $a2 = sub {my @array = split(',',ReadingsVal($echod,'list_SHOPPING_ITEM',''));
foreach my $sk (@array) {fhem ("set $echod item_shopping_delete $sk")}};

my $sr2cmnd = {
'0x20df22dd' => \&$a1,
'0x20dfda25' => \&$a2};

return fhem("set $kecho speak $dudevstate") if $rcCode eq '0x20df55aa';
return $sr2cmnd->{$rcCode}->().$sound->() if ref $sr2cmnd->{$rcCode} eq 'CODE';
return;
}


defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:.* {no strict;;\
return if !defined $EVTPART1;;\
return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}

frober

Hi,
es ist toll, das du das alles dokumentierst.
Allerdings macht es den Thread langsam unübersichtlich und ich meine, dass es in Anfängerfragen nicht richtig aufgehoben ist.

Mich interessiert das alles, und ich habe mittlerweile auch alle größeren Funktionen in myUtils. Daher wäre es super, wenn wir dafür  ein Unterforum bekommen könnten.

Nur weiß ich momentan nicht wen wir dazu überzeugen müssen...

Ich denke, dass ein entsprechendes Unterforum, vielleicht auch ein Zwischenschritt zum Dev. wäre!?

Grüße
Bernd
Raspi 3b mit Raspbian Buster und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

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

TomLee

ZitatIch denke, dass ein entsprechendes Unterforum, vielleicht auch ein Zwischenschritt zum Dev. wäre!?

Ein entsprechendes Unterforum fänd ich auch toll.
Das mit dem Zwischenschritt sehe ich nicht so, ich bin weder Tester und niemals Developer, einfach nur ich, bin auf dem Acker groß geworden, hab mit Programmierung nie was am Hut gehabt, mir macht das (Heute/mittlerweile) zwischendurch einfach nur Spaß und mit meiner Ausübung meiner Tätigkeit hat das auch null am Hut.

frober

Zitat von: TomLee am 24 Juli 2021, 19:29:34
Ein entsprechendes Unterforum fänd ich auch toll.
Das mit dem Zwischenschritt sehe ich nicht so, ich bin weder Tester und niemals Developer, einfach nur ich, bin auf dem Acker groß geworden, hab mit Programmierung nie was am Hut gehabt, mir macht das (Heute/mittlerweile) zwischendurch einfach nur Spaß und mit meiner Ausübung meiner Tätigkeit hat das auch null am Hut.

Mir geht es ähnlich, das war nur Mal als Argument in den Raum geworfen. . 8)
Raspi 3b mit Raspbian Buster und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

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

frober

Raspi 3b mit Raspbian Buster und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

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

Beta-User

Zitat von: TomLee am 24 Juli 2021, 18:40:35
Also aus den Infos aus dem anderen Thread ziehe ich das !defined auf $EVTPART1 die richtige Variante ist (mir auch gefällt) und wenn das mit der Meldung des notify nur mit no strict zu umgehen ist dann ist das halt so.

Vermutlich ist der Hinweis untergegangen, aber (ungetestet) sollte sich das Warning auch verhindern lassen, indem man die regexp so wählt, dass sichergestellt ist, dass $EVTPART1 exisitiert:
defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:..* {return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}
Der weitere Punkt ("..*", kann man hier vermutlich auch als ".+" notieren) sollte sicherstellen, dass das Reading tatsächlich einen neuen Wert gesetzt erhält.
Server: HP-elitedesk@Debian 12, 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

frober

Zitat von: Beta-User am 28 Juli 2021, 07:44:27
Vermutlich ist der Hinweis untergegangen, aber (ungetestet) sollte sich das Warning auch verhindern lassen, indem man die regexp so wählt, dass sichergestellt ist, dass $EVTPART1 exisitiert:
defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:..* {return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}
Der weitere Punkt ("..*", kann man hier vermutlich auch als ".+" notieren) sollte sicherstellen, dass das Reading tatsächlich einen neuen Wert gesetzt erhält.

Kannst du mir das näher erläutern?

Wieso "..*"?  MWn bedeutet "." jedes x-beliebige Zeichen und "*" kann unendlich mal vorkommen, somit sollte ".*" doch reichen !?
Das '+' muss ich erst nachlesen...
Raspi 3b mit Raspbian Buster und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

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

TomLee

ZitatVermutlich ist der Hinweis untergegangen, aber (ungetestet)

Nee untergegangen nicht, erst nicht verstanden wo der Punkt gemeint gewesen wäre und später, als ich verstanden hatte wo ging mir dann das gleiche durch den Kopf wie Frober, mich aber ehrlich gesagt dann nicht weiter beschäftigt habe.

Du schreibst ja ungetestet, hätte jetzt aber erwartet nachdem du das extra nochmal hochholst du hast es getestet und bist dir sicher.

Es kommt mit beiden Varianten weiterhin zu der Meldung, die erste mit ..* die zweite mit .+:

2021.07.28 10:09:25 1: PERL WARNING: Use of uninitialized value $EVTPART1 in split at (eval 756491) line 4.
2021.07.28 10:09:25 3: eval: my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $NAME=   $evalSpecials->{'%NAME'};my $SELF=   $evalSpecials->{'%SELF'};my $TYPE=   $evalSpecials->{'%TYPE'};{no strict;
#return if !defined $EVTPART1;
#return unless $EVTPART1;
return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));}
2021.07.28 10:12:57 1: PERL WARNING: Use of uninitialized value $EVTPART1 in split at (eval 756852) line 4.
2021.07.28 10:12:57 3: eval: my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $NAME=   $evalSpecials->{'%NAME'};my $SELF=   $evalSpecials->{'%SELF'};my $TYPE=   $evalSpecials->{'%TYPE'};{no strict;
#return if !defined $EVTPART1;
#return unless $EVTPART1;
return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));}


Hier nochmal die notify-Definition, aber nur mit .+ (die zweite Meldung):

defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:.+ {no strict;;\
#return if !defined $EVTPART1;;\
#return unless $EVTPART1;;\
return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}

Beta-User

".*" ist "beliebige Zeichenfolge, kann auch 'nichts' sein". 'nichts' verursacht hier grade das Problem, weil das "split" für $EVTPARTn eben nur ein Element (=> $EVTPART0) findet.

"..*" ist "beliebige Zeichenfolge, aber mindestens ein Zeichen" (nämlich den expliziten "Punkt"). Hab's grade getestet, das funktioniert, aber man braucht einen dritten Punkt:
defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:...* {return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}Die Ursache dürfte im Zusammenbau des Auswertestrings in 91_notify.pm (dort notify_Exec()) liegen.

Zum "+" und weiteren Fragen würde ich auf regex101.com verweisen, da findet  man z.B. auch Infos, wie man die Zahl der Wiederholungen einstellen kann usw.. Was z.B. auch geht, ist "mind. 2 Zeichen" so zu schreiben:
defmod not_Echo_Einkaufsliste notify Echo:list_SHOPPING_ITEM:.{2,} {return FileWrite({ FileName=>"/opt/fhem/einkaufsliste.txt", ForceType=>"file", NoNL => 0},split(/\,/,$EVTPART1));;}

Man sollte bei solchen Optimierungen nur darauf achten, dass NOTIFYDEV weiter gesetzt bleibt (zu finden unter den Internals beim notify). (Das ist aber eine andere Diskussion, ich müßte ggf. die Links suchen, auch auch zur Hilfsfunktion zur Analyse, woran es hakt (notifyRegexpCheck()).
Server: HP-elitedesk@Debian 12, 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