[Gelöst] Wie kann man Variablen zusammensetzen?

Begonnen von mi.ke, 17 Februar 2018, 14:31:47

Vorheriges Thema - Nächstes Thema

Otto123

#15
Moin,

also ein letzter Versuch. Es gab von Dir drei Fragen:
Wie kann man Variablen zusammensetzen?
Da gibt es doch bestimmt einen normierte Schreibweise?
Kann mir bitte jemand einen Tip geben?

Die habe ich versucht zu beantworten. Und zwar nicht nur mit "Aussagen", sondern ich habe nebenbei alles auch getestet und Dir etwas nachvollziehbares geliefert.

Dein letzter Code:$A = (ReadingsVal("Text_$NAME","state",""));Mein letzer Code:{Log 1, ReadingsVal($NAME,"Text_".$NAME,"") }

Siehst Du den Unterschied zwischen "Text_$NAME" und "Text_".$NAME beim genauen Hinsehen?

Aber beide Schreibweisen sind, wie ich Dir in den anderen Beispielen nachvollziehbar gezeigt habe, die Antwort auf Deine erste Frage.
Die Antwort auf Deine zweite Frage lautet: Ja, aber - Es hängt von der genauen Anwendung ab. Leider!

Ich weiß das auch bloß nicht exakt, ich muss es testen. Deswegen war meine erste Antwort vielleicht nicht exakt auf Dein Anwendungsbeispiel zugeschnitten. Der Test mit ReadingsVal war etwas aufwendiger und ich habe etwas umständlich gedacht und mir erst Dummys und notify gebaut.
Aber eigentlich war ja die allererste Antwort von KernSani schon die richtige.  :D

Und die Kopie eine Fehlermeldung als Ergänzung zu "es funktioniert nicht" ist doch nicht zuviel verlangt. Man bekommt doch eine Fehlermeldung, wenn man das mit ReadingsVal falsch im Editor einträgt.

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

mi.ke

#16
Hi Otto,
danke das Du noch mal so genau auf das Thema eingegangen bist.

Zitat von: Otto123 am 18 Februar 2018, 07:58:19
Siehst Du den Unterschied zwischen "Text_$NAME" und "Text_".$NAME beim genauen Hinsehen?

Ich hatte ja geschrieben, dass diese Schreibweise eine gangbare Lösung ist.

Der Vorschlag von KernSani bezog sich, wie ich es verstanden hatten, auf die Punktierung.
Der Schlüssel scheint aber das unterschiedliche setzen der Anführungszeichen zu sein.

In Deinem "Zeit-Beispiel"  . . .
{"Zeit: $hour"}
. . . sind Text und und Variable innerhalb der Anführungszeichen. Und es funktioniert ja auch.
Beim lesen des Readings oder des Attributes muss die Variable aber anscheinend zwingend ausserhalb der " "  stehen und der Text wird maskiert.

Zusammenfassend:
Wie schon am Anfang des Thread erwähnt, können in solchen Fällen die Textbausteine in Variablen geschrieben werden. Dann lassen sie sich einfach hintereinander schreiben (mit und ohne Punkt)
my $vA = "vorher_";
my $nA = "_nacher";
my $A_NAME = "$vA$NAME$nA";
$A = (ReadingsVal("$A_NAME","state",""));


Wie jetzt gelernt, muss die Variable beim direkten verheiraten ausserhab der  " " stehen
$A = (ReadingsVal("vorher_".$NAME."_nachher","state",""));
und mit Punkt(en) maskiert werden.

Den Post lass ich bis heute Abend offen, falls inhaltlich etwas hinzuzufügen wäre. Dann schließ ich ihn als gelöst.

Vielen Dank an Otto und KernSani für die Unterstützung.

Cheers
mi.ke
FHEM 5.9 | RPi4 + 5 x RPi(Z) + FB7590 + FB 6890 LTE via LAN und WAN (VPN) verbunden.
2 x CUL868 + 3 x RFXTRX(e) + 6 x HMwLanGW + 4 x z2tGw + 5 x LGW + 2 x IRBlast + CO2 +++
FS20, FHT, FMS, Elro(mod), CM160, Revolt, LGTV, STV, AVR, withings, HM-sec-*, HM-CC-RT-DN, AMAD, PCA301, arlo, Aqara

CoolTux

