[Gelöst] und [Geklärt] Wechselwirkung Perl-sleep-Funktion <-> FHEM

Begonnen von fhem_olsi, 30 März 2023, 17:54:55

Vorheriges Thema - Nächstes Thema

fhem_olsi

Ich habe ein gravierendes Verständnisproblem mit der Auswirkung der Sleep-Funktion im Perl-Script unter FHEM:
Ich habe folgendes Test-Notify:
---------
olsi:.* {
  my $i = 0;;
  for ($i = 10; $i > 0; $i--) {
      Log 1, "Loop index = " . $i;;
      sleep (1);;
      fhem( "set LampePC TOGGLE" );;
  }
}
---------
Es soll(te) also 10 x im Abstand von einer Sekunde eine Lampe abwechselnd ein- und ausgeschaltet werden.
Tut es aber nicht!

Nach Aussage der Log-Datei scheint alles richtig abgearbeitet worden zu sein:
---------------------
2023.03.30 17:43:42 1: Loop index = 10
2023.03.30 17:43:43 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:43 1: Loop index = 9
2023.03.30 17:43:44 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:44 1: Loop index = 8
2023.03.30 17:43:45 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:45 1: Loop index = 7
2023.03.30 17:43:46 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:46 1: Loop index = 6
2023.03.30 17:43:47 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:47 1: Loop index = 5
2023.03.30 17:43:48 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:48 1: Loop index = 4
2023.03.30 17:43:49 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:49 1: Loop index = 3
2023.03.30 17:43:50 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:50 1: Loop index = 2
2023.03.30 17:43:51 3: MQTT2_DEVICE set LampePC TOGGLE
2023.03.30 17:43:51 1: Loop index = 1
2023.03.30 17:43:52 3: MQTT2_DEVICE set LampePC TOGGLE
---------------------
Aber in der Praxis geschieht folgendes: Das Perl-Script wird 10 Sekunden lang abgearbeitet, aber bei der Lampe passiert gar nichts. Danach wird die Lampe (rasend schnell ~ 10 Hz?) ein- und wieder ausgeschaltet.
Belegt wird dies auch durch das Protokoll im "Event monitor":
---------------------
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: ON
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: OFF
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: ON
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: OFF
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: ON
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: OFF
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: ON
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: OFF
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: ON
2023-03-30 17:43:52 MQTT2_DEVICE LampePC POWER: OFF
---------------------

Die Situation ist übrigens dieselbe, wenn ich anstatt der Perl-sleep-Funktion die entsprechende FHEM-Funktion gewählt hätte:
{ fhem( "set ....; sleep 1; set ..." ) }

Was habe ich da nicht verstanden?
Für eine Aufklärung wäre ich dankbar...

Beta-User

Vorab mal willkommen im FHEM-Forum!

Zum einen sollte man Perl-sleep-Anweisungen unbedingt vermeiden. FHEM tut in der Zeit nämlich sonst nichts (hier offenbar nur kurz den Code einreihen, den das IO dann anscheinend asynchron raushaut).

Bei FHEM-sleep findest du die Lösung in der commandref vermutlich unter "sleep". Man muss die ";" escapen, also für jede Runde verdoppeln.

Falls das Zieldevice das kann, ist vermutlich "blink" aus den SetExtensions für deinen Anwendungsfall interessant.

Ansonsten kannst du das über einen (rekursiven) InternalTimer-Aufruf (oder ein sich selbst wieder definierendes "at") lösen.

Hoffe, das halbwegs verständlich geschrieben zu haben.

Grüße, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Jamo

#2
Das Perl sleep ist blockierend, wie Beta-User schon geschrieben hat.
Du kannst so was mit einem FHEM sleep machen:
olsi:.* {
  my $i = 0;;
  for ($i = 10; $i > 0; $i--) {
      Log 1, "Loop index = " . $i;
      fhem( "sleep $i;set LampePC TOGGLE" );
  }
}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

fhem_olsi

@Beta-User
> Man muss die ";" escapen, also für jede Runde verdoppeln.
Bezieht sich diese Aussage auf meinen Perl-Code? Wenn ja, dann verstehe ich das nicht.

