sleep in Funktionen

Begonnen von ftsinuglarity, 04 Juni 2018, 17:08:59

Vorheriges Thema - Nächstes Thema

ftsinuglarity

#15
Zitat von: CoolTux am 05 Juni 2018, 14:36:14
Wie gesagt es ist lediglich ein externes Script welches Deine Aufgabe erfüllt (unabhängig von FHEM) und die Rückgabewerte welches es bekommt über einen FHEM Kanal an FHEM übermittelt.
Im Script von Rudi ist es telnet, Du kannst aber auch FHEM direkt aufrufen und die Daten übermitteln.

perl fhem.pl 7072 'set dummy reading ergebnis'


Ich hätte es in Erwägung gezogen hättest Du nicht von EINFACH und SIMPEL gesprochen


Ich glaube so langsam verstehe ich es.

sub aktuelle_funktion{ / oder direkt aufrufen
     fhem('"$script cur_ip"');
}


Im Script werden die Werte dann auf die eine oder andere Weise an FHEM übergeben. zB:

#!/bin/bash
..
ip=`wget ...ip_adresse..`
perl /path/fhem.pl 7072 "set Dummy $ip"
...



Um auf die Auswertung zu reagieren, könnte dann ein Notify auf den Dummy gesetzt werden
Habt ihr das so in etwa gemeint ?


Zitat von: CoolTux am 05 Juni 2018, 14:36:14
Ich hätte es in Erwägung gezogen hättest Du nicht von EINFACH und SIMPEL gesprochen
Joa, ist jetzt ein wenig mehr als "sleep 10" :D

Der InternalTimer ist für andere Szenarien auch sehr interessant.



rudolfkoenig

ZitatHabt ihr das so in etwa gemeint ?
Noe :), eher so:
define bewaessern at *19:00 "bin/garden.pl"
An FHEM-Daten kommt man aus dem Skript in etwa so ran:
my $regenmenge=`perl fhem.pl 7072 "{ReadingsNum('wetterstation','rain',0)}"`;
Und so kann man einen Schalter aus dem Skript setzen:
`perl fhem.pl 7073 "set Pumpe on-for-timer $dauer"`;oder ein Event auslosen:`perl fhem.pl 7073 "trigger bewaessern giessen_ist_fertig"`;

Ich will niemanden zwingen, so zu arbeiten, ich wollte nur zeigen, dass man so relativ einfach was bauen kann, was selbst schlafen/blockieren/lange rechnen kann, ohne FHEM zu blockieren, und man ist dabei auch nicht auf perl festgelegt. Und ich fand es merkwuerdig, dass kaum jemand sowas macht, obwohl das von Anfang an moeglich war.

ftsinuglarity

#17
Zitat von: rudolfkoenig am 05 Juni 2018, 15:48:18
Noe :) , eher so:
Mist :)
Zitat von: rudolfkoenig am 05 Juni 2018, 15:48:18define bewaessern at *19:00 "bin/garden.pl"
ah .. da ist das "..." :) .. schön direkt

Zitat von: rudolfkoenig am 05 Juni 2018, 15:48:18An FHEM-Daten kommt man aus dem Skript in etwa so ran:
my $regenmenge=`perl fhem.pl 7072 "{ReadingsNum('wetterstation','rain',0)}"`;
Und so kann man einen Schalter aus dem Skript setzen:
`perl fhem.pl 7073 "set Pumpe on-for-timer $dauer"`;oder ein Event auslosen:`perl fhem.pl 7073 "trigger bewaessern giessen_ist_fertig"`;
Ja vielen Dank für die Details! Das ist mal echt schick. (so ganz daneben lag ich doch aber grad nicht ??)
Und so schwer wars eigentlich gar nicht zu verstehen .. man man, der Schlauch ist manchmal ziemlich lang...

Zitat von: rudolfkoenig am 05 Juni 2018, 15:48:18Ich will niemanden zwingen, so zu arbeiten, ich wollte nur zeigen, dass man so relativ einfach was bauen kann, was selbst schlafen/blockieren/lange rechnen kann, ohne FHEM zu blockieren, und man ist dabei auch nicht auf perl festgelegt. Und ich fand es merkwuerdig, dass kaum jemand sowas macht, obwohl das von Anfang an moeglich war.
Wüßte nicht wer jetzt behaupten könnte, du wolltest ihn zu irgendwas zwingen ;)
Vielen Dank für eure Zeit und diesen sehr informativen Ausflug an euch beide!!

