Übergabe Variable von perl in fhem Ebene

Begonnen von Fritz Muster, 21 Februar 2023, 12:20:58

Vorheriges Thema - Nächstes Thema

Fritz Muster

Bin jetzt mal dazu gekommen das Ganze per copy/paste umzusetzen. Leider funktioniert der Code nicht. Es passiert schlichtweg nichts, auch im log findet sich kein Eintrag was evtl. ein Hinweis geben könnte warum nichts passiert.

Viele Grüße
Fritz
RasPi 3B+, Stretch, Fhem 5.9, DBlog SQLite
HMLAN, mapleCUN MAX/WMBus, mapleSduino 868/433/868
HM Sensoren/Aktoren ,Technoline TX 29 DTH-IT, TFA 30.3155WD, MAX!
Hour Counter, Astro, EletricityCounter, Statistics, Charting Frontend, TabletUI, Modbus

DeeSPe

Zitat von: Fritz Muster am 08 März 2023, 19:32:13
Leider funktioniert der Code nicht. Es passiert schlichtweg nichts, auch im log findet sich kein Eintrag was evtl. ein Hinweis geben könnte warum nichts passiert.

Hab das jetzt selbst mal getestet und bei mir funktioniert es genau wie erwartet!
Die Funktion habe ich noch um ein paar Debug Ausgaben erweitert und auch diese landen mit dem erwarteten Inhalt im Log.
Code (99_myUzils.pm) Auswählen
sub myStateCheck
{
  my ($name,$max,$tim,$count) = @_;
  ##### CONFIG START #####
  my $maxi = 1; # Maximale Anzahl an wiederholten Prüfungen wenn keine vorgegeben wurde
  my $time = 5; # Zeit nach der die wiederholte Prüfung stattfinden soll
  ##### CONFIG END #####
  my $state = ReadingsVal($name,'state','');
  $max = $max?$max:$maxi;
  $tim = $tim?$tim:$time;
  $count = $count?$count:0;
  if ($state eq 'off' && $count<$max)
  {
    Debug 'Durchlauf '.$count;
    Debug 'if Zweig';
    Debug "$name ist $state";
    # wenn offline und Zähler kleiner als Vorgabe dann prüfe in $tim Sekunden wieder
    $count++;
    fhem "sleep $tim quiet; {myStateCheck('$name',$max,$tim,$count)}";
  }
  elsif ($state eq 'off' && $count)
  {
    Debug 'Durchlauf '.$count;
    Debug 'elsif Zweig';
    Debug "$name ist $state";
    # mach was du machen willst wenn das Device nicht mehr off ist, aber vorher offline war
    fhem "set $name on";
  }
  # sonst tue nichts
  # Ende immer mit return
  return;
}



Code (Dummy zum Testen definieren) Auswählen
define d1 dummy
attr d1 setList on off

setstate d1 off
setstate d1 2023-03-10 10:53:50 state off


Code (Funktion ausführen) Auswählen
{myStateCheck('d1')}

Nach 5 Sekunden wird der vorher ausgeschaltete Dummy noch einmal geprüft und wenn er immer noch ausgeschaltet ist wird dieser eingeschaltet.
Während dessen wird in das Log geschrieben:
2023.03.10 10:53:20 1: DEBUG>Durchlauf 0
2023.03.10 10:53:20 1: DEBUG>if Zweig
2023.03.10 10:53:20 1: DEBUG>d1 ist off
2023.03.10 10:53:25 1: DEBUG>Durchlauf 1
2023.03.10 10:53:25 1: DEBUG>elsif Zweig
2023.03.10 10:53:25 1: DEBUG>d1 ist off


Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Fritz Muster