Zitat von: mi.ke am 18 Februar 2018, 13:32:37
Wie jetzt gelernt, muss die Variable beim direkten verheiraten ausserhab der  " " stehen
$A = (ReadingsVal("vorher_".$NAME."_nachher","state",""));
und mit Punkt(en) maskiert werden.

Cheers
mi.ke

Der Punkt maskiert nicht, er verbindet.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Otto123

Ich nerv nochmal. ;D
Ich habe noch ein wenig recherchiert. Wenn ich das richtig verstanden habe, ist in Perl ist ja eigentlich bei Strings sowohl Interpolation als auch concatenation möglich.
Interpolation  -> my $a = "Hallo"; my $b = "$a Welt"
concatenation -> my $a = "Hallo"; my $b = $a." Welt"
$b enthält in beiden Fällen "Hallo Welt"

Deswegen noch meine Fragen in die Runde:
- Ist es so, dass die Pflicht zur Verwendung von concatenation quasi nur eine Einschränkung von ReadingsVal & Co ist?
- Oder liegt der Grund woanders?
- Muss man generell probieren wie es geht?
- Oder ist concatenation immer vorzuziehen?

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

uelpenich

Hallo,
ich bin sehr an diesem Thema interessiert und habe diesen Thread mehrfach rauf und runter gelesen, ohne jedoch alles zu verstehen. Ich habe gelernt, wie man mit verschiedenen Hilfskonstruktionen das Zusammensetzen von Zeichenketten und Variablenwerten bewerkstelligt. Ich bin aber überfordert, diese Beispiele konkret in eine Notify Definition einzusetzen.

Meine Aufgabenstellung ist:
ich habe 8 1-Wire Thermometer, deren Temperaturwerte auf 8 Gruppenadressen ins KNX übertragen werden sollen.
Diese acht 1-Wire Thermometer sind wie folgendes Beispiel definiert:
define EG_HKV_RL_Bad OWTHERM DS18B20 0E3979A21903 300
setuuid EG_HKV_RL_Bad 5d8dbae6-f33f-4cb6-e9c6-c1fc76a2af96afa7
attr EG_HKV_RL_Bad IODev myOWFS
attr EG_HKV_RL_Bad event-on-update-reading state
attr EG_HKV_RL_Bad group EG_HKV
attr EG_HKV_RL_Bad model DS18B20
attr EG_HKV_RL_Bad room Erdgeschoss
attr EG_HKV_RL_Bad stateFormat {sprintf("%.1f",ReadingsVal($name,"temperature",0))."°C"}
attr EG_HKV_RL_Bad tempConv onkick
attr EG_HKV_RL_Bad tempHigh 73
attr EG_HKV_RL_Bad tempLow -1
attr EG_HKV_RL_Bad tempOffset -0.69
attr EG_HKV_RL_Bad tempUnit Celsius


Der reguläre Ausdruck im Suchmuster des Notify sowie die Variablen im Commandteil erlauben es mir, mit einem Notify mehrere Temperaturwerte an die KNX Gruppenadressen zu übertragen.

Die zugehörigen KNX Gruppenadressen habe ich so defniert:
define GA_EG_HKV_Bad KNX 2/6/1:dpt9.001:x2
setuuid GA_EG_HKV_Bad 5e384361-f33f-4cb6-7e03-d4c07a73a4926e00
attr GA_EG_HKV_Bad IODev knx
attr GA_EG_HKV_Bad group GA_EG_FBH
attr GA_EG_HKV_Bad room Erdgeschoss FBH,Erdgeschoss
attr GA_EG_HKV_Bad slider 18,1,30
attr GA_EG_HKV_Bad stateFormat {sprintf("%.1f",ReadingsVal($name,"x2-set",0))."°C"}
attr GA_EG_HKV_Bad webCmd state


Ich habe eine Lösung für das Problem "wasvornedran_$NAME" gefunden.
Deswegen haben die KNX Gruppenadressen etwas "vornedran" (EG_HKV_RL_Bad -> GA_EG_HKV_RL_Bad)

Mein Notify sieht so aus:
define EG_HKV_GA notify EG_HKV_.*T:.* set GA_$NAME $EVTPART1
setuuid EG_HKV_GA 5e384361-f33f-4cb6-0e97-116a28f403cec6f4
attr EG_HKV_GA group EG_FBH
attr EG_HKV_GA room Erdgeschoss FBH,Erdgeschoss