Ist jetzt zwar keine einfaches "sleep 10 && machirgendwas()" geworden, das hilft mir aber enorm weiter, mit "sicheren" Werten zu arbeiten. Ein reines "sleep 10" ist ja immer nur ne Schätzung. Wenn das Script länger als 10 Sekunden bräuchte, wären die Variablen trotz sleep nicht gefüllt. (ok, dann könnte ich in eine sleep-Schleife gehen bis die Variablen voll sind) So ists aber wesentlich sauberer und direkter und vor allem non-blocking.


ftsinuglarity

#18
Ich habe mit InternalTimer experimentiert, mir ist einiges noch nicht ganz klar.


Beispiel:
Meine Waschmaschine hängt an einer schaltbaren Strommessdose.
Schalte ich sie ein, wird die Funktion switch_device_on(DEVICE,Wattgrenze) aufgerufen.
Diese schaltet das DEVICE ein, und schreibt in den Hash des DEVICE den Gerätenamen und die Wattgrenze (limit) und übergibt diese per InternalTimer an die Funktkion: auto_power_depend_OFF
Dort ziehe ich mir aus dem Hash dann den DEVICE-Namen und die Wattgrenze.


Parameterübergabe mit 2 Parametern über InternalTimer:

sub switch_device_on($$) {
  my ($device,$limit) = @_;
  my $hash = $defs{$device};

  fhem("set $1 on");
  $hash = {'device' => $device, 'limit' => $limit};
  InternalTimer(gettimeofday()+5, "auto_power_depend_OFF", $hash);
}

sub auto_power_depend_OFF {
  my ($hash) = @_;
  my $device = $hash->{device};
  my $limit = $hash->{limit};
   ...
}




Frage: Ist die Parameterübergabe so im Sinne des Erfinders, oder mache ich es unnötig kompliziert ?

---------------------
Frage 2: auto_power_depend_OFF prüft ob der Stromverbrauch mehrere Schleifen lang unter der $limit (Wattgrenze) liegt, und schaltet dann aus, bzw. nicht wenn die Wattgrenze einmal überschritten wurde.
Die Schleife erzeuge ich dadurch, das ich einen at_Timer setze, der dann wiederum die Funktion erneut aufruft und die Stromwerte checkt.
Das geht sicher besser. Mir ist hier nicht klar, wie ich den hash per at_Timer übergebe.


sub auto_power_depend_OFF {
  my ($hash) = @_;
  my $device = $hash->{device};
  my $limit = $hash->{limit};
   ...
  fhem("defmod at_Timer at +00:00:30 {auto_power_depend_OFF(".$hash.")}");
  ...
}


Dieser Aufruf führt zu:
ERROR evaluating {auto_power_depend_OFF("HASH(0x58cd430)")}: Can't use string ("HASH(0x58cd430)") as a HASH ref while ...
oder wahlweise:
Undefined subroutine &main::HASH called at ..


--> gelöst
Selbst wenn der Hash erfolgreich übergeben würde, wären dann:
  my $device = $hash->{device};
  my $limit = $hash->{limit};
überhaupt noch gesetzt ?
--> Ja, weil direkt ins Device geschrieben wird

ftsinuglarity

#19
Ich habe es jetzt selbst anders gelöst.


switch_device_on()  prüft nur noch das Device auf Existenz und ruft dann per InternalTimer die eigentliche Funktion "auto_power_depend_OFF ()" auf
Einen Hash für InternalTimer brauche ich nicht mehr, da der vorher auch nicht mehr machte, als in das Device zu schreiben. Das mache ich jetzt direkt in "auto_power_depend_OFF()"


# eigentlich benötige ich diese Funktion nur noch zum vereinfachten Aufruf im Notify

sub switch_device_on($) {
my $device = $_[0];
        if(!$defs{$device}) {return 0;}
InternalTimer(gettimeofday()+5, "auto_power_depend_OFF", $device);
}



in auto_power_depend_OFF() kann ich jetzt direkt das Device übergeben

sub auto_power_depend_OFF($) {
  my $device = $_[0];
   ...



und damit auch dem Timer von:

  fhem("defmod at_Timer at +00:00:30 {auto_power_depend_OFF(".$hash.")}");
  ...
}



auf

  fhem("defmod at_Timer at +00:00:30 { InternalTimer(gettimeofday()+1, 'auto_power_depend_OFF', \"".$device."\")}");
  ...
}


setzen

Außerdem läuft auf diese Weise die Funktion bei jedem Aufruf non-blocking, nicht nur beim ersten Aufruf durch switch_device_on(), wie in meiner 1. Version.



Warum die Hashübergabe im at_Timer nicht funktioniert, ist mir noch nicht klargeworden.

sub myTest {
my $dev = "Testdevice";
my $hash = $defs{$dev};

InternalTimer(gettimeofday()+2, "myTest2", $hash) ;
}

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

fhem("defmod at_Timer at +00:00:05 {myTest2(".$hash.")}");
}