Habe es jetzt hinbekommen das es läuft. Typischer copy/paste Fehler meinerseits  :-[

Allerdings scheint es das ich nicht exakt genug die Funktionsweise beschrieben habe. Ich möchte gerne das immer nach X Sekunden Wartezeit und nicht erfolgter state Änderung der set Befehl ausgelöst wird. Das Ganze soll in Y Intervallen geprüft werden. So wie ich Deine Funktion verstehe läuft die erste if Schleife die Y Intervalle immer durch ohne in den Intervallen selbst nochmal zu prüfen ob das device den state geändert hat. Oder sehe ich das falsch?

Vielen Dank und viele Grüße
Fritz
RasPi 3B+, Stretch, Fhem 5.9, DBlog SQLite
HMLAN, mapleCUN MAX/WMBus, mapleSduino 868/433/868
HM Sensoren/Aktoren ,Technoline TX 29 DTH-IT, TFA 30.3155WD, MAX!
Hour Counter, Astro, EletricityCounter, Statistics, Charting Frontend, TabletUI, Modbus

DeeSPe

Zitat von: Fritz Muster am 12 März 2023, 13:45:38
Habe es jetzt hinbekommen das es läuft. Typischer copy/paste Fehler meinerseits  :-[

Allerdings scheint es das ich nicht exakt genug die Funktionsweise beschrieben habe. Ich möchte gerne das immer nach X Sekunden Wartezeit und nicht erfolgter state Änderung der set Befehl ausgelöst wird. Das Ganze soll in Y Intervallen geprüft werden. So wie ich Deine Funktion verstehe läuft die erste if Schleife die Y Intervalle immer durch ohne in den Intervallen selbst nochmal zu prüfen ob das device den state geändert hat. Oder sehe ich das falsch?

Vielen Dank und viele Grüße
Fritz

Tja, wenn man den genauen Use-Case kennen würde, dann könnte man auch besser helfen.

So wie ich das versteh benötigst Du den else Zweig gar nicht.
sub myStateCheck
{
  my ($name,$max,$tim,$count) = @_;
  ##### CONFIG START #####
  my $maxi = 1; # Maximale Anzahl an wiederholten Prüfungen wenn keine vorgegeben wurde
  my $time = 5; # Zeit nach der die wiederholte Prüfung stattfinden soll
  ##### CONFIG END #####
  my $state = ReadingsVal($name,'state','');
  $max = $max?$max:$maxi;
  $tim = $tim?$tim:$time;
  $count = $count?$count:0;
  if ($state eq 'off' && $count<$max)
  {
    # wenn off und Zähler kleiner als Vorgabe dann schalte ein und prüfe in $tim Sekunden wieder
    fhem "set $name on";
    $count++;
    fhem "sleep $tim quiet; {myStateCheck('$name',$max,$tim,$count)}";
  }
  # sonst tue nichts
  # Ende immer mit return
  return;
}


Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

RalfRog

Das Thema scheint ja vom Prinzip her geklärt.

Was passiert in der Perl-Funktion mit dem Wert, der per return zurück gegeben wird. Hier landet er im UserReading (watchdog) von FHEM.

Zitat von: Fritz Muster am 21 Februar 2023, 12:20:58
...
In einem device habe ich folgendes userreading zum aufruf der Routine angelegt
watchdog {mysub ($name,"state")}
...

Wenn ich darf würde ich mich mit einer ähnlichen Frage hier dazu hängen.

Gerade bei den UserReadings ist schon soweit klar, dass der in der Sub per return zurückgegebene Wert im Reading landet.

Wie sieht es z.B. bei einem AT mit dem Aufruf einer Perl-Funktion aus. Möglicherweise doof gefragt:
Kann man da mit dem Rückgabewert im AT etwas anfangen und wo hätte man Zugriff.

FHEM auf Proxmox VM Bookworm (Futro S740) - nanoCUL, HM-MOD-RPI-PCB und MAX!Cube über LAN
HM- Fensterkontakte, UP-Schalter, Bewegungsmelder und ein Rauchmelder sowie Shelly 3EM, 1PM, PlugS und IT Schaltsteckdosen

DeeSPe

Funktionen sollten nur einen Rückgabewert bieten wenn dieser auch weiterverarbeitet werden soll, wie z.B. bei 'userReadings'.
Rückgabewerte von Funktionen die aus z.B. 'at' oder 'notify' aufgerufen werden landen im 'Nirvana' oder Du schreibst sie explizit irgendwo hin, z.B. ins Log oder ein Reading.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

RalfRog

Danke dir :D   Aussage Nirwana reicht mir, war mir nicht so klar.

Thema Log und Readings in Perl-Funktionen ist soweit (geläufig.

Gruß Ralf
FHEM auf Proxmox VM Bookworm (Futro S740) - nanoCUL, HM-MOD-RPI-PCB und MAX!Cube über LAN
HM- Fensterkontakte, UP-Schalter, Bewegungsmelder und ein Rauchmelder sowie Shelly 3EM, 1PM, PlugS und IT Schaltsteckdosen

Benni

Zitat von: DeeSPe am 12 März 2023, 15:00:37
Rückgabewerte von Funktionen die aus z.B. 'at' oder 'notify' aufgerufen werden landen im 'Nirvana' oder Du schreibst sie explizit irgendwo hin, z.B. ins Log oder ein Reading.

So Pauschal würde ich das nicht abhandeln! ;)

Zitat von: RalfRog am 12 März 2023, 14:20:20
Wie sieht es z.B. bei einem AT mit dem Aufruf einer Perl-Funktion aus. Möglicherweise doof gefragt:
Kann man da mit dem Rückgabewert im AT etwas anfangen und wo hätte man Zugriff.

Wenn ich meinen notify- oder AT-Ausführungsteil auf perl-Ebene setze, dann kann ich den Rückgabewert sehr wohl dort weiterverarbeiten:


defmod myAt at +*00:01:00 {\
   my $name='IrgendeinDeviceName';;\
   ## Übernahme des Rückgabewertes auf Perl-Ebene in einer Variable\
\
   my $rueckgabewert=mysub ($name,"state");;\
\
   ## den kann ich jetzt bspw. auf FHEM-Ebene in eineme Reading im at selbst speichern\
   ## (oder was auch immer damit machen)\
\
   fhem("setreading $SELF mysub_result $rueckgabewert");;\
}


gb#

DeeSPe

Zitat von: Benni am 12 März 2023, 15:41:11

defmod myAt at +*00:01:00 {\
   my $name='IrgendeinDeviceName';;\
   ## Übernahme des Rückgabewertes auf Perl-Ebene in einer Variable\
\
   my $rueckgabewert=mysub ($name,"state");;\
\
   ## den kann ich jetzt bspw. auf FHEM-Ebene in eineme Reading im at selbst speichern\
   ## (oder was auch immer damit machen)\
\
   fhem("setreading $SELF mysub_result $rueckgabewert");;\
}


Das bestätigt doch nur meine Aussage:
Zitat von: DeeSPe am 12 März 2023, 15:00:37
Rückgabewerte von Funktionen die aus z.B. 'at' oder 'notify' aufgerufen werden landen im 'Nirvana' oder Du schreibst sie explizit irgendwo hin, z.B. ins Log oder ein Reading.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Benni

Irgendwie bin ich zur Zeit wohl etwas unaufmerksam!   :-\

gb#

DeeSPe

Zitat von: Benni am 12 März 2023, 16:02:43
Irgendwie bin ich zur Zeit wohl etwas unaufmerksam!   :-\

Vielleicht doch mal ne Runde Gassi gehen? :D

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Benni

Zitat von: DeeSPe am 12 März 2023, 16:04:43
Vielleicht doch mal ne Runde Gassi gehen? :D

War ich eigentlich vorhin erst  :D

gb#

RalfRog

Jungs danke euch.
Beispiel von Benni war trotzdem nicht schlecht  ;)

Hoffe Fritz Muster ist jetzt nicht aus dem Tritt  8)