> Falls das Zieldevice das kann, ist vermutlich "blink" aus den SetExtensions für deinen Anwendungsfall interessant.
Mein Anwendungsfall war nicht das Blinken einer Lampe. Dieses war in diesem Fall nur ein Hilfsmittel zur Visualisierung der Zeitabläufe zum Thema "Wechselwirkung Perl-sleep-Funktion <-> FHEM".

Aber danke: Ich glaube, ich habe verstanden...

Ich fasse meine Erkenntnis 'mal so zusammen:

FHEM wartet "in Ruhe" das Abarbeiten des Perl-Scripts ab und sammelt dabei alle angefallenen FHEM-Aktionen (set-Befehle etc.) in einem Puffer. Dann, wenn das Perl-Script beendet ist, werden die FHEM-Aktionen in der angefallenen Reihenfolge schnellstmöglich oder nach durch entsprechende FHEM-Anweisungen vorgegebenen Zeit-Intervallen ausgeführt. Alle während der Abarbeitung angefallenen FHEM-Anweisungen werden quasi nachgeholt, auch solche, die durch andere Ereignisse (in anderen Scripts definiert) ausgelöst wurden.

Ist das ungefähr richtig zusammengefaßt?

Demnach wäre der Perl-Befehl "sleep" für die Nutzung von zeitgesteuerten FHEM-Aktionen völlig ungeeignet.

Damian

Zitat von: fhem_olsi am 31 März 2023, 10:27:50Ich fasse meine Erkenntnis 'mal so zusammen:

FHEM wartet "in Ruhe" das Abarbeiten des Perl-Scripts ab und sammelt dabei alle angefallenen FHEM-Aktionen (set-Befehle etc.) in einem Puffer. Dann, wenn das Perl-Script beendet ist, werden die FHEM-Aktionen in der angefallenen Reihenfolge schnellstmöglich oder nach durch entsprechende FHEM-Anweisungen vorgegebenen Zeit-Intervallen ausgeführt. Alle während der Abarbeitung angefallenen FHEM-Anweisungen werden quasi nachgeholt, auch solche, die durch andere Ereignisse (in anderen Scripts definiert) ausgelöst wurden.

Ist das ungefähr richtig zusammengefaßt?


Nein. Das wäre noch sehr optimistisch. FHEM wartet nicht "in Ruhe" und macht etwas anderes. FHEM ist im wesentlich ein einziger Prozess. Wenn du Perl-sleep benutzt steht dein FHEM solange, es wartet nicht, und macht auch nichts anderes in dieser Zeit.

Perl-sleep sollte man in FHEM niemals benutzen. Dafür gibt es, wie schon geschrieben, andere Funktionen - unglücklicherweise heißt die echte Warte-FHEM-Funktion in FHEM auch sleep.



Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Beta-User

Zitat von: fhem_olsi am 31 März 2023, 10:27:50@Beta-User
> Man muss die ";" escapen, also für jede Runde verdoppeln.
Bezieht sich diese Aussage auf meinen Perl-Code? Wenn ja, dann verstehe ich das nicht.
Nein, das bezieht sich auf FHEM-sleep, siehe die allgemeinen Ausführungen zu "Indirektionen" in https://commandref.fhem.de/commandref_DE.html#command

ZitatIch fasse meine Erkenntnis 'mal so zusammen:

FHEM wartet "in Ruhe" das Abarbeiten des Perl-Scripts ab und sammelt dabei alle angefallenen FHEM-Aktionen (set-Befehle etc.) in einem Puffer. Dann, wenn das Perl-Script beendet ist, werden die FHEM-Aktionen in der angefallenen Reihenfolge schnellstmöglich oder nach durch entsprechende FHEM-Anweisungen vorgegebenen Zeit-Intervallen ausgeführt. Alle während der Abarbeitung angefallenen FHEM-Anweisungen werden quasi nachgeholt, auch solche, die durch andere Ereignisse (in anderen Scripts definiert) ausgelöst wurden.

