Double Tap on a switch to control another one (with groovy)


its a little groovy script to switch another switch on/off when DoubleTap.
Coding with fonction again! Much better :wink:

your switch need to send its status quickly. Some switch send their status after 20-25 minutes, this will not work with this script.


import org.openhab.core.jsr223.internal.shared.*
import org.openhab.core.items.ItemRegistry
import org.joda.time.DateTime
import org.openhab.core.library.types.*
import java.util.timer.*

//double tap on a switch will control another switch
class DoubleTapImpl implements Rule {
    //delay to ignore commands when the script is sending a command
    //and delay between tap in milliseconds
    static tapDelay = 500  
    //var that take your configuration, see init in DoubleTapImpl()
    static switchToControl = []
    static ItemRegistry itemRegistry
    static Class pe
    def logger = Openhab.getLogger('DoubleTap')
    DoubleTapImpl() {'DoubleTap init') 
        //You need to add your light to control here!
        //onVsOff:  'on' = only turn ON the other switch, 'off' = only turn OFF, 'all' = turn ON and OFF
        //invertControl: true = double tap on switchB will control switchA also.
        //do not change lastTap, timer and sending
        //do not make multiple entry with the same light
        switchToControl << [switchA:'Light_A',\
                            switchB:'Light_B', \
                            onVsOff:'all', \
                            invertControl:true, \
                            lastTap:new DateTime().minusMinutes(2), \
                            timer:null, \
                            sending:false ]
        switchToControl << [switchA:'Light_Bed1', \
                            switchB:'Light_Bed2', \
                            onVsOff:'all', \
                            invertControl:false, \
                            lastTap:new DateTime().minusMinutes(2), \
                            timer:null, \
                            sending:false ]

    java.util.List<EventTrigger> getEventTrigger() {
        def myTrigger = []
        switchToControl.each {
            myTrigger << new UpdatedEventTrigger(it.switchA)
            myTrigger << new UpdatedEventTrigger(it.switchB)
        return myTrigger

    void execute(Event event) {
        def switchIndex = returnIndex(event.getItem().getName())
        if(switchIndex!=null) {
            if(switchToControl[switchIndex].sending == false) {
    def returnIndex(String theSwitch) {
        def returnIndex = null
        switchToControl.eachWithIndex { item, index ->
            if(item.switchA == theSwitch || (item.invertControl == true && item.switchB == theSwitch)) {
                returnIndex = index
        return returnIndex
    void checkDelay(def switchIndex, Event event) {
        if(switchToControl[switchIndex].lastTap.plusMillis(tapDelay).afterNow) {
            if(switchNeedCommand(switchIndex,event)) {
            switchToControl[switchIndex].lastTap = new DateTime()
    boolean switchNeedCommand(def switchIndex, Event event) {
        return switchToControl[switchIndex].onVsOff=='all' || \
    void sendToSwitch(def switchIndex, Event event) {
        switchToControl[switchIndex].sending = true
        Openhab.sendCommand(getSwitch(switchIndex, event), event.getNewState())
    def getSwitch(int index, Event event) {
        if(switchToControl[index].switchA == event.getItem().getName()) {
            return itemRegistry.getItem(switchToControl[index].switchB)
        }else {
            return itemRegistry.getItem(switchToControl[index].switchA)
    String convertState(OnOffType status) {
        return (status == OnOffType.ON) ? 'on' : 'off'
    void removeSending(int index) {
        switchToControl[index].timer = Openhab.createTimer(new DateTime().plusMillis(tapDelay),{
                switchToControl[index].sending = false
            } as TimerTask )

RuleSet getRules() {
    return new RuleSet(new DoubleTapImpl())
DoubleTapImpl.itemRegistry = this.ItemRegistry = this.PersistenceExtensions 

1 Like

How does one implement this, and will it work with Zwave devices?

I’ve been trying to write a rule to handle double tap, but it’s not working as I can’t use the rules “changed” event, as on the subsequent event nothing has changed so the rule doesn’t fire. I have noticed in the wave logs that openhab is in fact receiving the subsequent event.


it work with any switch. any binding that update switch state rapidly.

you need to install the jsr223 engine and install the groovy script engine. check this wiki page for how to do it.

when it work it will tell you that you have groovy available in the engine.

after that. create a file doubletap.groovy and copy my code in it. put that file in configurations/scripts

you need to modify the variable switchToControl with your own switch. you can put as many as you like. (there is 2 in the example)

ps: this is not compatible with oh2.
they are working to get something like jsr223. but it’s not done yet.

Hi Joel!

I know that this is a little bit offtopic, but as you seem to know to install, configure and develop in jsr223, I need to ask you a question: what method did you follow to install openHAB? apt-get or manual unziping?

I would really appreciate if you could take some minutes and help me with my installation problem described here: Installing jython for JSR233 - update on wiki (My last post)

Many thanks for your help and best regards,


I know, it was a curse to install.

If you follow the wiki:
you need to modify your .sh in openhab/ if you are running with linux, and openhab/start.bat for windows. (both sh and bat are shown in the wiki)

i am running on windows, so no simlink. I just copy every groovy*.jar in the openhab/lib directory. That should be the same with your script engine. And no app-get, i unzipped the engine in my addons directory.

Good luck!

Hi Joel!

Many thanks for your answer and help. My problem is that I don’t know which file I need to edit because the apt-get installation method doesn’t provide an openhab/ file :pensive: I will edit every possible file and report back with the final working configuration.

Best regards,