Switch Event Handler: Discerning One Press or Two

(Convinced ST will never be unbroken…) #1

I am trying to create a SmartApp that is essentially a combination of ‘The Big Switch’ and ‘Double Tap’. The behavior I am looking for is:

On single press do X
On double press do Y; but NOT X

Obviously the first press always falls through initially, so a double press does X and Y. I have tried putting a ‘pause’ in the event handler to wait for the second press (if present), but that seems to block any additional events.

How can I look for a double press first? and if not present, then execute X.

(Geko) #2

Have you tried this: schedule X using runIn() after first press, then if second press, unschedule X and execute Y?

(Convinced ST will never be unbroken…) #3

That’s a thought. I wonder what the average latency on schedule and unschedule is. Guess I’ll find out. (c;

(Convinced ST will never be unbroken…) #4

@geko Well it works… sort of.

It seems ‘runIn’ won’t actually set a schedule unless it is set for 60 seconds or more. Really don’t want to have to wait a whole minute for X to be executed via a single press.

Any other thoughts?

(Patrick Stuart [@pstuart]) #5

So, what you want is a delay after first press to wait xx seconds before firing first press command but if 2nd press occurs within xx seconds then first only double press?

What I would do is something like this:

On first press, log the datetime of first press
start a timer for xx seconds

On second press, check if datetime of this press is within xx time of first press datetime
if yes, fire double press event, set var for double press = true

On end of timer, check for double press == true
if not, then fire single press event.

Or, just get last two events from button press, compare times and do one or the other based on time difference :smile:

(Convinced ST will never be unbroken…) #6

Well… that’s what I am struggling with; how to set a timer, that when it times out I send the single press event.

(Patrick Stuart [@pstuart]) #7

Will runOnce() do it? Just set the timeToday() + 30 seconds…

(Chrisb) #8

Looking at the canned DoubleTap app, it looks like when it sees an “on” tap, it looks in the log for the device to see if there’s been recent activity and if there’s two “on” taps within the recently time allowed then it acts on the double tap instructions.

It might be possible to do the same thing but look for NO additional press within the time allotted.

(Convinced ST will never be unbroken…) #9

That throws an error. But this seems to be working reliably:

import groovy.time.TimeCategory
def switchHandler(evt) {
    log.debug "in event handler"
    if (state.gotON) {
    } else {
    	state.gotON = true
        def timer = new Date()
		use(TimeCategory) {
    	timer = timer + 3.second
    	runOnce(timer, "fireSingle")

def fireSingle() {
    log.debug "firing single"
    state.gotON = null

def fireDouble() {
    log.debug "firing double"
    state.gotON = null

UPDATE: Yup… working like a charm. See this post for more info and the final app.

(Tony Gutierrez) #10

I get an error whenever I try to use any interation of unschedule(). It seems like this is a job for the java.util.timer, but for some reason creating an instance of that is not allowed.

(Convinced ST will never be unbroken…) #11

This worked… albeit I haven’t used it in quite some time. Seems SmartThings broke a lot of things in the recent platform update. What you’re seeing may be due to one of them.

(Tony Gutierrez) #12

Thanks…any idea how you pass a parameter on to the function you are running in runonce? like runOnce(timer, doThis(val))


(Convinced ST will never be unbroken…) #14

Dunno. There is no example of that in the docs. Have you tried ‘doThis(value)’?

If it doesn’t work you’ll need to use a variable or state prior to calling it to change what happens in ‘doThis’

(Tony Gutierrez) #15

My problem was trying to use those functions in a device type. Device types are even more limited than apps, and there do not seem to be any delay or timer functions whatsoever.