[gelöst] InternalTimer -> Lerne Perl anhang eines Codes

Begonnen von HoTi, 10 Juni 2015, 14:01:14

Vorheriges Thema - Nächstes Thema

HoTi

Hallo zusammen,

ich versuche ich gerade an Perl. Ich habe ein Code von Elektroluch aus diesem Forum. Diesen möchte ich von 1 auf mehrere Rollos erweitern.

Eine codezeile habe ich nicht verstanden. Hier wird eine Sub Funktion aufgerufen:

ZitatInternalTimer(gettimeofday()+ $fahrzeit, "Markise_Stop", $hash, 0);

Markise_Stop. Wie kann ich jetzt dieser Funktion noch Variablen übergen? Irgendwie mit dem Hash, aber da habe ich nicht so viele Anfängertauglichen Infos gefunden.

Wenn ich das richtig verstanden habe soll ich meinen eigenen Hash machen und den FHEM Hash da integrieren.

Und da weiß ich nicht mehr weiter.
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Dietmar63

Wenn du ein eigenes Modul geschrieben hast, hast  du ein $hash schon zur Verfügung.

Mit

$hash->{key1} = "Wert1";
$hash->{key2} = "Wert2";


kannst du dir Dinge in $hash (assoziatives Array, in perl halt Hash genannt) merken.

Markise_Stop ist so zu diefinieren:


sub Markise_Stop ($) {
my ($hash) = @_;

print  $hash->{key1};   # liefert "Wert1"
...
}


Wenn du kein Modul gebaut hast kannst du in 99_util $hash so erzeugen(genau genommén handelt es sich um eine Refferenz auf ein leeres Hash):


my $hash = {};


zu Hash gibt es im Netz viel Dokumentation im Netz.
Einfach nach perl Hash suchen.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

HoTi

Danke, das funktioniert! Aber wir verarbeite ich das weiter? Bekomme ja nur die Adressen

