[gelöst] Variablen in Userreading (bei DOIF)

Begonnen von harald654, 21 Februar 2021, 12:14:00

Vorheriges Thema - Nächstes Thema

harald654

Hallo,

ich hab für die Steuerung eines Heizkörpers ein DOIF erstellt, in diesem will ich in einem Userreading den Stellwert des Thermostats berechnen (abhänig von einem anderen Thermostat).
Um den Code übersichtlicher und kürzer zu machen hab ich Variablen verwendet, leider scheint das nicht zu funktionieren :/
Mein Code:
actuation_ofen:actuation.* {my $x1=AttrNum("Set_Hzng_WhnZmar","threshold_ofen_low",1); my $x2=AttrNum("Set_Hzng_WhnZmar","threshold_ofen_high",1); my $v=ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1); if ($v<$x1){my $xy=0} elsif ($v>$x2){my $xy=$v} else {my $xy=(0+(($x2-0)/(($x2-$x1))*($v-$x1)))}; $xy}
Die Fehlermeldung:
ZitatError evaluating Set_Hzng_WhnZmar userReading actuation_ofen: Global symbol "$xy" requires explicit package name (did you forget to declare "my $xy"?) at (eval 44838) line 1.

Erkennt jemand meine Fehler, ich habe doch die Variable $xy definiert??


Edit: wenn ich die Variabeln weglassen dann funktioniert es, aber dan wird der Code sehr unleserlich, und ich bekommen bestimmt Problemen wenn ich dort mal ein Device umbenenne will :/
actuation_ofen:actuation.* {if (ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1)<AttrNum("Set_Hzng_WhnZmar","threshold_ofen_low",1)){0} elsif (ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1)>AttrNum("Set_Hzng_WhnZmar","threshold_ofen_high",1)){ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1)} else {(0+((AttrNum("Set_Hzng_WhnZmar","threshold_ofen_high",1)-0)/((AttrNum("Set_Hzng_WhnZmar","threshold_ofen_high",1)-AttrNum("Set_Hzng_WhnZmar","threshold_ofen_low",1)))*(ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1)-AttrNum("Set_Hzng_WhnZmar","threshold_ofen_low",1))))}}

MadMax-FHEM

Naja ich denke: du hast zwar definiert ABER eben nur, wenn bestimmte Bedingungen durchlaufen wurden. Das xy am Ende wird aber IMMER "verwendet". Also einmal "vorne" definieren my $xy=""; und dann später eben zuweisen.

ABER: macht ein userReadings bei einem DOIF überhaupt Sinn? Also noch dazu wenn du Werte ANDERER Devices abfrägst/nutzt?

WEIL: ein userReadings wird ja nur "ausgeführt", wenn sich etwas bei dem Device tut, wo es "dranhängt"! Also beim DOIF. Solange beim DOIF nichts passiert, wird auch das userReadings nicht "beachtet"...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

harald654

Zitat von: MadMax-FHEM am 21 Februar 2021, 13:54:03
Naja ich denke: du hast zwar definiert ABER eben nur, wenn bestimmte Bedingungen durchlaufen wurden. Das xy am Ende wird aber IMMER "verwendet". Also einmal "vorne" definieren my $xy=""; und dann später eben zuweisen.
hmm, da ich in allen if-Zweigen (if, elsif und else) $xy definiert habe müsste es eigentlich immer definiert werden, oder habe ich hier einen Denkfehler?
Ich hab es mal mit deinem Hinweis versucht:
actuation_ofen:actuation.* {my $xy=""; my $x1=AttrNum("Set_Hzng_WhnZmar","threshold_ofen_low",1); my $x2=AttrNum("Set_Hzng_WhnZmar","threshold_ofen_high",1); my $v=ReadingsNum("Set_Hzng_WhnZmar","actuation",1,1); if ($v<$x1){my $xy=0} elsif ($v>$x2){my $xy=$v} else {my $xy=(0+(($x2-0)/(($x2-$x1))*($v-$x1)))}; $xy}
Dadurch wird keine Fehlermeldung mehr angezeigt, aber es wird für das Userreading "actuation_ofen" immer nur "" eingetragen, die if-Funktion wird wohl garnicht durchlafen. Nur warum nicht?
Zitat
ABER: macht ein userReadings bei einem DOIF überhaupt Sinn? Also noch dazu wenn du Werte ANDERER Devices abfrägst/nutzt?

WEIL: ein userReadings wird ja nur "ausgeführt", wenn sich etwas bei dem Device tut, wo es "dranhängt"! Also beim DOIF. Solange beim DOIF nichts passiert, wird auch das userReadings nicht "beachtet"...

Gruß, Joachim
Das passt soweit, in dem DOIF triggere ich auf das eigene Reading "actuation", welches von einem anderem Modul befüllt wird. Das Userreading "actuation_ofen" soll sich nur bei einer aktualisierung des Reading "actuation" aktualisieren.
Ich hab die Berechnung von "actuation_ofen" aus dem DOIF raus und in das Userreading genommen, da ich für "actuation_ofen" eine Interpolation berechne und mir das zu umständlich im DOIF-Bereich war (bzw. hab es dort nicht hinbekommen).

MadMax-FHEM

#3
Naja, du definierst es schon auf jeden Fall aber erst, wenn auch die if/elsif/else durchlaufen sind. Evtl. stört das, weil beim "Prüfen" eben das nicht gemacht wird und somit "fehlt" dann eben die Definition...
Bin aber kein Experte was den Ablauf des Syntax-Checks bzw. Perl angeht...


EDIT: äh, jetzt wo ich unten den EDIT schreibe: die "Gültigkeit" von deinem my $vx= INNERHALB der if/elsif/else ist nat. auch nur INNERHALB! D.h. "außerhalb" gibt es die Variable (dann) nicht (mehr)!

Also wenn du das my $xy="" vorne drin hast, dann muss das "hinten" nat. überall raus.
EDIT2: also das 'my' natürlich nur ;)
EDIT:
Zitat
else {my $xy=(0+(($x2-0)/(($x2-$x1))*($v-$x1)))}
D.h. es wird "kurzzeitig" eine lokale (innerhalb von if/elsif/else) Variable xy angelegt und mit dem erwarteten Wert belegt aber beim "Verlassen der Klammer" wieder "zerstört". Die "vorher" definierte Variable xy hat aber immer noch "" als Wert ;)

Ich hab jetzt nicht geprüft was du da so machst. Aber evtl. würde es helfen, wenn du Logausgaben machst. Also alle "abgefragten" Variablen ausgibst und dann innerhalb der if/elsif/else Zweige eben auch noch mal, damit du siehst wo du "langläufst"...

Also das userReadings hängt jetzt nicht (mehr) am DOIF sondern (wieder) am "Original-Device" wo auch das "Trigger-Reading" ist!?

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

harald654

Vielen Dank für die ausführliche Erklärung,
hab es so umgesetzt wie von dir beschrieben und jetzt läuft es  8)
actuation_ofen:actuation.*
{
my $xy="";
my $x1=AttrNum("Set_Hzng_WhnZmr","threshold_ofen_low",1);
my $x2=AttrNum("Set_Hzng_WhnZmr","threshold_ofen_high",1);
my $v=ReadingsNum("Set_Hzng_WhnZmr","actuation",1,0);
if ($v<$x1){$xy=0} elsif ($v>$x2){$xy=$v} else {$xy=(0+(($x2-0)/(($x2-$x1))*($v-$x1)))};
sprintf("%.0f",$xy)
}