Unerwartetes Verhalten / perl / for-schleife/ fhem(...) / 99_Utils

Begonnen von jazzor, 02 Dezember 2016, 00:02:55

Vorheriges Thema - Nächstes Thema

jazzor

Hallo zusammen,

ausgehend von diesem beitrag, in dem ich um Ideen zur Ansteuerung meiner Fernbedienung per GPIO bat, habe ich angefangen mir Subs zu schreiben, die die Logik der unterschiedlichen Rollos auflösen sollen.
Leider habe ich dabei ein Problem, dass nämlich der Funktionsaufruf innerhalb der For-Schleife im Sub RolladenKanalWechsel($) im zweiten Block direkt durchläuft, obwohl die Befehle in Fhem noch nicht abgeschlossen sind.
Zum Testen hatte ich dann mal die führenden sleep() eingefügt, die aber ja auch nichts bringen, da die for-schleife drüber hinweghuscht.

Kann mir jemand nen Tipp geben? Kann ich die For-Schleife dazu bringen, auf die Ausführung der Fhem-Befehle zu warten?

Viele Grüße!

sub RolladenButtonPress($){
   my ($gpioNr) = @_;
      #Log 1, ("\$gpioNr = $gpioNr");
      my $zuletztBenutzt = ReadingsVal("RolloSpeicherDummy","Zeitpunkt",0);
      my $aktZeitpunkt = time();
      my $differenz = $aktZeitpunkt - $zuletztBenutzt;
      Log 1,("\$zuletztBenutzt \:$zuletztBenutzt  \| \$aktZeitpunkt \: $aktZeitpunkt");
      Log 1,("differenz\: $differenz");
   if (($aktZeitpunkt - $zuletztBenutzt)>4.75)
   {
      #Log 1, ("Doppelklick");
      fhem("sleep 0.25;set GPIO$gpioNr on-for-timer 0.5 ; sleep 0.25 ; set GPIO$gpioNr on-for-timer 0.15 ; sleep 0.25");
   } else {
      #Log 1, ("Einfachklick");
      fhem("sleep 0.25; set GPIO$gpioNr on-for-timer 0.15");
   }
   fhem ( "setreading RolloSpeicherDummy Zeitpunkt " .time() );
}
#############################################################

sub RolladenKanalWechsel($) {
   my ($neuerKanal) = @_;
   my $aktKanal = ReadingsVal("RolloSpeicherDummy","aktKanal",0);
   if ($neuerKanal > $aktKanal){
      my $kanalschritte = $neuerKanal - $aktKanal;
      for (my $i=0; $i<$kanalschritte; $i++){
         RolladenButtonPress("7");
      };
      fhem ( "setreading RolloSpeicherDummy aktKanal $neuerKanal");
   } elsif ($neuerKanal < $aktKanal){
      my $kanalschritte = $aktKanal - $neuerKanal;
      for (my $i=0; $i<$kanalschritte; $i++){
         RolladenButtonPress("8");
      };
      fhem ( "setreading RolloSpeicherDummy aktKanal $neuerKanal");
   }
}

#############################################################

sub Rolladen2GPIO($$){
   my($richtung,$kanal) = @_;
   if ($richtung eq "up") {
      RolladenKanalWechsel($kanal);
      RolladenButtonPress("10");
      #Log 1, ('RolladenButtonPress(10)');
   } elsif ($richtung eq "stop") {
      RolladenKanalWechsel($kanal);
      RolladenButtonPress("9");
      #Log 1, ('RolladenButtonPress(9)');
   } elsif ($richtung eq "down") {
      RolladenKanalWechsel($kanal);
      RolladenButtonPress("11");
      #Log 1, ('RolladenButtonPress(11)');
   }
}

dev0

Zitat von: jazzor am 02 Dezember 2016, 00:02:55

      #Log 1, ("Doppelklick");
      fhem("sleep 0.25;set GPIO$gpioNr on-for-timer 0.5 ; sleep 0.25 ; set GPIO$gpioNr on-for-timer 0.15 ; sleep 0.25");

Vorsicht, ein FHEM sleep ohne nachfolgenden Befehl blockiert FHEM.

on-for-timer funktioniert intern so, dass direkt ein 'on' an das Device geschickt wird und dann ein interner Timer gestartet wird, der nach x sekunden das 'off' an das Device schickt. In der Zwischenzeit werden Deine Funktionen weiter abgearbeitet.

Wenn Du eine Art "Doppelklick" an ein Device schicken willst, dann muss das in etwas so aussehen:

fhem("set GPIO$gpioNr on-for-timer 0.5; sleep 0.6; set GPIO$gpioNr on-for-timer 0.5");

Das erste on wird direkt gesendet, nach 0.5s kommt das off, dann 0.1s pause (0.6 - 0.5), dann wird on gesendet und nach weiteren 0.5s das letzte off. Soll das jetzt wiederholt werden, dann muss das nächste on-for-timer schon um min. 1.6s verzögert gestartet werden...

Ich sehe adhoc 3 Möglichkeiten, wie Du weiter vorgehen kannst:

- Entweder Du übergibst der sub RolladenButtonPress() wie oft der og. Befehl wiederholt werden soll und kümmerst Dich dort dann in einer Schleife um das x-fache senden mit jeweils erhöhten sleep Zeiten, damit die Befehle sich nicht in die Quere kommen.

- oder Du rufst in der RolladenKanalWechsel() Schleife die sub RolladenButtonPress() jeweils über einen, pro Durchlauf erhöhten, Timer auf (InternalTimer).

- oder Du löst die Sub RolladenButtonPress() auf, schiebst den Code in die RolladenKanalWechsel() Schleife und berechnest (erhöhst) dort die nötigen sleep Werte bei jedem Durchlauf.