Zitatsub Ga_Schalter2_not($$$$)
{
my ($name,$event,$device_down,$device_up) = @_;
#my $hash = $defs{$name},$defs{$device_down},$defs{$device_up};
my $hash = {};
$hash->{NAME} = $defs{$name};
$hash->{DEVICE_DOWN} = $defs{$device_down};
$hash->{DEVICE_UP} = $defs{$device_up};
...

Zitat...
InternalTimer(gettimeofday()+ $fahrzeit, "Markise_Stop", $hash, 0);
...

Zitatsub Markise_Stop($$$)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $device_down = $hash->{DEVICE_DOWN};
my $device_up = $hash->{DEVICE_UP};
Log3($name,3,"ACHTUNG 99: name $name device_down $device_down device_up $device_up");
...
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Dietmar63

was meinst du nur die Adressen?
Welche Adressen?
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Dietmar63

ich glaube ich habe es verstanden:


my $device_down = $hash->{DEVICE_DOWN};
print  $device_down->{NAME};


$device_down  ist auch wieder ein hash, das je nach Inhalt(muss man wissen) abgefragt werden kann.
in Perl/fhem werden die Daten in einem riesigen hash of hash of hash of hash (beliebige Tiefe) abgelegt.

mit Log 3, keys %{$hash} kann man sich die Schlüssel eines hash ausgeben lassen und ggf. darüber iterieren. Ich hoffe die Syntax stimmt.
mit Dumper kann man sich ganze hash Bäume ausgeben - Syntax etwas wie Log 3, Dumper dump $hash oder  Log 3, Dumper dump \%hash (Google befragen oder fhem Code absuchen)
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

HoTi

ZitatACHTUNG 99: name HASH(0x88edb8) device_down HASH(0x87af20) device_up HASH(0x88e830)

Ich habe die 0x8... jetzt als adresse interpretiert. Sorry wenn das nicht stimmt.

Die 0x8... ist ja das Gerät. Wie bekomme ich jetzt den inhalt?
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Dietmar63

Zitat von: RettungsTim am 10 Juni 2015, 16:00:29


Ich habe die 0x8... jetzt als adresse interpretiert. Sorry wenn das nicht stimmt.

Die 0x8... ist ja das Gerät. Wie bekomme ich jetzt den inhalt?

ja, stimmt - siehe oben
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

HoTi

Danke das war fast zeitgleich. Bin jetzt nur noch am handy da dauert es etwas länger.

Kann leider erst morgen weiter machen. Aber mit den tipps komme ich schon mal weiter.

Vielen dank! Ich melde mich ob es klappt oder wo ich wieder was nicht verstanden habe.
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Elektrolurch

Hallo,

my $device_down = $hash->{DEVICE_DOWN};
würde ich vorsichtshalber aber so schreiben:
my $device_down = $hash->{'DEVICE_DOWN'};


Das $device_down ist ein String, und kein hash.
Und zwar ist das eine Kopie des Strings, der im  hash
$hash->{'DEVICE_DOWN'}
steht.


Elektrolurch
configDB und Windows befreite Zone!

HoTi

Hallo Elektrolurch,
Schön von dir zur lesen.

Wie kommst du darauf das das ein String sein soll? Ich bin schon der Meinungen das es so wie ich dein code umgeschrieben habe (lese oben ) ein Hash habe.

Habe es am Handy gerade ausprobiert. Oh man ist das ne tipper rei.
Aber es geht,  ohne die Anführungszeichen.

Jetzt muss ich mich um die anderen Probleme kümmen.

1. Position merken bei fhem neustart (z.b. Stromausfall)
2. Slider soll da stehen bleiben wo er ist.
3. Code vollständig verstehen. Hab heut schon viel gelernt.

Ich befürchte euch noch öffters zu brauchen.

Vielen dank euch beiden!
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Dietmar63

Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Elektrolurch

Hallo,
Zitat:
Aber es geht,  ohne die Anführungszeichen.

ein Hash wird mit einem (fast) beliebigen Text indiziert. Du könntest z.B. auch so was schreiben:

$hash->{mein_Vorname}

wenn Du aber das z.B. so schreibst:
$hash->{mein-Vorname}

versucht perl hier eine Substraktion durchzuführen.
Sobald Du also Irgendwelche Sonderzeichen in dem Indexs für den hash verwendest, würde ich den index in ' ' oder " " setzen, ihn also eindeutig als Stringkonstante kennzeichnen.
Das Du die Stringzeichen weglasssen kannst in bestimten Konstellationen, ist reine Freundlichkeit von perl.
Jetzt muss ich mich um die anderen Probleme kümmen.
Zitat:
1. Position merken bei fhem neustart (z.b. Stromausfall)
Wenn die Position in einem reading (bei mir ist es für die Markise ja ein dummy) steht, wird sie automatisch mit dem "save" - Befehl in das statefile geschrieben.

Das gilt aber grundsätzlich für alle devices in fhem.
Wenn Du das "save" automatisch auslösen möchtest, damit der letzte Status auch nach Neujstart wieder stimmt, dann  fügst Du entweder nach Abschluß einer Positionierung in den Code

fhem("save");
ein oder
definierst Dir z.B. ein at

define fhem_save_at at +01:00 save

oder
define fhem_save_at at +01:00 {fhem('save');; Log(1,"Konfig gesichert um $hour");;}

Mal so als Anregung.


2. Slider soll da stehen bleiben wo er ist.
Position des sliders = reading
Elektrolurch (auch aus OBB)
configDB und Windows befreite Zone!

HoTi

Danke euch beiden, ich denke ich habe jetzt schon viel gelernt aber es fehlt noch sehr viel.

Diesen Code finde ich jetzt mit euren Anmergungen irgenwie unschön. Das muss doch einfacher und besser gehen.
Perl meckert auch die dopplete Namensbenennung von $device_down und $device_up an, weil ich diese in sub Ga_Schalter2_not($$$$) schon habe :

Zitat
sub Markise_Stop($$$)
{
my ($hash,$device_down,$device_up) = @_;
my $name_hash = $hash->{NAME};
my $device_down_hash = $hash->{"DEVICE_DOWN"};
my $device_up_hash = $hash->{"DEVICE_UP"};

my $name = $name_hash->{NAME};
my $device_down = $device_down_hash->{NAME};
my $device_up = $device_up_hash->{NAME};

#Log3($name,3,"ACHTUNG 99: name $name device_down $device_down device_up $device_up");

my $mup = Value($device_up);
my $mdown = Value($device_down);
my $dt = 0;
my $aktpos = ReadingsVal($name,'Pos',0);
my $newpos;
#Log3($name,3,"ACHTUNG 3: mup $mup mdown $mdown");
if($mup =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp($device_up,'state',0));
fhem("set $device_up aus");
$newpos = $aktpos - (100 * $dt / ReadingsVal($name,'Einfahrzeit',0));
} # Die Markiese fährt bereis
elsif($mdown =~m/(ein|on).*/)
{
$dt = time() - time_str2num(ReadingsTimestamp($device_down,'state',0));
fhem("set $device_down aus");
$newpos = $aktpos + (100 * $dt / ReadingsVal($name,'Ausfahrzeit',0));
} # Die Markiese fährt bereis

$newpos = sprintf("%d",$newpos); # runden
$newpos = 0 if($newpos < 0);
$newpos = 100 if($newpos > 100);
#Log3($name,3,"$name _stop: dt $dt newpos $newpos");
readingsSingleUpdate($hash,'Pos',$newpos,0);
readingsSingleUpdate($hash,'state',"Pos $newpos",0);
# alle timer löschen
RemoveInternalTimer($hash);   
return undef;
} # end sub Markise_Stop
###########################
Viele Grüße aus  Oberbayern
Tim (RettungsTim)

Dietmar63

dopplete Namensbenennung von $device_down und $device_up
ist dann kein Fehler mehr wenn du innerhalb eines Subs bei der zweiten Zuweisung das my weglässt.


if($mup =~m/(ein|on).*/) {
   $dt = time() - time_str2num(ReadingsTimestamp($device_up,'state',0));
   fhem("set $device_up aus");
   $newpos = $aktpos - (100 * $dt / ReadingsVal($name,'Einfahrzeit',0)); 
} elsif($mdown =~m/(ein|on).*/){ # Die Markiese fährt bereis
   $dt = time() - time_str2num(ReadingsTimestamp($device_down,'state',0));
   fhem("set $device_down aus");
   $newpos = $aktpos + (100 * $dt / ReadingsVal($name,'Ausfahrzeit',0));
} # Die Markiese fährt bereis
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

HoTi

Ah Super!

Kannst du auch was dazu sagen?

Zitat
PERL WARNING: Subroutine myUtils_Initialize redefined at ./FHEM/99_MyUtils.pm line 15.
PERL WARNING: Subroutine LastEvent redefined at ./FHEM/99_MyUtils.pm line 21.
PERL WARNING: Subroutine Markise_Stop redefined at ./FHEM/99_MyUtils.pm line 38.
PERL WARNING: Subroutine Ga_Schalter2_not redefined at ./FHEM/99_MyUtils.pm line 84.
Viele Grüße aus  Oberbayern
Tim (RettungsTim)