Alles funktioniert wie gewünscht.

Und nun zu meiner Frage:
Wenn ich aus taktischen Gründen meinen KNX-Devicenamen etwas anhängen will "$NAME_etwashintendran", wie muss ich dann den Command Teil im Notify schreiben?

PS: ich habe viel probiert und möglicherweise vor lauter Bäumen den Wald nicht gesehen. Das Problem liegt wohl daran, dass Perl die Variablennamen nicht nach hinten abgrenzt und daher nicht entscheiden kann, wo der Variablennamen aufhört und das "hintendran" beginnt. Die Unterscheidung zwischen "vornedran" und dem Variablennamen ist durch das Dollarzeichen gegeben.
Ich habe keinen Weg gefunden, den Command Teil wie in diesem Thread diskutiert mit "" . so zu formulieren, dass es funktioniert.

Christoph Morrison

Zitat von: Otto123 am 19 Februar 2018, 09:09:59
Deswegen noch meine Fragen in die Runde:
- Ist es so, dass die Pflicht zur Verwendung von concatenation quasi nur eine Einschränkung von ReadingsVal & Co ist?
- Oder liegt der Grund woanders?
- Muss man generell probieren wie es geht?
- Oder ist concatenation immer vorzuziehen?

Gut dass uelpenich den Thread wiederbelebt hat  8)

Die Antwort ist 2 - der Grund liegt woanders. Es liegt im Beispiel von mi.ke daran, dass _ und der Variablenname zusammenhängen und der Perl-Interpreter dann nicht mehr identifizieren kann, wo die Variable aufhört. Folgende Beispiele verdeutlichen es - man achte auf Variante 0 und 1:


use v5.10;

my $var = "pedo";
say "Variante #0: ", "$var_mellon a minno";
say "Variante #0: ", "${var}_mellon a minno";
say "Variante #2: ", "$var mellon a minno";
say "Variante #3: ", $var . " mellon a minno";


ergibt:


Variante #0:  a minno
Variante #0: pedo_mellon a minno
Variante #2: pedo mellon a minno
Variante #3: pedo mellon a minno


In Variante 0 ist es dem Perl-Interpreter nicht möglich $var zu erkennen, da $var_mellon ein erkanntes Lexem ist, dem aber kein Speicherinhalt zugewiesen wurde.

Mit use warnings meckert der Interpreter dann auch:

Name "main::var_mellon" used only once: possible typo at scratch_2.pm line 5.
Use of uninitialized value $var_mellon in concatenation (.) or string at scratch_2.pm line 5.


Zu deiner Frage, uelpenich:
Zitat
Wenn ich aus taktischen Gründen meinen KNX-Devicenamen etwas anhängen will "$NAME_etwashintendran", wie muss ich dann den Command Teil im Notify schreiben?

$NAME_etwashintendran muss ${NAME}_etwashintendran heißen, dann klappt's auch mit dem Appendix.

Siehe auch:
Interpolating Functions and Expressions Within Strings



uelpenich

#21
Zitat$NAME_etwashintendran muss ${NAME}_etwashintendran heißen, dann klappt's auch mit dem Appendix.
Nachdem das {Klammern} des Variablen Namens gut funktioniert hat, wird es in der jetzigen Perl Version als "veraltet" gekennzeichnet mit tötlichem Ausgang ab Perl 5.30
Zitat2020.10.25 20:38:00 1: PERL WARNING: Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through in regex; marked by <-- HERE in m/^(GA_${ <-- HERE NAME})$/ at fhem.pl line 1331.
2020.10.25 20:38:00 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:32 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:34 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:35 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:36 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:37 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:38 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:39 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:41 3: EG_HKV_GA return value: Please define GA_${NAME} first
2020.10.25 20:44:42 3: EG_HKV_GA return value: Please define GA_${NAME} first
Wie würde ein  "escaped left brace in regex" aussehen?

Otto123

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

uelpenich

Danke für die schnelle Antwort.
Es scheint nicht so einfach zu sein. Im Logfile tauchen dann folgende Fehlermeldungen auf:
2020.10.25 23:11:10 3: EG_HKV_GA return value: Please define GA_$\{NAME} first

