Ankündigung

Einklappen
Keine Ankündigung bisher.

Einfacher Taster mit mehreren Tastpunkten (Anel)

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

    Einfacher Taster mit mehreren Tastpunkten (Anel)

    Hi openHAB Gemeinde,

    ich beschäftige mich gerade mit den Anel Binding (NET-PwrCtrl HUT). Der Baustein funktioniert hervorragend! Folgende Logik möchte ich implementieren:
    Ich habe einen Eingang (IO1) definiert. Daran hängt ein normaler 1-fach Taster. Drücke ich ihn, geht am Relaisausgang 1 die Lampe an. Drücke ich noch mal, geht sie aus. Anbei der Code.

    Code:
    rule "Taster T1"
    when Item Anel_IO1 changed to OFF
    then
        sendCommand(Anel_F1, if (Anel_F1.state == ON) OFF else ON)
    end
    Um das ganze noch smarter zu machen, habe ich mich inspirieren lassen von Loxone. Die können mit einem Taster verschiedene Beleuchtungsszenen umsetzen (Link). Bsp. 1x Klick: Licht im Raum an, ein weiterer Klick: Szene A, weiterer Klick: Szene B. 2x Klick: Licht im Raum aus, 3x Klick: Radio an. Das mal so als Beispiel.

    Ich denke mit openHAB ist es auch möglich. Jemand eine Idee dazu ? Oder selber schon im Einsatz ?

    Merci u. Danke für euer Feedback!
    hardoverflow

    #2
    Um bei einzelnen Klicks jeweils andere Lichtstimmungen abzurufen, könnte man pro Klick ein Item hochzählen. Das löst dann mit einer weiteren Rule die verschiedenen Zustände aus.
    Für die Mehrfach-Klick-Erkennung wäre vermutlich beim 1. Klick ein Timer zu starten, falls vor Ablauf des Timers die Rule ein weiteres Mal gestartet wird, wird der Timer gecancled und die Alternativaktion ausgeführt. bei Dreifachklick wäre das dann ein weiterer Timer.
    Wenn der Timer abläuft, wird jeweils die entsprechende Aktion ausgelöst.
    Ist halt etwas Aufwand, aber sicher realisierbar.

    Kommentar


      #3
      Was ich bis jetzt hinbekommen habe ist folgendes:

      Code:
      rule "Anel IO1 - Testing rule"
      when Item Anel_PWR_IO1 changed to OFF
      then
          Anel_IO1 = Anel_IO1 + 1
          if (Anel_IO1 > 3) {
              Anel_IO1 = 0
          }
          logInfo( "Taster", "Anel_IO1: " + Anel_IO1)
          if (Anel_IO1 == 0) {
                  sendCommand(Anel_PWR_F1, OFF)
                  sendCommand(Wireless_Milight_01, OFF)
          }
          if (Anel_IO1 == 1) {
                  sendCommand(Anel_PWR_F1, ON)
          }
          if (Anel_IO1 == 2) {
                  sendCommand(Wireless_Milight_01, ON)
          }
          if (Anel_IO1 == 3) {
                  sendCommand(Anel_PWR_F1, OFF)
          }
      end
      Mit dem Code kann ich wunderbar verschiedene Szenen durchschalten. Aber jetzt möchte ich noch einen Doppelklick / Dreifachklick auf den Taster hinzufügen. Quasi eine neue Ebene.

      udo1toni : Dein Vorschlag kann ich zwar nachvollziehen aber leider nicht in Code implementieren. Kann da jemand helfen ?
      Zuletzt geändert von hardoverflow; 23.09.2015, 16:01.

      Kommentar


        #4
        Hi,
        du müsstest erstmal prüfen wie schnell kann openHab deine Klicks verarbeiten, ich vermute da schon einen Engpass.
        Aber man kann es ja mal versuchen.
        So in der Art kann es funktionieren (ungetestet):
        Code:
        var Timer timer_anel   = null  //Timer global
            
        rule "Anel IO1 - Testing rule"
        when Item Anel_PWR_IO1 changed to OFF
        then
            Anel_IO1 = Anel_IO1 + 1
            logInfo( "Taster", "Anel_IO1: " + Anel_IO1)
            
            if (timer_anel == null) // Timer noch nicht gestartet
            {
                timer_anel = createTimer(now.plusSeconds(1)) [|
                {
                    if         (Anel_IO1 == 1)  sendCommand(Anel_PWR_F1, ON)
                    else if (Anel_IO1 == 2)  sendCommand(Wireless_Milight_01, ON)
                    else if (Anel_IO1 == 3)  sendCommand(Anel_PWR_F1, OFF)
                    Anel_IO1 = 0
                    timer_anel.cancel // nicht sicher ob das notwendig ist
                    timer_anel=null
                } ]
            
            }
        end
        Die Rule wird bei jedem Klick aufgerufen, beim ersten mal wird ein Timer gestartet der hier nach 1 Sekunde nachschaut wie hoch der Zähler gekommen ist.

        Holger

        Kommentar


          #5
          Ich denke, eine halbe Sekunde sollte schon gehen, also den timer mit createTimer(now.plusMillis(500)) [|Kommandoblock, falls der Timer abgelaufen ist] anlegen, falls der Timer nicht existiert. Falls er existiert (else) müsste der Timer zuerst gelöscht werden (mit timer.cancel und anschließendem auf null setzen) und danach der Befehl ausgeführt werden, der bei Doppelklick kommen soll. Wenn man noch einen Dreifachklick abfangen will, müsste entsprechend im elseblock ein weiterer timer gestartet werden, auf den zu Anfang der Rule geprüft wird.

          Wichtig, damit die Sache mit dem Timer funktioniert ist noch ein Import für Joda-Time am Anfang der Rule-Datei (also vor der 1. Rule und vor der 1. Timer-Definition):
          Code:
          import org.joda.time.DateTime
          ...
          var Timer timer_anel = null
          ...
          Rule blabliblub
          ...
          Wenn der Timer abgelaufen ist, muss er nicht zurückgesetzt werden. Weiterhin darf man Anel_IO1 nur dann hochzählen, wenn der Taster einfach geklickt wurde (kann natürlich sein, dass der Doppelklick eh "Ausschalten" soll, dann wäre es egal, ob der Zähler vor dem Rücksetzen noch hochgezählt wird).

          Kommentar


            #6
            Danke für eure Hilfe erst einmal! Schon viel Wert :-) Aktuell sieht meine Rule so aus:

            Code:
            rule "Tasterschaltung - Pushbutton mit 2 Tastpunkten"
            when
                Item Anel_IO_T1 received command OFF
            then
                if (timerAnel_IO_T1 == null) {
                    timerAnel_IO_T1 = createTimer(now.plusMillis(500)) [|
                        varAnel_IO_T1_E0 = varAnel_IO_T1_E0 + 1
                        if (varAnel_IO_T1_E0 > 1) {
                            varAnel_IO_T1_E0 = 0
                        }
                        if (varAnel_IO_T1_E0 == 0) logInfo( "Anel_IO_T1", "Changed to: E0+" + varAnel_IO_T1_E0)
                        else if (varAnel_IO_T1_E0 == 1) logInfo( "Anel_IO_T1", "Changed to: E0+" + varAnel_IO_T1_E0)
                        timerAnel_IO_T1.cancel
                        timerAnel_IO_T1=null
                    ]
                }
                else if (timerAnel_IO_T1 != null) {
                    timerAnel_IO_T1.cancel
                    timerAnel_IO_T1=null
                    
                    timerAnel_IO_T1 = createTimer(now.plusMillis(500)) [|
                        varAnel_IO_T1_E1 = varAnel_IO_T1_E1 + 1
                        if (varAnel_IO_T1_E1 > 1) {
                            varAnel_IO_T1_E1 = 0
                        }
                        if (varAnel_IO_T1_E1 == 0) logInfo( "Anel_IO_T1", "Changed to: E1+" + varAnel_IO_T1_E1)
                        else if (varAnel_IO_T1_E1 == 1) logInfo( "Anel_IO_T1", "Changed to: E1+" + varAnel_IO_T1_E1)
                        timerAnel_IO_T1.cancel
                        timerAnel_IO_T1=null
                    ]
                }
            end
            Ebene 0 (Einfach-Klick) und Ebene 1 (Zweifach-Klick) funktionieren erst einmal ohne Probleme (virtuell). Heute Abend werde ich es mit der Hardware verknüpfen und mit einem richtigen Taster ausprobieren. Mir fehlt jetzt noch die "Dritte" Tastebene - wo und wie implementiere ich diese ?

            Merci

            Kommentar


              #7
              Ich hab es jetzt mal so getestet, ja es funktioniert, bei meinen gefühlt 100 Rules aber etwas träge und nicht immer präzise:
              Code:
              rule "Anel IO1 - Testing rule"
              when Item testswitch received command ON
              then
                  Anel_IO1 = Anel_IO1 + 1
                  if (Anel_IO1 == 1)
                  {
                      timer_anel = createTimer(now.plusMillis(1000)) [|
                      {
                          logInfo( "Taster", "Ergebnis: " + Anel_IO1)
              
                          if      (Anel_IO1 == 1)  sendCommand(switch_licht, ON)
                          else if (Anel_IO1 == 2)  sendCommand(switch_licht_sz, ON)
                          else if (Anel_IO1 == 3)  sendCommand(Licht_Ambiente1, ON)
                          Anel_IO1 = 0
                      } ]
                  }
                  if (Anel_IO1 >3) Anel_IO1 = 0
                  logInfo( "Taster", "Anel_IO1: " + Anel_IO1)
              end
              Holger

              Kommentar


                #8
                Sicher, dass der Code funktioniert? Ich hab mir jetzt mal die Mühe gemacht, es im Designer so hinzuschreiben, wie ich denke, dasss es ein muss:
                Code:
                import org.joda.time.DateTime
                
                var Timer timer_anel1 = null
                var Timer timer_anel2 = null
                var int switch_anel=0
                
                rule test
                when
                    Item testswitch received command OFF
                then
                    if (timer_anel2!=null){
                        timer_anel2.cancel
                        timer_anel2=null
                        logInfo("ANel_IO","Dreifach-Klick erkannt")
                        //hier sendCommand() Dreifachklick
                    }
                    else
                        if (timer_anel1!=null){
                            timer_anel1.cancel
                            timer_anel1=null
                            timer_anel2 = createTimer(now.plusMillis(500))[|{
                                logInfo("ANel_IO","Doppel-Klick erkannt")
                                //hier sendCommand() Doppelklick
                            }]
                        }
                        else
                            timer_anel1 = createTimer(now.plusMillis(500))[|{
                                logInfo("ANel_IO","Einfach-Klick erkannt")
                                switch_anel=switch_anel+1
                                if (switch_anel>3)
                                    switch_anel=0
                                switch (switch_anel) {
                                    case 0: {
                                        logInfo("ANel_IO","Einfach-Klick Stufe 0")
                                        //hier sendCommand() Einfachklick Stufe 0
                                    }
                                    
                                    case 1: {
                                        logInfo("ANel_IO","Einfach-Klick Stufe 1")                        
                                        //hier sendCommand() Einfachklick Stufe 1
                                    }
                                    
                                    case 2: {
                                        logInfo("ANel_IO","Einfach-Klick Stufe 2")                        
                                        //hier sendCommand() Einfachklick Stufe 2
                                    }
                                    
                                    case 3: {
                                        logInfo("ANel_IO","Einfach-Klick Stufe 3")                        
                                        //hier sendCommand() Einfachklick Stufe 3
                                    }
                                }
                            }]
                      
                end
                Erklärung: Die Rule triggert jeweils, sobals ein OFF erkannt wird (ich gehe davon aus, dass der Taster das sendet, wenn er losgelassen wird)
                Als erstes wird überprüft, ob der 2. Timer läuft. Falls das der Fall ist, ist das der 3. Klick im Zeitfenster -> Timer stoppen und Befehl ausführen.
                Falls der Timer nicht läuft, wird getestet, ob der 1. Timer läuft. Wenn dies der Fall ist, ist es der 2. Klick im Zeitfenster, -> den 1. Timer zurücksetzen und den 2. Timer starten.
                Falls auch der 1. Timer nicht läuft, so handelt es sich um den 1. Klick, also den 1. Timer starten.
                Wenn der 2. Timer abläuft, bevor ein drittes Mal geklickt wird, wird der Doppelklick-Befehl ausgeführt
                Wenn der 1. Timer abläuft, bevor ein zweites Mal geklickt wird, wird der Einfach-Klick-Befehl ausgeführt, nämlich zuerst die Variable hochgezählt, anschließend überprüft, ob sie größer 3 ist (dann wird sie auf 0 gesetzt) und zum Abschluss mit der switch-case Anweisung verzweigt.

                Man kann auch 4- oder 5-mal klicken, das entspricht dann dem Dreifach-Klick mit anschließendem Einzel- oder Doppelklick.
                Zuletzt geändert von udo1toni; 28.09.2015, 04:29. Grund: Tippfehler korrigiert

                Kommentar


                  #9
                  Also ich bekomme bei deiner Rule folgende Error-Meldung:
                  Code:
                  2015-09-27 18:00:51.125 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'test': cannot invoke method public abstract boolean org.openhab.model.script.actions.Timer.cancel() on null
                  Edit: Nachdem ich 0 durch null ersetzt habe funktioniert die Rule. Allerdings nicht richtig... ich teste erst mal.
                  Zuletzt geändert von hardoverflow; 27.09.2015, 17:21.

                  Kommentar


                    #10
                    Jepp. Tippfehler meinerseits hab's ausgebessert...

                    Kommentar

                    Lädt...
                    X