FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: LCN-User am 10 Mai 2013, 22:03:50

Titel: Lebensdauer von Variablen in Subroutinen
Beitrag von: LCN-User am 10 Mai 2013, 22:03:50
Hallo,

in einer Subroutine sollen abhängig von der übergebenen Variable ein oder mehrere Bits eines 8bit-Worts eines Arrays selektiv gesetzt werden. Ein Notify übergibt eine 8bit-Maske mit den betreffenden Bits sowie den eigentlichen Datenwert als 8bit-Wort. Da die Subroutine von verschiedenen Notifys mit wechselnden MAsken aufgerufen wird, soll der letzte Wert des ermittelten 8bit-Worts in der Subroutine gespeichert werden.

Notify und Subroutine (in 99my_util abgelgt) sehen folgendermaßen aus:
FensterBadWC {
   my $vm = 216;
   my $BinMask = 0b11110011;
   my $BinVal  = 0b00001100;
   { if ($EVENT eq "closed") {$BinVal = 0b00000000;}
     elsif ($EVENT eq "tilted") {$BinVal = 0b00000100;}
   }
   LinHK_BinaryState($vm, $BinMask, $BinVal);
}

sub LinHK_BinaryState
{
   my $lastBinaryStatus;
   my $LCN_vm     = shift;
   my $BinaryMask = shift;
   my $BinaryVal  = shift;
   my $vm_Min     = 210;
   my $vm_Index   = $LCN_vm - $vm_Min;
   my @BinaryStatus;

   $BinaryStatus[$vm_Index] = ($lastBinaryStatus & $BinaryMask) | $BinaryVal;
   $lastBinaryStatus = $BinaryStatus[$vm_Index];

   { GetHttpFile("192.168.178.5:8000", "/vm_bin?sgmt=0&module=$LCN_vm&value=$lastBinaryStatus"); }
return("0")
}


Jetzt habe ich zwei Probleme:
1. Der Trigger setzt zwar die richtigen Bits, löscht aber die von anderen Notify's gesetzten Bits. Geht der Inhalt der in der Sub lokal definierten Variablen @BinaryStatus und $lastBinaryStatus beim Verlassen der Subroutine verloren? Wenn ja, wie kann ich den Inhalt erhalten?
2. Ein Debuggen der Subroutine klappt nicht. Wenn ich 'log 3,"..."' einfüge, erfolgt keine Ausgabe in die fhem.cfg.

Gruß, LCN-USer
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: herrmannj am 10 Mai 2013, 22:44:30
Hallo LCN-USer,

war auch gerade an einem ähnlichen Punkt. FHEM sorgt vermutlich für einige neue Perl Skills im Land ;-)

Die mit "my" definierte Variable hat nur den scope der sub (bzw des evals). Beim verlassen der Routine verliert sie die Gültigkeit. http://www.perlmonks.org/?node_id=66677 (//www.perlmonks.org/?node_id=66677)

Variante #1:
Definition mit "our" in der sub - entspricht global, damit ist die Lebenserwartung die des Programms.

Variante #2:
Definition mit "my" im Kopf der 99_myUtil, scope im Modul ...

Variante #3:
Ein Device (ggf einen Dummy) als Zwischenspeicher benutzen. Mit userReadings Werte setzen mit RadingsVal zu Beginn Deiner sub wieder einlesen.

#3 ist meine derzeitige Präferenz weil: die Werte damit theoretisch einen Neustart des Programms überleben. (Allerdings für mich noch nicht komplett save: wie es scheint sind die readings teilweise direkt nach Programmstart noch nicht verfügbar). Die Werte sind "an eine Instanz" gekoppelt (zuviel OOP? ;-). Last but not least: das Device / der Dummy kann die Werte so auch via stateFormat visualisieren - wenn gewünscht.

Das debuggen sollte funktionieren. Grosses "L" bei Log und zum debuggen am besten Log 1, "...". Die Zahl ist der verbose Level, 1 geht immer und nach dem debuggen fliegt es vermutlich wieder raus.

viele Grüße
herrmannj
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: LCN-User am 10 Mai 2013, 22:52:17
Hallo hermannj,

das mit der Lebensdauer habe ich inzwischen auch herausgefunden. Aber die Lösungen von dir sind klasse.

