Umgang mit @-Zeichen in String DOIF vs Perl

Begonnen von Sirel, 30 Mai 2021, 23:53:54

Vorheriges Thema - Nächstes Thema

Sirel

Hallo zusammen,
ich habe eine Subroutine welche mir ein String erstellt, in welchem alle Namen der anwesenden Personen mit einem @ vorangestellt gespeichert werden. Hintergrund ist, das nur diese Personen eine Nachricht via Telegramm erhalten sollen. Die Telegram Syntax setzt voraus, dass alle Peers ein @-Zeichen vorangestellt bekommen.

Übernehme ich das Ergebnis der Routine in ein DOIF, funktioniert alles es ohne Probleme:


([Test] eq "open") (set xxxx_telegram send {(com_control)} blablabla)

DOELSE


Alles top, die Personen welche über die Routine com_cotrol ermittelt werden,  erhalten alle die Nachricht.

Der String, welcher zurückgegeben wird ist 
@Max @Johanna .
Dies sind unsere @usernamens. Der String wird dynamisch erstellt, abhängig wer zu Hause ist.

Wenn ich die gleiche Logik in einer myUtils anwende, dann erhalte ich eine Nachricht in der steht:

@Max @Johanna bla bla bla

Wobei @Max unterstrichen ist.

Der Code in der myUtils lauter:
{fhem ("set xxxtelegram send " . '{(com_control)}' . " Morgen müssen folgende Tonnen rausgestellt werden \\n$tonne")};

Was macht das DOIF, was Perl anders macht? Und was muss ich tun, damit es in Perl auch so funktioniert?

Ich tippe das hat damit etwas zutun:

https://forum.fhem.de/index.php?topic=48859.0

VG,
Max

Damian

Probiere mal:

{fhem ("set xxxtelegram send ".com_control." Morgen müssen folgende Tonnen rausgestellt werden \\n$tonne")};
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sirel

Guten Morgen Damian,

habe es eben ausprobiert, leider kein Unterschied.
Weiterhin kommt

@Max @Johanna Morgen müssen...

Als returnvalue in einem DOIF klappt es ja ohne Probleme.

Komisch...

Besten Dank und Grüße,

Max

yersinia

Du musst das @ escapen im perl
\@Max \@Johanna
dann sollte es gehen.
viele Grüße, yersinia
----
FHEM 6.4 (SVN) on RPi 4B with RasPi OS Bookworm (perl 5.36.0) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

Sirel

Hallo zusammen,

das will noch nicht so recht.

Ich baue wie folgt den String zusammen:



my $pres_list = ReadingsVal("rgr_Bewohner","residentsTotalOwnersPresentDevs","rr_Mama");
my @residents ="";
my @clear_names ="";
my $name = "";
my $ret_value = "";

@residents = split (/,/, $pres_list);

if (!@residents) {
$ret_value = "";
return $ret_value;
}