Ist das ungefähr richtig zusammengefaßt?

Demnach wäre der Perl-Befehl "sleep" für die Nutzung von zeitgesteuerten FHEM-Aktionen völlig ungeeignet.
Nicht komplett korrekt.

Perl-sleep ist absolut zu vermeiden! Diese Schlussfolgerung ist jedenfalls für Einsteiger 100% richtig!

Ansonsten: FHEM "tickt" absolut linear. Wenn also das angesteuerte Modul eine "set-on"-Anweisung direkt umsetzt und auch direkt über das IO absetzt, würde das ggf. auch funktionieren. Hier scheint aber die Umsetzung irgendwie timer-basiert umgesetzt zu sein, so dass eben ZUERST deine (blockierende!) Perl-Schleife abgearbeitet wird, und dann erst die gepufferten Befehle abgearbeitet werden.
Aber was konkret rauskommt, hängt eben stark vom jeweiligen Modulcode ab. Wenn der (imo) "gut" ist, passiert alles timer-basiert und FHEM kann checken, welche nächste Aktion die höchste Prio hat...

Hoffe, das ist jetzt noch klarer?

(Doppel gemoppelt hält vielleicht besser)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

fhem_olsi

ZitatNein. Das wäre noch sehr optimistisch. FHEM wartet nicht "in Ruhe" und macht etwas anderes. FHEM ist im wesentlich ein einziger Prozess. Wenn du Perl-sleep benutzt steht dein FHEM solange, es wartet nicht, und macht auch nichts anderes in dieser Zeit.
"nichts anderes" scheint mir nicht richtig zu sein!
Es müssen im Hintergrund irgendwelche interrupt-gesteuerte Prozesse ablaufen, während das im Vordergrund laufende Perl-Script den FHEM-Haupt-Prozeß "blockiert". Denn Ereignisse und damit verbundene (andere) Scripte werden offensichtlich registriert (gespeichert) und nachgeholt, sobald das "blockierende" Script abgearbeit ist. Habe ich selbst getestet!

Aber ansonsten: Danke.

Beta-User

Es ist richtig!

Dass das OS in der Zeit nicht schläft, ist doch eigentlich selbstverständlich.

 Und dass dein Code "drumrum" irgendwas (unbewußt) in den Hintergrund (als timer) schickt, ist kein Widerspruch dazu, denn das passiert VOR bzw. NACH deinen Perl-sleeps. Wenn dann dein Code um ist, schaut FHEM wieder alle seine "Dateien" an, ob was relevantes dabei ist (=> Events) und arbeitet (u.a. deine) Timer ab...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Damian

Zitat von: fhem_olsi am 31 März 2023, 12:40:25
ZitatNein. Das wäre noch sehr optimistisch. FHEM wartet nicht "in Ruhe" und macht etwas anderes. FHEM ist im wesentlich ein einziger Prozess. Wenn du Perl-sleep benutzt steht dein FHEM solange, es wartet nicht, und macht auch nichts anderes in dieser Zeit.
"nichts anderes" scheint mir nicht richtig zu sein!
Es müssen im Hintergrund irgendwelche interrupt-gesteuerte Prozesse ablaufen, während das im Vordergrund laufende Perl-Script den FHEM-Haupt-Prozeß "blockiert". Denn Ereignisse und damit verbundene (andere) Scripte werden offensichtlich registriert (gespeichert) und nachgeholt, sobald das "blockierende" Script abgearbeit ist. Habe ich selbst getestet!

Aber ansonsten: Danke.

In FHEM gibt es so gut wie keine im Hintergrund laufenden Prozesse. Wenn etwas gepuffert wird, dann eher im Gerätetreiber. Wenn ein FHEM-"Script" durch Perl-sleep blockiert wird, dann läuft kein anderes FHEM-"Script" in dieser Zeit.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Jamo

Ich habe meinen Typo oben korrigiert,
ZitatDas Perl sleep ist blockierend, wie Beta-User schon geschrieben hat.
Du kannst so was mit einem FHEM sleep machen:
Der code sollte so aber so funktionieren.
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

