Da ich keine passende Stelle finde, frage ich mal hier nach:
Warum funktioniert das sleep nicht in folgender Perl-Zeile in MyUtils?
if ($kanalSoll > $kanalIst) {foreach my $i ($kanalIst..$kanalSoll) {fhem("say $i; sleep 1; set Rollo_Plus push; set DU_FB_aktiv on-for-timer 10;")}};
Nach meinem Verständnis sollte fhem nach jedem Schleifenschritt 1 Sekunde warten, geht aber nicht. Rennt einfach durch. Bei der Testansage kommt nur 1 und 4, 2 und 3 werden ausgelassen, also wird nicht gewartet.
Hat jemand einen Tipp für mich? Danke im Voraus.
Lies mal hier: https://fhem.de/commandref_DE.html#command
Das hatte ich bereits getan, bevor ich hier fragte. Leider habe ich keine Lösung gefunden. Deshalb frage ich ja hier.
Dein sleep ist ein fhem sleep und hat mit der Schleife nichts zu tun. Das sleep sollte aber eine Verzögerung zwischen der Befehlsverarbeitung von say und set machen.
Ja, das ist auch mein Plan gewesen. Die Schleife wird aber mehrfach durchlaufen. Insofern sollte die Verzögerung doch auch mehrfach auftreten und der Befehl auch mehrfach abgearbeitet werden. Was passiert aber offenbar nicht. Die Schleife wird durchgezählt, also theoretisch auch abgearbeitet. Der Zähler wird ja auch erhöht. Die Verzögerung tritt nicht auf. Ich will quasi bei der Abarbeitung eines jeden Zählers in der Schleife eine Pause erzeugen. Kann es sein, dass sleep innerhalb einer Schleife nicht mehrfach funktioniert?
Die kannst Dir den per fhem auszuführenden Befehl durch die Schleife erst komplett als String zusammenstellen und nach der Schleife zur Ausführung bringen.
Ich benutze das in einer Sonnenaufgangssimulation.
Etwa so:
if ($kanalSoll > $kanalIst)
{
my $cmd;
foreach my $i ($kanalIst..$kanalSoll)
{
$cmd .= "sleep 2;" if ($cmd);
$cmd .= "say $i; set Rollo_Plus push; set DU_FB_aktiv on-for-timer 10;";
}
fhem $cmd;
}
Gruß
Dan
Hi,
das sleep schickt den ganzen Rest sozusagen in den Hintergrund. D.h. es werden erst alle 3 say-Kommandos ausgeführt und dann erst das, was jeweils nach dem sleep kommt. Der Ablauf ist also ungefähr folgendermaßen:
say 1
say 2
say 3
say 4
(hier vielleicht noch ein bisschen Pause)
set Rollo_Plus push
set DU_FB_aktiv on-for-timer 10
set Rollo_Plus push
set DU_FB_aktiv on-for-timer 10
set Rollo_Plus push
set DU_FB_aktiv on-for-timer 10
set Rollo_Plus push
set DU_FB_aktiv on-for-timer 10
Ich vermute mal, dass "say" schnell hintereinander sich unter Umständen verschluckt.
Um Dir richtig zu helfen müsste man vielleicht etwas mehr Kontext wissen...
Gruß,
Thorsten
das sleep sorgt dafür das das nachfolgende kommando auf halde gelegt wird bis es dran ist. der code aussenrum (deine schleife) läuft sofort weiter. das ist auch gut so weil sonst dein komplettes fhem für die ganze zeit blockiert wäre. fhem ist nicht multithreaded.
einen möglichen weg wie man das angehen kann findest du in diesem thread: https://forum.fhem.de/index.php/topic,51906.msg436451.html#msg436451
oder du schaust dir mal das ROLLO modul aus dem wiki an.
OK, habe ich verstanden. Sleep verzögert ausschliesslich den einen nachfolgenden Befehl. Schade.
Das Modul Rollo kann ich leider für meine Aufgabe nicht nutzen. Ich muss das richtige Rollo immer über den zugehörigen Kanal der FB ansteuern. Diesen Kanal muss ich also zuerst wählen. Das sollte diese Schleife erledigen, was nun aber leider so nicht geht. Ich habe noch keinen Plan, was ich nun machen könnte. Mal überlegen.
Danke für die Erklärungen.
Zitat von: Invers am 29 März 2017, 09:39:55Diesen Kanal muss ich also zuerst wählen. Das sollte diese Schleife erledigen, was nun aber leider so nicht geht. Ich habe noch keinen Plan, was ich nun machen könnte. Mal überlegen.
Schau Dir den Beitrag von DeeSPe an. Das müsste im Prinzip gehen, vielleicht ein bisschen umsortiert.
Gruß,
Thorsten
Danke für eure Mühe und Geduld. Bin halt blutiger Perl Anfänger.
Ich habe mal das Beispiel von DeeSpee probiert, bekomme jedoch eine Fehlermeldung, die ich nicht deuten oder beseitigen kann, da ich noch zu wenig Durchblick habe.
Can't modify constant item in concatenation (.) or string at ./FHEM/99_myUtils.pm line 699, near ""sleep 2;" if"
Da ich Teile genau dieser Zeile: cmd .= "sleep 2;" if ($cmd); nicht verstehe, bitte ich um einen Tipp, oder eine Korrektur.
Mein Verständnis scheitert hier am Teil if ($cmd) . Welche Bedingung greift denn hier?
Danke für die Geduld.
Hi,
vor alle "cmd" muss ein "$". Also z.B.:
$cmd .= "sleep 2;" if ($cmd);
So etwas wie
... if ($cmd);
bedeutet grob gesagt "...wenn $cmd nicht leer".
Gruß,
Thorsten
Dann hätte ich if ($cmd) eher am Zeilenanfang erwartet, weil ja in mir bekannten Programmiersprachen immer if...then benutzt wird. Aber wich werde versuchen, das zu vertiefen. Dankeschön.
Zitat von: Invers am 29 März 2017, 10:37:58
Dann hätte ich if ($cmd) eher am Zeilenanfang erwartet, weil ja in mir bekannten Programmiersprachen immer if...then benutzt wird.
Dann willkommen bei Perl...
Soweit ich weiß ist es so: Wenn man das if am Anfang hat, dann braucht man danach {}. Wenn man aber nur ein Statement hat, dann kann man die {} weglassen und schreibt das if danach.
Das mag etwas ungewöhnlich sein, ist aber ein ganz normales Perl-Idiom.
Gruß,
Thorsten
@Thorsten Pferdekaemper
Dein Code funktioniert hervorragend.
Auch die Erklärung zum if habe ich nun verstanden.
Meinen äusserst erfreuten Dank. Natürlich auch an alle Anderen, die sich meiner Unkenntnis erbarmt haben. :-)
Zitat von: Thorsten Pferdekaemper am 29 März 2017, 10:28:59
Hi,
vor alle "cmd" muss ein "$". Also z.B.:
$cmd .= "sleep 2;" if ($cmd);
So etwas wie
... if ($cmd);
bedeutet grob gesagt "...wenn $cmd nicht leer".
Gruß,
Thorsten
Huch, das war mir selber gar nicht aufgefallen dass ich das vergessen hatte.
So ist das mit Code den man mal eben ungetestet aus dem Handgelenk schüttelt.
Habe es mal in meinem früheren Beitrag berichtigt.
Gruß
Dan
Sorry, war natürlich dein Code, nicht der von Thorsten. Das habe ich vor lauter Freude über den funktionierenden Code durcheinander gebracht.
Ja, ich vergesse zum Beispiel immer wieder das Semikolon am Zeilenende.