[geklärt] split von $EVENT im notify

Begonnen von TomLee, 24 Juli 2021, 12:54:46

Vorheriges Thema - Nächstes Thema

TomLee

Hallo,

gegeben ist folgender dummy, damit kann ich ein Reading Test setzen das keinen Inhalt hat (wenn zuvor was in dem Reading drin stand sonst ergibt der setter undefined)

defmod Demo dummy
attr Demo readingList Test
attr Demo room Test
attr Demo setList Test:noArg

setstate Demo Test Test1
setstate Demo 2021-07-24 12:17:36 Test


und ein notify:

defmod Demo_notify_1 notify Demo:Test:.* {my $ec = split(': ','$EVENT');;\
Log3(undef, 3, "Das ist $EVENT und $ec");;}


Wenn ich jetzt den setter Test ausführe steht im Log:
Zitat
2021.07.24 12:30:40 3: Das ist Test:  und 1

das deckt sich auch mit:

{my $ec = split(': ','Test: ');; return $ec;;}

aus der Kommandozeile, ergibt auch 1.

Führe ich ein

setreading Demo Test Test1

aus steht im Log:

2021.07.24 12:34:54 3: Das ist Test: Test1 und 1

in der Kommandozeile:

{my $ec = split(': ','Test: Test1');; return $ec;;}

aber 2.

Was mach ich hier falsch in dem notify/was übersehe ich/was hab ich nicht verstanden ?

Und es ist mir egal wieviele EVTPARTx es geben könnte, möchte nur eine Fallunterscheidung ob ein EVTPART1 existiert oder nicht erreichen.


Weitere Frage:

Nehme ich in dem notify eine Bedingung mit rein (jetzt mal unabhängig davon das wie oben gezeigt im notify immer 1 als Anzahl zurückkommt):

defmod Demo_notify_1 notify Demo:Test:.* {my $ec = split(': ','$EVENT');;\
return if $ec == '1';;\
set OG_Echo_Wohnzimmer speak bla;;
Log3(undef, 3, "Das ist $EVENT und $ec");;}


erfolgt wie erwartet wegen dem return nix keine Ausführung des Befehls oder der Logausgabe.

Ändere ich in dem obigen Beispiel die Sprachausgabe zu $EVTPART1

defmod Demo_notify_1 notify Demo:Test:.* {my $ec = split(': ','$EVENT');;\
return if $ec == '1';;\
set OG_Echo_Wohnzimmer speak $EVTPART1;;
Log3(undef, 3, "Das ist $EVENT und $ec");;}


erfolgt wie erwartet keine Sprachausgabe und Logausgabe, es kommt aber zu folgender Meldung im Log:

2021.07.24 12:47:29 1: ERROR evaluating my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $NAME=   $evalSpecials->{'%NAME'};my $SELF=   $evalSpecials->{'%SELF'};my $TYPE=   $evalSpecials->{'%TYPE'};{my $ec = split(': ','$EVENT');
return if $ec == '1';
set OG_Echo_Wohnzimmer speak $EVTPART1;
Log3(undef, 3, "Das ist $EVENT und $ec");}: Global symbol "$EVTPART1" requires explicit package name (did you forget to declare "my $EVTPART1"?) at (eval 125142) line 3.

2021.07.24 12:47:29 3: Demo_notify_1 return value: Global symbol "$EVTPART1" requires explicit package name (did you forget to declare "my $EVTPART1"?) at (eval 125142) line 3.


Es sollte nach dem return nix doch eigentlich auch nix mehr passieren, warum nimmt das notify aber trotzdem eine "Auswertung" von $EVTPART1 vor ?

Gruß

Thomas

JensS

Bei notify im Zusammenhang mit dummy hatte ich kürzlich ebenfalls ein seltsames Phänomen.
Aus einem Modul heraus wurde bei verschiedenen Devicetypen (Zigbee2MQTT, GHoma, FRM_OUT) mit "set <device> on" ein Event ausgelöst, beim Typ dummy aber nicht.
https://forum.fhem.de/index.php/topic,119447.msg1167212.html#msg1167212
Sorry, wenn das dein Topic nicht direkt betrifft aber vielleicht gibt es einen Zusammenhang.

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

