Ankündigung

Einklappen
Keine Ankündigung bisher.

Plugins - Zeitversetzte Reaktion?

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [wiregate] Plugins - Zeitversetzte Reaktion?

    Was ist der empfohlene Weg, um in einem Plugin eine zeitversetzte Reaktion auszulösen?

    Konkret:
    Ich habe ein Plugin, das auf eine GA hört und je nach Wert, der an diese GA gesendet wird, die Visu per WOL weckt, schlafen legt oder herunterfährt.
    Wenn nun der Befehl zum Schlafen oder zum Herunterfahren kommt und der Visu-PC aber gerade heruntergefahren ist bzw. schläft muss ich den erst mal aufwecken um ihn dann ca. eine halbe Minute später in den gewünschten Status zu bringen...
    TS2, B.IQ, DALI, WireGate für 1wire so wie Server für Logik und als KNX Visu die CometVisu auf HomeCockpit Minor. - Bitte keine PNs, Fragen gehören in das Forum, damit jeder was von den Antworten hat!

    #2
    Ich denke am ehesten wie folgt:

    - an GA anmelden
    - Wert an GA auswerten, Merker setzen
    - Cycle auf gewünschten Verzögerungswert setzen
    - beim zyklischen Aufruf prüfen ob Merker gesetzt, ggfs. Aktion starten, Merker+cycle resetten

    Kostet nichts und sollte recht präzise laufen, weil z.B. sleep ist eine gaaanz dumme Idee: das würde die gesamte Verarbeitung blockieren! (Chris weiss das, aber ...)

    Also in etwa so: (syntaktisch ungeprüft)
    Plugin "Verzögerte Aktion"
    Code:
    ### Definitionen
    $plugin_info{$plugname.'_cycle'} = [COLOR="Red"]0[/COLOR]; # egal..
    my $ga = "14/6/111";  # Gruppenadresse zum aktivieren
    my $delay = 30;  # Verzögerung in sek.
    ### Ende Definitionen
    
    if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $ga and $msg{'data'}) { # nur bei bei 1 an $ga
       $plugin_info{$plugname.'_sema'} = 1;
       $plugin_info{$plugname.'_cycle'} = $delay;
    [COLOR="Red"]   $plugin_info{$plugname.'_last'} = time();
    [/COLOR]} elsif ($plugin_info{$plugname.'_sema'}) {
       # mach verzögert irgendwas sinnvolles
       # -> hier
       $plugin_info{$plugname.'_sema'} = 0;
       $plugin_info{$plugname.'_cycle'} = [COLOR="Red"]0[/COLOR]; # egal..
    } else { # zyklischer Aufruf
       # Plugin an Gruppenadresse "anmelden"
       $plugin_subscribe{$ga}{$plugname} = 1;
    }
    
    return;
    Edit 2012-05-26: Angepasst auf aktuelle Version..

    Makki
    EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
    -> Bitte KEINE PNs!

    Kommentar


      #3
      Danke, probiere ich aus.

      Was andere (und nur leicht OT):
      Gibt es eine Möglichkeit remote den Status eines Linux-Rechners festzustellen, d.h. ob er läuft (sollte per ping gehen), schläft oder ausgeschaltet ist (gerade für die Unterscheidung der beiden fällt mir gerade nichts ein...)
      TS2, B.IQ, DALI, WireGate für 1wire so wie Server für Logik und als KNX Visu die CometVisu auf HomeCockpit Minor. - Bitte keine PNs, Fragen gehören in das Forum, damit jeder was von den Antworten hat!

      Kommentar


        #4
        On ein Host erreichbar ist, wäre ganz Quick&Dirty natürlich ein 4-Zeiler:
        Code:
        my $addr = "172.17.2.92";
        system("ping","-c1",$addr);
        if ($?) { # nicht erreichbar 
        	# mach was
        	return "Host $addr nicht erreichbar: $?";
        } elsif ($? == 0) { # host pingbar
        	# mach was anderes
        	return "Host $addr ist erreichbar";
        }
        (c1 = Anzahl der Pings, könnte man bei zu erwartenden Problemen evtl. auf 2 oder 3 erhöhen, im geswitchten LAN aber unnötig..)

        bzgl. Suspend/Standby dürfte das einfachste sein, im entspr. Skript lokal (das findest Du schneller als ich..) einen dezenten
        groupswrite ip:WIREGATE GA 0/1
        zu machen.
        Den Zustand sonst remote festzustellen würde mir so auf Anhieb nichts einfallen (mal von Servern mit IPMI&Co abgesehen)
        Edit: mit dem Ping + dem Switchport per SNMP wüsste man natürlich zumindest ob er wach ist, tot oder schläft, aber jetzt wirds wild und braucht managed Switches

        Makki
        EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
        -> Bitte KEINE PNs!

        Kommentar


          #5
          Zitat von Chris M. Beitrag anzeigen
          Gibt es eine Möglichkeit remote den Status eines Linux-Rechners festzustellen, d.h. ob er läuft (sollte per ping gehen), schläft oder ausgeschaltet ist (gerade für die Unterscheidung der beiden fällt mir gerade nichts ein...)
          Panzeron hat vor ein paar Tagen ein Plugin in den Codeschnipseln eröffnet, vielleicht ist das hilfreich: https://knx-user-forum.de/code-schni...ermitteln.html

          Gibt auch noch ein WOL-Plugin, ebenfalls von Panzeron.

          Kommentar


            #6
            Hallo,

            aus Fehler wird man ja bekanntlich klug:
            Bei mir werkelt erfolgreich folgendes Plugin:
            Code:
            ####################
            ###Einstellungen:###
            ####################
            
            my $Fenster_GA = '10/0/31'; # hier die GA von allen Fenstern ohne Haustür --> gesetzt durch Plugin
            my $Haustuer_GA = '10/0/14'; # hier die GA der Haustür  --> gesetzt durch Plugin
            my $zustand_geschlossen = 1;    # auf richtige polarit?t achten!
            my $zustand_offen = 0;
            my $Dauer_Benachrichtigung = 3; # Dauer in Sekunden
            my $schalt_GA = '1/3/18'; # GA die bei Benachrichtung adressiert wird
            my $count =1;
            
            ###
            
            $plugin_subscribe{$Haustuer_GA}{$plugname} = 1;
            if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $Haustuer_GA) {
            $plugin_info{$plugname.'_aktiv'} = int($msg{'data'});
            
            
            #Hier wird der aktuelle Wert für die Fensterzustände gelesen:
                my $ZustandFenster = knx_read($Fenster_GA,0,1);
            
            
            #Hier wird der aktuelle Wert für die Haustüre gelesen:
                my $ZustandHaustuere = knx_read($Haustuer_GA,0,1);
            
                if (($ZustandFenster == $zustand_offen) && ($ZustandHaustuere == $zustand_offen)) { # ein Fenster offen, Haustür geöffnet
                        knx_write($schalt_GA,1,1);
                         sleep($Dauer_Benachrichtigung);
                    $plugin_info{$plugname.'_cycle'} = $Dauer_Benachrichtigung;
                        knx_write($schalt_GA,0,1);
            
            ### neu
            #if ($plugin_info{$plugname.'_aktiv'} and $count == 1) {
            #     knx_write($schalt_GA,1,1); # read&write last value - logical OR
            #     $count++;
            #     $plugin_info{$plugname.'_cycle'} = $Dauer_Benachrichtigung;
            #     }
            ###
            
            
                    }
            }
            Die Zeitverzögerung habe ich nun mit sleep() gelöst. Nach Lektüre des obigen Posts möchte ich das jedoch umbauen.

            Ich habe nun versucht Makki's Code von oben für mich anzuüpassen. Das hat aber nicht funktioniert.

            Es müsste doch wie folgt aufgebaut sein:
            Code:
            ### Definitionen
            $plugin_info{$plugname.'_cycle'} = 86400; # egal..
            my $ga = "14/6/111";  # Gruppenadresse zum aktivieren
            my $delay = 30;  # Verzögerung in sek.
            ### Ende Definitionen
            
            if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $ga and $msg{'data'}) { # nur bei bei 1 an $ga
               $plugin_info{$plugname.'_sema'} = 1;
            # Hier WENN Prüfung
            # ($ZustandFenster == $zustand_offen) && ($ZustandHaustuere == $zustand_offen)) { 
            # ein Fenster offen, Haustür geöffnet 
            #            knx_write($schalt_GA,1,1); 
            # ENDE WENN Prüfung
            
               $plugin_info{$plugname.'_cycle'} = $delay;
            } elsif ($plugin_info{$plugname.'_sema'}) {
               # mach verzögert irgendwas sinnvolles
               # -> hier
               # Hier dann das Auschalten der zuvor eingeschalteten GA
               # knx_write($schalt_GA,0,1); 
               # Ende
               $plugin_info{$plugname.'_sema'} = 0;
               $plugin_info{$plugname.'_cycle'} = 86400; # egal..
            } else { # zyklischer Aufruf
               # Plugin an Gruppenadresse "anmelden"
               $plugin_subscribe{$ga}{$plugname} = 1;
            }
            
            return;
            Das funktioniert so aber nicht. Mache ich da noch etwas konzeptionell falsch? Möchte das gerne verstehen, um die nächste Logik angehen zu können.
            Danke!
            Gruß
            alexbeer

            Kommentar


              #7
              Zitat von alexbeer Beitrag anzeigen
              Die Zeitverzögerung habe ich nun mit sleep() gelöst.
              sleep ist so ungefähr worst-case: Das wird aufgrund einiger, vieler hässlichkeiten Single-Threaded ausgeführt. Also kann man in einem Plugin schon schlafen aber solange schlafen auch alle anderen.. ->

              [CODE]
              ...
              Das war ein recht einfaches, altes Beispiel, das aber prinzipiell so funktionieren sollte, emax hat das mit seiner Zeitschaltuhr etwas verfeinert (prinzipiell wäre ein präziser Timer/Scheduler besser aber dafür wurde die ganze Plugin-Umgebung so per se nicht gemacht das mag mal irgendwann kommen aber wann = ??)

              Ergo: was geht denn genau nicht, weil gehn tut alles, ist nur eine Frage des Aufwands
              In alles schön ein: return "debug-infos: ..." einbauen

              Makki
              EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
              -> Bitte KEINE PNs!

              Kommentar


                #8
                Hallo,

                ich habe (meiner Meinung nach) das Beispiel von Makki ausprobiert.
                So ähnlich hatte ich zuvor schon versucht eine Zeitverzögerung zu realisieren, ich habe aber das Problem, daß das schon vorher nicht funktioniert hat und auch jetzt nicht funktioniert,
                Code:
                $plugin_info{$plugname.'_cycle'} = 86400; # egal..
                my $aufrufende_ga = '8/1/0';
                my $delay = 15;
                
                if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $aufrufende_ga and $msg{'data'}) { # nur bei bei 1 an $ga
                   knx_write('0/4/2',"1","1");
                   $plugin_info{$plugname.'_sema'} = 1;
                   $plugin_info{$plugname.'_cycle'} = $delay;
                } elsif ($plugin_info{$plugname.'_sema'}) {
                   knx_write('0/4/2',"0","1");
                   #knx_write($aufrufende_ga,"0","1");
                   $plugin_info{$plugname.'_sema'} = 0;
                   $plugin_info{$plugname.'_cycle'} = 86400; # egal..
                } else { # zyklischer Aufruf
                   # Plugin an Gruppenadresse "anmelden"
                   $plugin_subscribe{$aufrufende_ga}{$plugname} = 1;
                }
                return;
                Kann da jemand einen Fehler entdecken?

                Auf dem Bus kann ich die Nachricht zum Ausschalten gleich nach dem Anschalten und nicht erst nach 15 Sekunden sehen.
                Es sieht für mich so aus, daß das Plugin aus irgendwelchen Gründen immer wieder gestartet wird und nicht erst nach den 15 Sekunden.

                Kommentar


                  #9
                  Hallo Oliver

                  Wenn ich das Plugin richtig lese, denn sehe ich folgendes Problem...

                  Code:
                  .....
                  } elsif ($plugin_info{$plugname.'_sema'}) {
                  .....
                  Bedeutet -> Wenn $plugname.'_sema' definiert wurde, ist die Bedingung TRUE und damit wird dieser Teil der If Abfrage auch unmittelbar ausgeführt, weil $plugname.'_sema' in der Zeile 7 bereits definiert wurde.

                  Versuche mal am ende der ersten If abfrage noch ein return; einzubauen um zu verhindern, dass die elsif abfrage direkt nach der ifabfrage ausgeführt werden kann.

                  z.B. so...

                  Code:
                  if ($msg{'apci'} eq "A_GroupValue_Write" and $msg{'dst'} eq $aufrufende_ga and $msg{'data'}) { # nur bei bei 1 an $ga
                     knx_write('0/4/2',"1","1");
                     $plugin_info{$plugname.'_sema'} = 1;
                     $plugin_info{$plugname.'_cycle'} = $delay;
                     return;
                  } elsif ($plugin_info{$plugname.'_sema'}) {
                  ...
                  Gruss Patrik alias swiss

                  Kommentar


                    #10
                    Das "Problem" ist das die Plugin-Ausführungszeit (bewusst) nur bei zyklischen Aufrufen, nicht jedoch bei aufrufen durch Telegramme/Socket zurückgesetzt wird;
                    Daher wird es sofort nochmal aufgerufen wenn man den cycle von 86400 auf 15 setzt (=1 Tag, 0 wär übrigens genauso gut; nie ausser zum init)

                    Im ersten if noch ein:
                    Code:
                    $plugin_info{$plugname.'_last'} = time();
                    sollte es tun.

                    @Patrik: elsif ist nur, wenn if nicht zutrifft

                    Edit: grad erst gesehen und oben geändert, das verhalten wurde seither geändert um andere Funktionen zu ermöglichen.


                    Makki
                    EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
                    -> Bitte KEINE PNs!

                    Kommentar


                      #11
                      Hallo Makki,
                      das wars.

                      Vielen Dank.

                      Kommentar

                      Lädt...
                      X