Schönen Sonntahg
FHEM auf Proxmox VM Bookworm (Futro S740) - nanoCUL, HM-MOD-RPI-PCB und MAX!Cube über LAN
HM- Fensterkontakte, UP-Schalter, Bewegungsmelder und ein Rauchmelder sowie Shelly 3EM, 1PM, PlugS und IT Schaltsteckdosen

Fritz Muster

#28
Danke, jetzt muss es nur noch eine weitere if Schleife in der 1. if Schleife geben, welche nach dem sleep erneut prüft ob das state noch off ist. Wenn das der Fall ist soll ein fhem "set on" kommen. und es soll dann im nächsten Intervall nach X Sekunden geprüft werden ob state nicht mehr off ist. Ich habe mich mal versucht mit folgendem Code, funktioniert aber nicht, Syntax Error im Log

if ($state eq 'off' && $count<$max) 
  {
    $count++;
    fhem "sleep $tim quiet;
           {if ($state eq 'off')
               {fhem "set $name on"; {myStateCheck('$name',$max,$tim,$count)}
           else {return;}";
          }
  }

 
Zitat von: RalfRog am 12 März 2023, 16:22:03
Hoffe Fritz Muster ist jetzt nicht aus dem Tritt  8)

Schönen Sonntahg

War noch nie drin im Tritt  ;D
RasPi 3B+, Stretch, Fhem 5.9, DBlog SQLite
HMLAN, mapleCUN MAX/WMBus, mapleSduino 868/433/868
HM Sensoren/Aktoren ,Technoline TX 29 DTH-IT, TFA 30.3155WD, MAX!
Hour Counter, Astro, EletricityCounter, Statistics, Charting Frontend, TabletUI, Modbus