betateilchen

Zitat von: TomLee am 24 Juli 2021, 12:54:46
Und es ist mir egal wieviele EVTPARTx es geben könnte, möchte nur eine Fallunterscheidung ob ein EVTPART1 existiert oder nicht erreichen.

Warum prüfst Du dann im notify nicht einfach auf $EVTPART1?


defmod demo_notify_1 notify demo:Test:.* {no strict;;return unless $EVTPART1;;Debug $EVTPART1;;}
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Christoph Morrison

Hallo Thomas,

Zitat von: TomLee am 24 Juli 2021, 12:54:46
Wenn ich jetzt den setter Test ausführe steht im Log:
das deckt sich auch mit:

{my $ec = split(': ','Test: ');; return $ec;;}

aus der Kommandozeile, ergibt auch 1.

Führe ich ein

setreading Demo Test Test1

aus steht im Log:

2021.07.24 12:34:54 3: Das ist Test: Test1 und 1

in der Kommandozeile:

{my $ec = split(': ','Test: Test1');; return $ec;;}

aber 2.

Zitat von: https://perldoc.perl.org/functions/splitSplits the string EXPR into a list of strings and returns the list in list context, or the size of the list in scalar context. (Prior to Perl 5.11, it also overwrote @_ with the list in void and scalar context. If you target old perls, beware.)

Du splittest einen String in ein bzw. zwei Listenelemente und sagst Perl, dass du das Ergebnis im skalaren Kontext haben willst → du erhältst die Anzahl der Elemente in der Liste, korrekterweise also 1 oder 2.


> perl -MData::Dumper -e '@p = split(q(: ),q(Test: Test1)); print Dumper(\@p)'
$VAR1 = [
          'Test',
          'Test1'
        ];

❯ perl -MData::Dumper -e '@p = split(q(: ),q(Test: )); print Dumper(\@p)'
$VAR1 = [
          'Test'
        ];


ZitatWeitere Frage:
Es sollte nach dem return nix doch eigentlich auch nix mehr passieren, warum nimmt das notify aber trotzdem eine "Auswertung" von $EVTPART1 vor ?

Der Code wird komplett übersetzt (dabei auf Fehler untersucht) und dann erst ausgeführt, wenn use strict verwendet wird.

❯ perl -e 'sub foo { return; print $not_declared}; foo()'

$not_declared existiert nicht, use strict ist nicht gesetzt -> keine Fehlermeldung, es passiert einfach gar nichts.

❯ perl -Mstrict -e 'sub foo { return; print $not_declared}; foo()'
Global symbol "$not_declared" requires explicit package name (did you forget to declare "my $not_declared"?) at -e line 1.
Execution of -e aborted due to compilation errors..


Boing. Deshalb verwendet betateilchen auch das no strict-Pragma, aber:


❯ perl -e '$t = 0; print q(wahr) unless $t'
wahr


Problematisch wird es, wenn $EVTPART1 mal 0 ist, denn unless 0 ist wahr. Besser ist defined.

ZitatUnd es ist mir egal wieviele EVTPARTx es geben könnte, möchte nur eine Fallunterscheidung ob ein EVTPART1 existiert oder nicht erreichen.

no strict; return if defined $EVTPART1


betateilchen

Zitat von: TomLee am 24 Juli 2021, 12:54:46
my $ec = split(': ','$EVENT');

Was mach ich hier falsch in dem notify/was übersehe ich/was hab ich nicht verstanden ?

split liefert ein array zurück, also müsste es besser "my @ec" heißen und nicht "my $ec".
Man kann auch an ein scalar zuweisen, dann muss man aber wissen, was man tut und was das Ergebnis sein wird.

Übrigens: die einfachen Anführungszeichen um $EVENT sind nicht nur überflüssig, sondern falsch.

----

Edit: ok, Christoph hat die lange Version meiner Antwort geliefert :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

TomLee

An dem Vorschlag hakt was.