fhem_olsi

@Jamo:
Hatte ich schon verstanden, ob fettgedruckt oder nicht; keine Sorge!

@Damian:
Zitatn FHEM gibt es so gut wie keine im Hintergrund laufenden Prozesse. Wenn etwas gepuffert wird, dann eher im Gerätetreiber. Wenn ein FHEM-"Script" durch Perl-sleep blockiert wird, dann läuft kein anderes FHEM-"Script" in dieser Zeit.
Das kann's einfach nicht sein!
Meine FHEM-Kommunikation läuft komplett - also nur - via MQTT; der Broker (Mosquitto auf demselben PC) "weiß" nichts von FHEM, läuft total asynchron. Da gibt es keinen weiteren "Gerätetreiber", der etwas speichert!!!
Vielleicht ist es das FHEM-Modul "MQTT2_DEVICE" selbst, das alle Infos via Subscribe abholt? Das interrupt-gesteuert läuft?

Damian

Zitat von: fhem_olsi am 01 April 2023, 12:09:16@Jamo:
Hatte ich schon verstanden, ob fettgedruckt oder nicht; keine Sorge!

@Damian:
Zitatn FHEM gibt es so gut wie keine im Hintergrund laufenden Prozesse. Wenn etwas gepuffert wird, dann eher im Gerätetreiber. Wenn ein FHEM-"Script" durch Perl-sleep blockiert wird, dann läuft kein anderes FHEM-"Script" in dieser Zeit.
Das kann's einfach nicht sein!
Meine FHEM-Kommunikation läuft komplett - also nur - via MQTT; der Broker (Mosquitto auf demselben PC) "weiß" nichts von FHEM, läuft total asynchron. Da gibt es keinen weiteren "Gerätetreiber", der etwas speichert!!!
Vielleicht ist es das FHEM-Modul "MQTT2_DEVICE" selbst, das alle Infos via Subscribe abholt? Das interrupt-gesteuert läuft?


Das mag ja alles sein. Dennoch macht es zu keinem Zeitpunkt Sinn die Hauptabarbeitungsschleife für alle FHEM-Module zu blockieren.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

fhem_olsi

ZitatDas mag ja alles sein. Dennoch macht es zu keinem Zeitpunkt Sinn die Hauptabarbeitungsschleife für alle FHEM-Module zu blockieren.
Diese Erkenntnis hatte ich ja schon lange gewonnen; s.o.!
Mit ging's doch um das Verstehen der Wechselwirkungen; versteh' doch!

Beta-User

Zitat von: fhem_olsi am 01 April 2023, 12:09:16Das kann's einfach nicht sein!
Meine FHEM-Kommunikation läuft komplett - also nur - via MQTT; der Broker (Mosquitto auf demselben PC) "weiß" nichts von FHEM, läuft total asynchron. Da gibt es keinen weiteren "Gerätetreiber", der etwas speichert!!!
Vielleicht ist es das FHEM-Modul "MQTT2_DEVICE" selbst, das alle Infos via Subscribe abholt? Das interrupt-gesteuert läuft?

Nochmal: Was das OS oder andere Prozesse in der Zeit machen, ist in dem Zusammenhang hier völlig wurst.
FHEM reagiert nicht selbst auf "interrupts", das tut ggf. das OS, aber FHEM bekommt davon (bestenfalls) erst nach dem Perl-sleep mit. FHEM ist kein Microcontroller.

Und wenn was gepuffert wird, dann eher nicht im (FHEM-Sprech) Client-Modul (MQTT2_DEVICE), sondern in dem IO-Modul, das es verwendet (hier, da mosquitto: MQTT2_CLIENT).
(War mir aber auch nicht bewußt, dass Rudi das asynchron ausgelegt hat. Cool!)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

fhem_olsi

ZitatUnd wenn was gepuffert wird, dann eher nicht im (FHEM-Sprech) Client-Modul (MQTT2_DEVICE), sondern in dem IO-Modul, das es verwendet (hier, da mosquitto: MQTT2_CLIENT).
Einverstanden!