Lebensdauer von Variablen in Subroutinen

Begonnen von LCN-User, 10 Mai 2013, 22:03:50

Vorheriges Thema - Nächstes Thema

LCN-User

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

herrmannj

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

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

LCN-User

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

MisterEltako

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
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

herrmannj

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

herrmannj

@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

LCN-User

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



LCN-User

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.

herrmannj

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 ;-)

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

LCN-User

Danke!

Das ist ja äußerst effektiv.