DeeSPe

Zitat von: Fritz Muster am 12 März 2023, 16:52:41
Danke, jetzt muss es nur noch eine weitere if Schleife in der 1. if Schleife geben, welche nach dem sleep erneut prüft ob das state noch off ist.

Aber genau das macht doch die Funktion indem sie sich selbst wieder nach Zeit X (verzögert durch sleep) aufruft und das so lange bis $max erreicht ist bzw. $state nicht mehr 'off' ist:
sub myStateCheck
{
  my ($name,$max,$tim,$count) = @_;
  ##### CONFIG START #####
  my $maxi = 1; # Maximale Anzahl an wiederholten Prüfungen wenn keine vorgegeben wurde
  my $time = 5; # Zeit nach der die wiederholte Prüfung stattfinden soll
  ##### CONFIG END #####
  my $state = ReadingsVal($name,'state','');
  $max = $max?$max:$maxi;
  $tim = $tim?$tim:$time;
  $count = $count?$count:0;
  if ($state eq 'off' && $count<$max)
  {
    # wenn off und Zähler kleiner als Vorgabe dann schalte ein und prüfe in $tim Sekunden wieder
    fhem "set $name on";
    $count++;
    fhem "sleep $tim quiet; {myStateCheck('$name',$max,$tim,$count)}";
  }
  # sonst tue nichts
  # Ende immer mit return
  return;
}


Also nochmal: Die Funktion prüft beim ersten Aufruf ob das Device 'off' ist und $max noch nicht erreicht ist, ist das der Fall wird das Device eingeschaltet und die Funktion nach Zeit X wieder aufgerufen. Dann kommt die selbe Prüfung wieder. Ist das Device also immer noch 'off' und $max immer noch nicht erreicht, dann wird wieder eingeschaltet und die Funktion nach Zeit X wieder aufgerufen. Das geht so lange bis das Device bei der Prüfung nicht mehr 'off' ist, oder $max erreicht ist.

Ich nehme an dass diese Funktion sicherstellen soll dass ein Device (mit evtl. schlechtem Funkempfang) auch wirklich eingeschaltet wurde.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe