FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: harald654 am 21 Februar 2021, 12:14:00

Titel: [gelöst] Variablen in Userreading (bei DOIF)
Beitrag von: harald654 am 21 Februar 2021, 12:14:00
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))))}}
Titel: Antw:Variablen in Userreading (bei DOIF)
Beitrag 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.

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
Titel: Antw:Variablen in Userreading (bei DOIF)
Beitrag von: harald654 am 21 Februar 2021, 15:46:59
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).
Titel: Antw:Variablen in Userreading (bei DOIF)
Beitrag von: MadMax-FHEM am 21 Februar 2021, 16:13:26
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
Titel: Antw:Variablen in Userreading (bei DOIF)
Beitrag von: harald654 am 22 Februar 2021, 19:08:27
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)
}