else {

foreach (@residents) {
$name = "\\@";
$name .= $1 if ($_=~ /((?<=rr_)\w+)/);
push @clear_names, $name;
}



$ret_value = join (" ",@clear_names);

return ($ret_value);



Diese Routine wird dann wie schon beschrieben hier aufgerufen:


{fhem ("set whale_telegram message ". '{(com_control)}' ."  Morgen müssen folgende Tonnen rausgestellt werden \n$tonne")};


Im Ergebnis steht jetzt in der Nachricht


\@Max \@Johanna Morgen müssen....


So, das ist das volle Bild und ich mit meinem Latein am Ende 😩

Viele Grüße,
Max



Sirel

Ok, jetzt funktioniert es.
Beim zusammensetzen des strings dar das @ nicht Maskiert werden.
Wenn also einfach nur ein @ vor den Namen gestellt wird, dann funktioniert es so, wie Damian es vorgeschlagen hat.

@Damian: Könntest du mir kurz erklären, warum es so funktioniert und anders nicht?

Vielen Dank und Grüße,

Max

Damian

Warum es beim set-Befehl nicht klappt, kann ich dir nicht sagen.

Das Maskieren von @ über \@ ist nur in Perl notwendig, wenn man einen String in doppelte Anführungszeichen setzt, also "\@", sonst wird es als Arrayangabe interpretiert. Beim einfachen Anführungszeichen wie z.B. '@' hat Perl kein Problem damit.

Beim DOIF wird bei: 

(set xxxx_telegram send {(com_control)} blablabla)

{(com_control)} vom DOIF interpretiert. Der Ausdruck kommt beim set-Befehl nicht mehr in der ursprünglichen Form an, sondern vom DOIF aufgelöst.

Beim notify dagegen wird {(com_control)} bis zum set durchgereicht und der set-Befehl wertet den Ausdruck aus - offenbar passt da was nicht.

Allerding dürfte dann z. B.

set test {('@blabla')}

in der Kommandozeile bei dir auch nicht funktionieren, bei mir wird aber der test-Dummy korrekt mit @blabla belegt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sirel

Hallo Damian,

wie immer, besten Dank für Deine Hilfe und Erklärung!
Bis demnächst mal wieder!

Viele Grüße,
Max

Sirel

Übrigens:
Im Perl-DOIF funktioniert die Lösung wie oben beschrieben leider nicht.

Konkret geht es um dieses Stück Code:

set_Exec("$DEVICE_timer",'$count == 0 ? 300 : (300/$count)','fhem_set ("xxxxtelegram message " . {(com_control)} . " {(AttrVal(\"$DEVICE\",\"alias\",\"\"))} ist noch offen")','$count < 9'); set_State("cmd_1",0)

Gibt's da noch eine weitere Spielart?

Viele Grüße,
Max

betateilchen

Irgendwann solltest Du Dir das Wissen erarbeiten, die Unterschiede zwischen "perl Code" und "FHEM Befehl" zu verstehen.
Danach kannst Du Dich damit beschäftigen, warum das in DOIF nochmal anders/komplizierter verarbeitet wird.

Dann brauchst Du künftig wahrscheinlich auch nicht mehr 3 Threads mit der gleichen Frage zu eröffnen :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Sirel

Hallo Betateilchen,
Danke für Deinen Hinweis. An dem Thema arbeite ich mich gerade ab.
Für jemanden, der sich nicht durchgehend mit der Fragestellung und der Komplexität beschäftigt, ist es teilweise nicht so eingängig wie für Dich als Vollprofi.

Vielleicht magst du mich aber dennoch erleuchten warum es nicht funktioniert?

Ich habe verstanden, dass bei strings in ' ' Sonderzeichen wie das @ für Arrays nicht interpretiert bzw ausgewertet werden. Quasi so, als wenn der String " " steht, aber das @ mit einem backslash maskiert ist. Soweit richtig?

Jetzt steht der Rückgabewert in " ", weil in der Klammer Fhem gesprochen wird. Demnach muss das  @ markiert werden, weil es vom Set sonst ausgewertet wird.  ... oder der returnstring muss in ' ', damit das nicht passiert.
Mache ich das, bekomme ich eine Fehlermeldung.
Und warum tauchen dann auch noch manchmal Punkte zwischen den Anführungszeichen auf?

Das zu verstehen, würde mir sehr helfen.

Viele Grüße und vorab,
Max


Damian

#11
Zitat von: Sirel am 01 Juni 2021, 19:14:11
Übrigens:
Im Perl-DOIF funktioniert die Lösung wie oben beschrieben leider nicht.

Konkret geht es um dieses Stück Code:

set_Exec("$DEVICE_timer",'$count == 0 ? 300 : (300/$count)','fhem_set ("xxxxtelegram message " . {(com_control)} . " {(AttrVal(\"$DEVICE\",\"alias\",\"\"))} ist noch offen")','$count < 9'); set_State("cmd_1",0)

Gibt's da noch eine weitere Spielart?

Viele Grüße,
Max

Ich gebe zu, dass man schon etwas Hintergrundwissen haben muss, um solche Perlkonstrukte zu beherrschen. Vor allem muss man wissen, dass DOIF-Perl im eigenen Package arbeitet, deswegen musst du vor Funktionen aus main :: voranstellen.

set_Exec("$DEVICE_timer",'$count == 0 ? 300 : (300/$count)','fhem_set ("xxxxtelegram message ".::com_control." ".::AttrVal("$DEVICE","alias","")." ist noch offen")','$count < 9'); set_State("cmd_1",0)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sirel

#12
Hallo Damian,
ok, das ist schon großes Kino 🍿😎
Gabs diese Fragestellung denn schon mal? Wäre nicht so, als wenn ich danach nicht schon gesucht hätte. In der Commandref steht dazu aber nichts, oder habe ich das überlesen?

Waren denn meine anderen Ausführungen soweit zutreffend? Und woher weißt man, dass man . " bspw nach com_control schreiben muss? Bzw es .:: und nicht nur :: wie ja auch von Dir beschrieben? Kann man das in kurzen Sätzen erklären oder ist das der Grund, weshalb man Informatik studieren kann?

Jedenfalls weiß ich jetzt, wo ich suchen muss, falls mich die Fragestellung noch einmal ereilen sollte.

Viele Grüße,
Max

Damian

#13
Zitat von: Sirel am 01 Juni 2021, 21:04:35
Hallo Damian,
ok, das ist schon großes Kino 🍿😎
Gabs diese Fragestellung denn schon mal? Wäre nicht so, als wenn ich danach nicht schon gesucht hätte. In der Commandref steht dazu aber nichts, oder habe ich das überlesen?

Waren denn meine anderen Ausführungen soweit zutreffend? Und woher weißt man, dass man . " bspw nach com_control schreiben muss? Bzw es .:: und nicht nur :: wie ja auch von Dir beschrieben? Kann man das in kurzen Sätzen erklären oder ist das der Grund, weshalb man Informatik studieren kann?

Jedenfalls weiß ich jetzt, wo ich suchen muss, falls mich die Fragestellung noch einmal ereilen sollte.

Viele Grüße,
Max

Es ist vieles nicht so einfach. Da in FHEM es immer wieder zwischen FHEM-Syntax und Perl Syntax hin und her geht.

Du kannst einen FHEM-Befehl auf verschiedene Art und Weisen zusammenbauen:

z. B.

so wird des String für die Ausführung in Perl zusammengebaut:

{'fhem ("set test "'.meine_funktion.")"}

und so geht es direkt über die set-Funktion, die ihrerseits inzwischen auch Perl vor der Ausführung auswerten kann:

set test {(meine_funktion)}

Ein Punkt fügt in Perl einfach Zeichenketten zusammen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Sirel

In der Tat, der Wechsel zwischen FHEM und Perl ist schon schwierig.

Naja, jetzt läuft alles so wie gewünscht. Nochmals allerbesten Dank für den super Support und das absolut geniale Modul!

Schönen Abend und bis bald,
Max