Ankündigung

Einklappen
Keine Ankündigung bisher.

Taster-Doppelklick via Logik

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Taster-Doppelklick via Logik

    Hallo zusammen!

    Mich wundert es, dass ich hier keine Threads zu dem Thema finden kann und ich es auch nicht selbst auf die Reihe bekomme.. aber naja

    Was ich will: Im Smarthome.py soll erkannt werden, ob auf einen KNX Taster doppelt geklickt wurde (zB innert 0,5 Sekunden). Dann soll eine andere Aktion getriggert werden als bei einem Einfachklick.

    Meine Ansätze mit prev_age, Timern, etc. in einer Logik sind kläglich gescheitert. Ich bin mir sicher, ihr habt einen schnellen, simplen Trick für einen Unwissenden?

    Vielen Dank!

    #2
    Naiv hätte ich jetzt auch erstmal prev_age versucht, was geht daran nicht? Poste doch mal was du hast und wie du die GAs im Taster belegt hast.
    Mit freundlichen Grüßen
    Niko Will

    Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
    - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

    Kommentar


      #3
      Hi,

      das geht in der Tat nicht (mehr).
      Ich habe dazu in das item.py erweitern müssen mit einer neuen Methode..

      Code:
      diff --git a/lib/item.py b/lib/item.py                                                                                                                                                                                                                                          
      index d912b7b..4e32f80 100755                                                                                                                                                                                                                                                   
      --- a/lib/item.py                                                                                                                                                                                                                                                               
      +++ b/lib/item.py                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                      @@ -363,6 +363,7 @@ class Item():                                                                                                                                                                                                                                               
                       self._change_logger("Item {} = {} via {} {} {}".format(self._path, value, caller, source, dest))                                                                                                                                                               
               self._lock.release()                                                                                                                                                                                                                                                   
               if _changed or self._enforce_updates or self._type == 'scene':                                                                                                                                                                                                         
      +            self.__prev_update = self.__last_update                                                                                                                                                                                                                            
                   self.__last_update = self._sh.now()                                                                                                                                                                                                                                
                   for method in self.__methods_to_trigger:                                                                                                                                                                                                                           
                       try:                                                                                                                                                                                                                                                           
      @@ -422,6 +423,10 @@ class Item():                                                                                                                                                                                                                                              
           def last_update(self):                                                                                                                                                                                                                                                     
               return self.__last_update                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                      
      +    def prev_update_age(self):                                                                                                                                                                                                                                                 
      +        delta = self.__last_update - self.__prev_update                                                                                                                                                                                                                        
      +        return delta.total_seconds()                                                                                                                                                                                                                                           
      +                                                                                                                                                                                                                                                                               
           def prev_age(self):                                                                                                                                                                                                                                                        
               delta = self.__last_change - self.__prev_change                                                                                                                                                                                                                        
               return delta.total_seconds()

      Kommentar


        #4
        Hallo Buffi!

        Danke für den Ansatz. In dem Fall frag ich nach dem Ändern der item.py in der Logik nach prev_update_age. Allerdings verstehe ich die Funktionsweise nicht so ganz... wie sähe dann die Logik aus?

        Vielleicht denke ich zu kompliziert, aber das eigentliche Problem besteht ja darin, dass der erste Klick auf jeden Fall triggert - er soll aber erst triggern, wenn danach kein weiterer Klick mehr kommt.

        Konkret habe ich das wie folgt versucht:
        Taster triggert GA 1/0/0
        1/0/0 ist die Aktion, die beim normalen Klick ausgeführt werden soll, aber NICHT beim Doppelklick

        Logik checkt dann, ob prev_age unter 0.4 Sekunden ist und triggert die zweite Aktion. Soweit alles wunderbar. ABER wie gesagt wird "natürlich" auch 1/0/0 geschalten, da prev_age vom ersten Klick des Doppelklicks gleich wie ein Singleklick höher ist.

        Also habe ich einen sleep, timer, wait, etc. für die 1/0/0 in der Logik drin, damit zuerst mal abgewartet wird, ob noch ein Klick kommt. Und wenn der Klick kommt, sollte 1/0/0 "abgebrochen" werden. Das hat soweit aber nicht wirklich funktioniert.

        Eine Überlegung wäre nun, die Aktion für 1/0/0 mit einem Scheduler anzulegen (sh.scheduler.add), der nach 0.5 Sekunden durchgeführt wird. Und falls der Doppelklick kommt gibt es ein sh.scheduler.remove. Keine Ahnung, ob das funktionieren kann. Habe derweilen auf ne sauberere/andere Lösung gehofft Werde es aber am Abend mal testen.

        Merci!

        Kommentar


          #5
          Genau, du musst von dem Taster dann eine GA senden lassen, die von keinem Aktor konsumiert wird. sh.py entscheidet dann, welche eigentliche GA geschaltet wird. Nachteil, wenn sh.py down, dann schaltet der Taster nix mehr. Aber anders wird es nicht gehen.
          Mit freundlichen Grüßen
          Niko Will

          Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
          - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

          Kommentar


            #6
            Jup.. das wär in meinem Fall egal, da es um das Schalten vom Soundplayer geht. Bei normalem Klick soll ne Playliste geladen werden, bei Doppelklick auf den vorigen Track geskippt werden. Wenn da mal die "Hauptfunktion" nicht funktioniert, wär das kein Drama

            Aber wie gesagt, es ginge halt um das Abfangen des "Normalverhaltens", das nur dann getriggert werden soll, wenn kein weiterer Klick folgt. Meinst du, über das Scheduling funktioniert das? Hab's über threading.Timer probiert, der dann gecancelt wird, wenn 2. Klick folgt, aber das war irgendwie nix..

            Kommentar


              #7
              Das sollte über den Scheduler gehen. Mit sh.scheduler.trigger() und sh.scheduler.change(). Mit Threading in einer Logik würde ich nicht hantieren.
              Mit freundlichen Grüßen
              Niko Will

              Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
              - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

              Kommentar


                #8
                Bei mir benötigte ich 3 klicks: ich habs dann so gemacht.

                bei einem Item definieren:
                Code:
                [Item1]
                        multiklick                                                                                                                                                                                                                                                              
                        klick_count = 3
                
                           [[multiklick]] # das hier wird dann getriggert                                                                                                                                                                                                                                                        
                               enforce_updates = true                                                                                                                                                                                                                                              
                               type = foo
                Logik definieren:
                Code:
                [Mehrfachklick]                                                                                                                                                                                                                                                                 
                    filename = mehrfachklick.py                                                                                                                                                                                                                                                 
                    watch_item = *:multiklick
                mehrfachklick.py
                Code:
                #!/usr/bin/env python                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                
                item = sh.return_item(trigger['source'])                                                                                                                                                                                                                                        
                mcitem = sh.return_item(trigger['source']+'.multiklick')                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                
                if 'klick_count' in item.conf:                                                                                                                                                                                                                                                  
                    count = int(item.conf['klick_count'])                                                                                                                                                                                                                                                                                                              
                    if hasattr(logic, 'save_state_' + item.id()):                                                                                                                                                                                                                               
                                                                                                                                                                                   
                        if item.prev_update_age() < 1:                                                                                                                                                                                                                                          
                            val = int (getattr(logic, 'save_state_' + item.id())) + 1                                                                                                                                                                                                           
                            setattr(logic, 'save_state_' + item.id(), val)                                                                                                                                                                                                                                                                                                                                                                    
                        else:                                                                                                                                                                                                                                                                   
                            setattr(logic, 'save_state_' + item.id(), 1)                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                
                    else:                                                                                                                                                                                                                                                                       
                        setattr(logic, 'save_state_' + item.id(), 1)                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                
                    if int (getattr(logic, 'save_state_' + item.id())) > count-1:                                                                                                                                                                                                               
                        mcitem(1)                                                                                                                                                                                                                                                                                                                                                  
                        setattr(logic, 'save_state_' + item.id(), 0)

                Kommentar


                  #9
                  Schöne Sache. Was ich noch nicht ganz verstehe, wie wertest du aus, was bei nur zwei oder einem Tastendruck passieren soll?
                  Mit freundlichen Grüßen
                  Niko Will

                  Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                  - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                  Kommentar


                    #10
                    bei 1 oder 2 Klick's passiert nichts und werte auch nichts aus. Ginge aber sicherlich auch irgendwie

                    Kommentar


                      #11
                      Irgendwie ja, aber nicht mit einer reinen Vergleichslösung wie du es gepostet hast. Denn dann würde bei klick_count = 1 die Aktion unmittelbar nach einem Klick ausgeführt werden. Um das zu Realisieren, was der TE gern hätte, muss auf jeden Fall noch gewartet werden, ob evtl. noch ein weiterer Tastendruck kommt.
                      Mit freundlichen Grüßen
                      Niko Will

                      Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                      - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                      Kommentar


                        #12
                        Hab ein bisserl rumprobiert, brauche aber echt eure Hilfe

                        Meine Idee war, dem Main-Item auch noch ein "Singleclick" zu geben. Dieses hat einfach nur type bool, die Logic.conf wartet auf eine Veränderung dieses Singleclicks und löst dann eine Aktion aus.

                        Und dann soll in der Logik von buffi ganz unten ein else stehen:
                        Code:
                               next_time = sh.now() + dateutil.relativedelta.relativedelta(seconds=10)
                               scitem = sh.return_item(trigger['source']+'.singleclick')
                               sh.scheduler.trigger('singleclick', scitem, next_time, 1,1,1)
                        Beim Debugging sieht es gar nicht so schlecht aus.. Scheduler setzt die Aktion in 10 Sekunden, allerdings wird sie dann interessanterweise doch sofort ausgeführt.

                        Code:
                        2014-05-20 21:59:28,673 INFO     Mehrfachklick {'dest': None, 'source': 'Squeezebox_KG.Playlist_Andy.Load', 'by': 'Item', 'value': False} -- multiclick.py:<module>:2
                        2014-05-20 21:59:28,679 DEBUG    Mehrfachklick Gerade durch -- multiclick.py:<module>:27
                        2014-05-20 21:59:28,687 DEBUG    Mehrfachklick Triggering singleclick - by: 2014-05-20 21:59:38.683533+02:00 source: 1 dest: 1 value: 1 -- scheduler.py:trigger:162
                        2014-05-20 21:59:28,696 DEBUG    singleclick  Triggering AmpBad_Andy - by: Item source: Squeezebox_KG.Playlist_Andy.Load.singleclick dest: None value: True -- scheduler.py:trigger:162
                        2014-05-20 21:59:28,701 INFO     AmpBad_Andy  {'dest': None, 'source': 'Squeezebox_KG.Playlist_Andy.Load.singleclick', 'by': 'Item', 'value': True} -- amp_bad_andy.py:<module>:11
                        Leider check ich auch das watch_item in der Logik nicht... Wie kann ich alle Items überwachen, die ein Unteritem "multiclick" bzw. das Wort "multiclick" drin haben? Mit dem *: funzt das bei mir nicht.. Das knx_listen (auf die Taste) muss doch in "Item1" sein, oder?

                        Kommentar


                          #13
                          Schau dir nochmal die Parameterreihenfolge von sh.trigger an:

                          This global function triggers any specified logic by its name. sh.trigger(name [, by] [, source] [, value] [, dt]) name (mandatory) defines the logic to trigger. by a name of the calling logic. By default its set to ‘Logic’. source the reason for triggering. value a variable. dt timezone aware datetime object, which specifies the triggering time.
                          EDIT: bzw. verwendest du ja sh.scheduler.trigger, da sieht es so aus:

                          sh.scheduler.trigger(name, obj=None, by='Logic', source=None, value=None, dest=None, prio=3, dt=None):
                          Mit freundlichen Grüßen
                          Niko Will

                          Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                          - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                          Kommentar


                            #14
                            Danke, 2nd sky.. konnte irgendwie nix zum scheduler.trigger finden - hätt wohl im Quellcode nachgucken sollen. Okay, dann probier ich's nochmals mit einer anderen Reihenfolge - wäre natürlich cool, wenn das klappen würde, hehe.

                            Kommentar


                              #15
                              Wenn du das in die Logik von buffi einfügst, denk auch im Falle eines singleclick daran, den counter für multiclick zurück zu setzen
                              Mit freundlichen Grüßen
                              Niko Will

                              Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
                              - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

                              Kommentar

                              Lädt...
                              X