Variante 1: habe ich mal eben ausprobiert - 2x 'my' durch 'our' ersetzen geht ja schnell - und es läuft wie gewünscht!
Variante 3: da habe ich ein wenig Schwierigkeiten.

Eine ähnliche Frage habe ich wegen Übernahme einer via httpget eingelesenen Variable gestellt. Da bekomme ich keinen Wert in den Dummy, aber wahrscheinlich mache ich es nicht richtig. Kannst du mir bei der Formulierung behilflich sein?

Danke, LCN-User
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: MisterEltako am 10 Mai 2013, 23:00:23
Oder du definierst die Variable so im Kopfbereich der 99_Utils.pm oder 99_myUtils.pm:

package main;
use strict;
use warnings;
use POSIX;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

#------------------------------------------------------------------------------------------------
my $variable="";
#--------------------------------------------------------------------------------------

sub ....{
deine Funktion}

Finde ich am einfachsten...

MfG, MisterEltako
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: herrmannj am 10 Mai 2013, 23:01:25
ZitatKannst du mir bei der Formulierung behilflich sein?

... klar gern. (Disclaimer: der perl compiler in meinem Brain ist alpha ;-)

Wo stehst Du denn ? Bekommst Du die Werte die Du speichern möchtest in eine lokale Variable und es scheiter am setzen auf dem Dummy ?

Ps, ich habe überschneidend nochmal im Beitrag oben die Infos zum Log ergänztz.

viele Grüße
herrmannj
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: herrmannj am 10 Mai 2013, 23:06:15
@MisterEltako

Yes, das war #2.

Auf die Art überleben die Werte aber keinen Neustart. Wenn das für den Logik-Ablauf OK ist sehe ich das genauso wie Du; the easiest way!

Grüße
herrmannj
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: LCN-User am 10 Mai 2013, 23:17:44
Zitat von: herrmannj schrieb am Fr, 10 Mai 2013 23:01Bekommst Du die Werte die Du speichern möchtest in eine lokale Variable und es scheiter am setzen auf dem Dummy ?
Ja, ich lese den Wert aus einem anderen System ein. Dieses Define holt sich die vom LCN-Bussystem zur Verfügung gestellte Temperatur und gibt sie als Text aus:
+*00:10 {
   my $OutsideTemp = GetHttpFile("192.168.178.5:8000","/replacestate?src=FHEM_Data.html");
   log 3,"Aussentemperatur = $OutsideTemp";
}

Ich habe nach Hinweis in einem anderen Thread folgenden Dummy definiert
Define MyTemp dummy
attr MyTemp userReadings $OutsideTemp

Mir fällt jetzt gerade ein, daß das Format von $OutsideTemp im Moment noch String ist. Muss ich noch in eine Zahl umwandeln. Wie komme ich nun generell an den Inhalt des Dummys heran?

Gruß, LCN-User


Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: LCN-User am 10 Mai 2013, 23:20:48
Zitat von: herrmannj schrieb am Fr, 10 Mai 2013 23:06Auf die Art überleben die Werte aber keinen Neustart. Wenn das für den Logik-Ablauf OK ist sehe ich das genauso wie Du; the easiest way!
IN meinem Fall würde bereits das Öffnen/Schliessen eines Fensters den korrekten Status für die Gesamthausanzeige wieder herstellen. Ich werde mich aber sicher demnächst mit den devices beschäftigen.
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: herrmannj am 12 Mai 2013, 13:32:50
Hi LCN-User,

ZitatWie komme ich nun generell an den Inhalt des Dummys heran?

Das ist einfach. (und btw: http://fhem.de/commandref.html#perl (//fhem.de/commandref.html#perl) ;-)

Innerhalb des at:
fhem ("set MyTemp $OutsideTemp");

Perl Variablen sind (wie php) typenlos, also dont worry bzgl String oder float.

Nachtrag: das attr MyTemp userReadings $OutsideTemp vom dummy schmeiß wieder raus - das bringt hier nichts.

viele Grüße
herrmannj
Titel: Aw: Lebensdauer von Variablen in Subroutinen
Beitrag von: LCN-User am 12 Mai 2013, 17:31:45
Danke!

Das ist ja äußerst effektiv.