Um den Zusammenhang darzustellen:
#
define GA_EG_HKV_VL_alles KNX 2/6/9:dpt9.001:x2
setuuid GA_EG_HKV_VL_alles 5e388825-f33f-4cb6-90f5-6788ebbb57e607a1
attr GA_EG_HKV_VL_alles IODev knx
attr GA_EG_HKV_VL_alles group GA_EG_FBH
attr GA_EG_HKV_VL_alles room Erdgeschoss FBH,Erdgeschoss
attr GA_EG_HKV_VL_alles webCmd state
attr GA_EG_HKV_VL_alles widgetOverride x2:slider,18,1,30
## attr GA_EG_HKV_VL_alles slider 18,1,30
## attr GA_EG_HKV_VL_alles stateFormat {sprintf("%.1f",ReadingsVal($name,"x2-set",0))."°C"}
#
# --------------------- Notify zum Befüllen der GAs ----------------------------------
#
#   etwasvornedran_${NAME}   ist veraltet und funktioniert nicht mehr
#   etwasvornedran_$NAME      funktioniert
#   $NAME_etwashintendran     eine Lösung wird gesucht, das Klammern des Variablennamen ${NAME} ist veraltet
#
define EG_HKV_GA notify EG_HKV_.*T:.* set GA_$NAME $EVTPART1
setuuid EG_HKV_GA 5e384361-f33f-4cb6-0e97-116a28f403cec6f4
attr EG_HKV_GA group EG_FBH
attr EG_HKV_GA room Erdgeschoss FBH,Erdgeschoss
#

Otto123

Ich bin nicht so der Perlexperte - aber ich lese die Warnung irgendwie anders.

Erstmal sollte der Code so noch funktionieren.
Dein Code ist kein regex, aber die Warnung bezieht sich auf ein regex - eventuell ist das ein sekundärer Effekt?
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

CoolTux

Mich würde die komplette Fehlermeldung interessieren

Zitat von: uelpenich am 25 Oktober 2020, 22:18:20
2020.10.25 21:22:01 1: PERL WARNING: Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.30), passed through in regex; marked by <-- HERE in m/^(GA_${ <-- HERE NAME})$/ at fhem.pl lin

da fehlt die Zeilennummer an Ende.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Otto123

Beim wiederholten lesen fällt mir auf: steht denn irgendwo, dass der FHEM Interpreter anstatt set GA_$NAME $EVTPART1 set GA_${NAME} $EVTPART1 verarbeiten kann (muss)?

Sollte man da nicht besser gleich auf Perl Ebene wechseln?
{my $dev="GA_${NAME}";;fhem("set $dev  $EVTPART1")}
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

uelpenich

Zitatda fehlt die Zeilennummer an Ende.
Ich habe oben die Zeilennummer und die Folgezeilen nachgetragen.

ZitatErstmal sollte der Code so noch funktionieren.
Dein Code ist kein regex, aber die Warnung bezieht sich auf ein regex - eventuell ist das ein sekundärer Effekt?
Der Code funktioniert nicht mehr, das kann man an den folgenden Fehlermeldungen sehen:
Zitat2020.10.25 20:38:00 3: EG_HKV_GA return value: Please define GA_${NAME} first
Ich lese diese Fehlermeldung so, dass die Variable nicht mehr evaluiert wird.

ZitatBeim wiederholten lesen fällt mir auf: steht denn irgendwo, dass der FHEM Interpreter anstatt set GA_$NAME $EVTPART1 set GA_${NAME} $EVTPART1 verarbeiten kann (muss)?
Die Notation der Variablen war ein Vorschlag von Christoph Morrison weiter oben
(https://forum.fhem.de/index.php/topic,84511.msg1020936.html#msg1020936)
Das hat bis zum letzten Update (apt-get update) funktioniert.

Christoph Morrison

Schätze mal uelpenich hat nicht die letzte Version der fhem.pl.

In einer älteren Version steht dort:
if (($op eq  "=" && $val =~ m/$lre/s) ||

Glaskugel: devspec2array macht aus GA_${NAME} ein Regex und da sind die Klammern nicht escaped.

Otto123

Ihr müsst meine Anmerkung nicht ernst nehmen, aber sie ist gut gemeint ;)

Wenn etwas funktioniert obwohl es nicht in der Doku steht, kann es sich auch um einen Fehler handeln.
Bei Softwareentwicklung gilt: Es besteht kein Rechtsanspruch auf die Beibehaltung von Fehlern.

Es existiert eine einfache und dokumentierte Lösung. Also warum das Pferd rückwärts reiten?

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