Mit keinem Wert in dem Reading Test und diesem
defmod Demo_notify_1 notify Demo:Test:.* {no strict;;return unless $EVTPART1;;set OG_Echo_Wohnzimmer speak bla;;}

erfolgt keine Sprachausgabe und dem no script keine Meldung im Log, gut.

Mach ich ein setreading Demo Test Test1 steht im Log:

2021.07.24 13:54:47 1: ERROR evaluating my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $EVTPART1=   $evalSpecials->{'%EVTPART1'};my $NAME=   $evalSpecials->{'%NAME'};my $SELF=   $evalSpecials->{'%SELF'};my $TYPE=   $evalSpecials->{'%TYPE'};{no strict;return unless $EVTPART1;set OG_Echo_Wohnzimmer speak bla;}: Can't locate object method "speak" via package "bla" (perhaps you forgot to load "bla"?) at (eval 131955) line 1.

2021.07.24 13:54:47 3: Demo_notify_1 return value: Can't locate object method "speak" via package "bla" (perhaps you forgot to load "bla"?) at (eval 131955) line 1.

TomLee

Ich war am schreiben, muss mich mit den letzten zwei Beiträgen noch beschäftigen.

betateilchen

Zitat von: TomLee am 24 Juli 2021, 13:59:20
defmod Demo_notify_1 notify Demo:Test:.* {no strict;;return unless $EVTPART1;;set OG_Echo_Wohnzimmer speak bla;;}

Du vermischt perl Code und FHEM Befehl, das kann so nicht funktionieren.

Probier mal:

defmod Demo_notify_1 notify Demo:Test:.* {no strict;;return unless $EVTPART1;;fhem("set OG_Echo_Wohnzimmer speak bla");;}

Du scheiterst mal wieder an absoluten FHEM Basics...  8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

TomLee

ZitatDu scheiterst mal wieder an absoluten FHEM Basics...

::)

TomLee

ZitatÜbrigens: die einfachen Anführungszeichen um $EVENT sind nicht nur überflüssig, sondern falsch.

Ich weiß, das hab ich mittleweile inne, mehre Codestücke oben waren auch einfach zusammenkopiert (aus dem Kopf), weil ich den ganzen Text schon fertig hatte, mich neu anmelden musste und alles wieder weg war.

Übrigens heute bist ein Spatz, mein Spatz  :P

Danke.

Christoph Morrison

Zitat von: betateilchen am 24 Juli 2021, 13:56:09
Übrigens: die einfachen Anführungszeichen um $EVENT sind nicht nur überflüssig, sondern falsch.

Das hier ist auch Käse:
Zitatreturn if $ec == '1';;\

Entweder in $ec is ein String, dann braucht man eq. Oder in $ec ist eine Zahl, dann braucht man keine Quotes um die 1.

Beta-User

$EVTPARTn ist doch - afair - auch nur das Ergebnis aus einem split... Warum das dann nicht im Code selbst durch einen passenderen split so machen, wie man es braucht?

Bzgl. des anderen Threads würde ggf. einfach ein Punkt mehr reichen um sicher zu sein, dass part1 existiert.
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

TomLee

Was ich jetzt nicht verstehe, das es mit return if defined $EVTPART1 zu der Meldung unten kommt beim löschen der Einkaufsliste und mit return unless $EVTPART1 keine kommt, habs jetzt so verstanden das das mit no strict in beiden Fällen abgefangen werden sollte.
Ich habs mehrfach getestet bevor ich hier Mist schreibe.

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));;}


2021.07.24 15:13:33 1: PERL WARNING: Use of uninitialized value $EVTPART1 in split at (eval 140328) line 4.
2021.07.24 15:13:33 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));}

Beta-User

#13
evalSpecials wird ausgeführt, bevor no strict greifen kann... => selber splitten und in Variablen packen...

EDIT: via evalSpecials kann auch nur ersetzt werden, was da ist... Die restlichen Variablen bleiben stehen.
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

betateilchen

Zitat von: Beta-User am 24 Juli 2021, 15:34:19
=> selber splitten und in Variablen packen...

Spätestens jetzt geh ich mal Popcorn holen und genieße das weitere Showprogramm hier...
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!