Hallo Leute.
Nach Wakeup eines Displays (Nextion) wird der Inhalt einer Datei mit den aktuellen Variablenwerten an das Display gesendet. Da es hierbei ab und an
Probleme gibt, habe ich versucht das Ganze durch ein Sleep zu entzerren.
Dafür verwende ich folgenden Code (hier übertrieben mit 2s zum Test; eigentlich steht hier ein Wert von 0.1 oder weniger - siehe Kommentar)
use Storable;
my %state = %{retrieve('TD_statefile')};
while(@array=each(%state))
{
Log 4, "$array[1]\n";
# {fhem ("sleep 0.1;set $device $array[1];")};
{fhem ("sleep 2;set $device $array[1]")};
}
Problem ist nun, daß die Verzögerung anscheinend keine Auswirkung hat: Die Befehle (ca. 60) werden anscheinend (inkl. Antwort vom Device) innerhalb
von etwas mehr als einer Sekunde abgearbeitet.
Denkfehler/Codefehler meinerseits?
Gruß, Oli
Da fällt mir gerade noch was auf:
Ist das abschließende Semikolon beim letzten Befehl nötig oder funktioniert beides?
{fhem ("sleep 0.1;set $device $array[1];")};
{fhem ("sleep 2;set $device $array[1]")};
Zitat von: hmtec99 am 02 Dezember 2023, 14:45:49Denkfehler/Codefehler meinerseits?
Ja ;)
Also deine Schleife läuft "sofort" und "komplett" durch.
Bei jedem Durchlauf wird ein "verzögerter set" erzeugt aber eben alle quasi "zeitgleich"...
D.h. alles läuft eben um 1x Sleepwert verzögert.
Wenn du in fhem sowas willst, ist eine Möglichkeit eine Sub rekursiv mit Verzögerung aufrufen und dann immer das nächste Stückchen abarbeiten.
Oder die Devices in eine structure packen und dann mit delay arbeiten...
Gruß, Joachim
oder die sleep time mit jedem schleifendurchlauf zu inkrementieren...
oder den kompletten "string" für einen "fhem" cmd in der schleife zusammenbauen und anschliessend ausführen.
Bahnhof? :o
Kann mir jemand meinen Code umbauen, damit es funktioniert? ;D
Oder mir erklären, was ich anscheinend an der Funktionsweise von while nicht verstehe...
Zitat von: hmtec99 am 02 Dezember 2023, 18:35:05Oder mir erklären, was ich anscheinend an der Funktionsweise von while nicht verst
Habe ich doch ausführlich?!
Also:
Durchlauf 1: es wird ein Slepp + Befehl abgesetzt
Sofort Durchlauf 2: es wird ein Sleep + Befehl abgesetzt
Aber Sleep1+Befehl2 und Sleep2+Befehl2 usw. werden quasi "zur selben Zeit" erzeugt...
D.h. am Ende der Schleife, die quasi "sofort" durch ist hast du X Sleep+Befehl erzeugt, die aber alle (fast) gleichzeitig loslaufen...
Packe doch einfach mal Logausgaben in deinen Code, dann wirst du es sehen...
Gruß, Joachim
Zitat von: hmtec99 am 02 Dezember 2023, 18:35:05Kann mir jemand meinen Code umbauen, damit es funktioniert?
Welche Variante soll es werden? ;)
Gruß, Joachim
Ist es nicht so?
while(@array=each(%state)) >> mache solange rum, bis kein Futter mehr im Array, und zwar:
{
Log 4, "$array[1]\n"; >> schreib was ins Log (falls Level >=4) und
# {fhem ("sleep 0.1;set $device $array[1];")};
{fhem ("sleep 2;set $device $array[1]")}; >> schlaf ein bißchen, führ anschließend EINEN Befehl aus und fang dann wieder von oben an!?
}
wenn ich dich richtig verstehe hat, vesetze ich fhem 2 sekunden in den schlaf und sende aber gleichzeitig den befehl ab?
häh??
Im Endeffekt möchte ich erreichen, daß jeder Durchlauf von while um eine Zeit x verzögert wird, das Zieldevice nicht überfordert wird... d.h. ballere nicht 60 Befehle quasi zeitgleich raus sondern mit jeweils minimaler Verzögerung...
Aber 'oben' wartet doch nicht, bis der 'eine' Befehl seinen 'sleep 2' fertig hat. Das 'sleep 2' ist nur der erste Teil des 'EINEN' Befehls, der dann sofort ausgefuehrt wird.
>>wenn ich dich richtig verstehe hat, vesetze ich fhem 2 sekunden in den schlaf und sende aber gleichzeitig den befehl ab?
Nein, es wird intern ein timer gestartet, der befehl wird dann erst mit 2 sekunden verspaetung gestartet.
Der Befehl wird am Fhem gesendet, dann läuft die Schleife weiter.
Fhem wartet parallel 2s und führt den Befehl aus. Während dessen kommen schon neue Befehle von der Schleife in Fhem an.
D.h. du hast das gleiche wie ohne sleep nur 2s später.
Nachtrag: da war Jamo schneller
d.h. das sleep müßte außerhalb von fhem {} stehen (davor)? sorry, I don't get it...
Ja, aber in Perl blockiert es!!!!
Zitat von: frober am 02 Dezember 2023, 18:57:49Ja, aber in Perl blockiert es!!!!
das habe ich auch schon gelesen... ;D
d.h.
jeder befehl wird zwar um 2s verzögert, aber jeweils mit nur minimalen versatz solange wie die while-schleife insgesamt braucht, um 60x durchzulaufen - also ein paar millisekunden, oder so??
hab ich's jetzt?? ;D
Zitat von: hmtec99 am 02 Dezember 2023, 18:59:58jeder befehl wird zwar um 2s verzögert, aber jeweils mit nur minimalen versatz solange wie die while-schleife insgesamt braucht, um 60x durchzulaufen - also ein paar millisekunden, oder so??
hab ich's jetzt??
Gratuliere! :)
EDIT: bzw. mit dem Versatz -> nicht bis die ganze Schleife durch ist, sondern eben von Durchlauf zu Durchlauf des nächsten Elementes ist dann der Versatz ziwschen den Befehlen (also Millisekunden)... 8)
Gruß, Joachim
Danke für die Blumen! ;D ;D ;D
Gibt es eine (integrierte) Schleifen-Funktion, in der man die Ausführung jedes Durchlaufs verzögern kann?
Zitat von: hmtec99 am 02 Dezember 2023, 19:09:28Danke für die Blumen! ;D ;D ;D
Gibt es eine (integrierte) Schleifen-Funktion, in der man die Ausführung jedes Durchlaufs verzögern kann?
Bzw. wie kann ich mein Ziel mit minimalem Umbau des Codes erreichen?
Huhu? Alle offline? :o
So sollte es funktionieren:
my $t=0;
while(@array=each(%state))
{
Log 4, "$array[1]\n";
# fhem ("sleep 0.1;set $device $array[1]");
fhem ("sleep $t ;set $device $array[1]");
$t = $t + 2;
}
Danke für die Hilfe...
Hat mein Problem so nicht gelöst, aber "Ehre wem Ehre gebührt"... ;D
Oli
P.S. Es funktioniert natürlich wie von dir vorgeschlagen, aber da liegt wohl noch was anderes im Argen... (Signalqualität o.ä.).
Vielleicht fehlt Dir einfach das Grundverständnis, dass
fhem("sleep 0.1; irgendein FHEM Befehl");
etwas völlig anderes ist, als der perl code
{
sleep 0.1;
irgendeine perl Funktion;
}
Im ersten Fall ist das einfach eine Kette von FHEM Befehlen (!), auch sleep ist in diesem Kontext ein Befehl und keine Funktion. Dieser Befehl sorgt dafür, dass FHEM einen internen Timer erzeugt, nach dessen Ablauf der gewünschte "irgendein FHEM Befehl" ausgeführt wird. Du kannst das in etwa so vergleichen:
define tempAt at +<wartezeit aus dem sleep befehl> 'irgendein FHEM Befehl'
Deshalb wartet FHEM in diesem Fall überhaupt nicht mit der weiteren Verarbeitung, sondern der Timer wird parallel abgearbeitet und dann der Befehl ausgeführt.
Im zweiten Fall hast Du einen perl Codeblock, dort ist das sleep() eine perl Funktion, die die Verarbeitung tatsächlich "anhält", deshalb ist das in FHEM ein blockierender Aufruf.