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
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 (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
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;;}
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
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 :)
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.
Ich war am schreiben, muss mich mit den letzten zwei Beiträgen noch beschäftigen.
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)
ZitatDu scheiterst mal wieder an absoluten FHEM Basics...
::)
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.
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.
$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.
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));}
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.
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...
Manege frei:
OK, mal nachgedacht:
return if !defined $EVTPART1
Zitat von: betateilchen am 24 Juli 2021, 13:13:00
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;;}
Nur aus Interesse, hat Debug noch weitere Parameter sowas wie Loglevel, ist es irgendwo dokumentiert, hab das hier das erste mal gesehen ?
sowas und andere feine Tools findest Du hier https://wiki.fhem.de/wiki/DevelopmentModuleAPI#Debug
Zitat von: TomLee am 25 Juli 2021, 13:36:02
Nur aus Interesse, hat Debug noch weitere Parameter sowas wie Loglevel
Nein, Debug($msg) ist nur ein quick&dirty Aufruf von 'Log 1, "DEBUG>" . $msg;' und hilfreich zum Testen.
Dokumentiert ist das primär in der fhem.pl
https://forum.fhem.de/index.php/topic,112785.msg1168079.html#msg1168079 (https://forum.fhem.de/index.php/topic,112785.msg1168079.html#msg1168079)
Zitat von: Christoph Morrison am 24 Juli 2021, 14:32:56
Das hier ist auch Käse:
Entweder in $ec is ein String, dann braucht man eq. Oder in $ec ist eine Zahl, dann braucht man keine Quotes um die 1.
Hier:
Zitatsub fb_cmp {
my $NAME = shift;
my $EVTPART0 = shift;
my $EVTPART1 = shift;
my $lgtvs = shift;
my $sonoswz = shift;
my $echok = shift;
my $sonosps = shift;
chop($EVTPART0);
$EVTPART1 =~ s/&/und/;
my $extn = ReadingsVal($NAME,'external_name','unbekannt');
my $extnr = ReadingsVal($NAME,'external_number','unbekannt');
my $intnr = ReadingsNum($NAME,'internal_number','unbekannt');
my $intc = ReadingsVal($NAME,'internal_connection','unbekannt');
my $mcr = ReadingsVal($NAME,'missed_call','unbekannt');
my $echodb = qq(set $echok sounds tuerklingel_3);
if ($EVTPART1 eq "ring") {
return fhem("set $sonoswz playSound 20 Vibrating") if $extn eq 'unknown';
return fhem("set $sonoswz playSound 20 Fax-Beep;set $echok speak Fax Eingang") if $intnr == '999999';
return fhem("set $sonoswz speak 20 Es ist $extn;set $echok speak Es ist $extn;set tb_TelegramBot msg Es ist: $extnr ($extn)");
}
}
muss ich die Quotes verwenden, sonst klappts nicht, was hab ich hier jetzt nicht verstanden ?
Ich kann dir zwar deine Frage nicht beantworten, aber ich sehe ein anderes Problem:
Zitatmy $extn = ReadingsVal($NAME,'external_name','unbekannt')
.
.
.
return fhem("set $sonoswz playSound 20 Vibrating") if $extn eq 'unknown';
Glaub zwar nicht das jemals der Fall eintritt das der Ersatzwert genommen wird, werds aber anpassen, Danke.
Was heißt denn "sonst klappts nicht"?
Hast du mal debuggt, was in $intnr drin steht?
Was heißt denn "sonst klappts nicht"?
Der Zweig
return fhem("set $sonoswz playSound 20 Fax-Beep;set $echok speak Fax Eingang") if $intnr == '999999';
wird halt nie ausgeführt ohne Quotes.
Zitat
Hast du mal debuggt, was in $intnr drin steht?
Schon, im Eventmonitor und als debug-Ausgabe ins Log und meine Faxnummer kenne ich.
Sry, ich merke gerade das es auch ohne geht, nachdem ich noch eine Telegram-Message dazu genommen habe, hab ich wohl im Log nicht richtig geschaut gehabt.
Das verwirrende war das nie playsound abgespielt wurde, das hing wieder damit zusammen das ich normal mute wenn ein call ist und unmute wenn ein disconnect ist, da ich aber vor Monaten rumgetestet hatte und das muten bei einem call rausgenommen hatte erfolgte zufällig immer bei meinem testen heute keine Ausgabe. Und da ich mich wegen einem anderen Thema mehrmals selbst angerufen habe, bei mir aber immer eine Umleitung (also nach einem call dann nochmal ein call erfolgt) war der Sonosplayer beim testen immer "gemuted". Schwierig zu erkären ::) , beim Sonosplayer nutz ich halt nur einen setter für mute zum Statuswechsel, kein mute on / off.
if ($EVTPART1 eq "ring") {
return fhem("set $sonoswz playSound 20 Vibrating") if $extn eq 'unknown';
return fhem("set $sonoswz playSound 20 Fax-Beep;set $echok speak Fax Eingang;set tb_TelegramBot msg Faxeingang $extnr ($extn $intnr)") if $intnr == 999999;
return fhem("set $sonoswz speak 20 Es ist $extn;set $echok speak Es ist $extn;set tb_TelegramBot msg Es ist: $extnr ($extn)");
}