Double tap, measure time between them


(Stephanschulz) #1

i have a feeling that the double tap need some sort of checking if the two taps where not too long apart.

it seems that the double tap action i scripted gets called when on a single tap.
i call an action on a double off tap.
this makes me believe it still has one off tap in memory from before.

could that be true?

thanks.


(Stephanschulz) #2

i think my problem comes from trying to monitor 2 switches for double taps.
i commented out the 2nd switch code and it is now more reliable.

preferences {
	section("When these switchs are double-tapped...") {
		input "switch1", "capability.switch", title: "Where?" //, multiple: true
		//input "switch2", "capability.switch", title: "Where?"
    }

    section("make this Siren react. top for on + bottom for off") {
		input "alarms", "capability.alarm", title: "Which Alarm(s)", multiple: true, required: false
    	input "silent", "enum", title: "Silent alarm only (Yes/No)", metadata:[values:["Yes","No"]]
       	input "lights", "capability.switch", title: "Flash these lights (optional)", multiple: true, required: false
    }

    section( "Notifications" ) {
		input "sendPushMessage", "enum", title: "Send a push notification?", metadata:[values:["Yes","No"]], required:false
		input "phone", "phone", title: "Send a Text Message?", required: false
	}
    
   section("Change to this mode") {
		input "newMode", "mode", title: "Mode?", required: false
	}
}

def installed()
{
	subscribe(switch1, "switch", switchHandler1, [filterEvents: false])
   // subscribe(switch2, "switch", switchHandler2, [filterEvents: false])
    state.alarmActive = null
}

def updated()
{
	unsubscribe()
	subscribe(switch1, "switch", switchHandler1, [filterEvents: false])
    //subscribe(switch2, "switch", switchHandler2, [filterEvents: false])
    state.alarmActive = null
}

private lastTwoStatesWere(value, states, evt) {
	def result = false
	if (states) {

		log.trace "unfiltered: [${states.collect{it.dateCreated + ':' + it.value}.join(', ')}]"
		def onOff = states.findAll { it.isPhysical() || !it.type }
		log.trace "filtered:   [${onOff.collect{it.dateCreated + ':' + it.value}.join(', ')}]"

		// This test was needed before the change to use Event rather than DeviceState. It should never pass now.
		if (onOff[0].date.before(evt.date)) {
			log.warn "Last state does not reflect current event, evt.date: ${evt.dateCreated}, state.date: ${onOff[0].dateCreated}"
			result = evt.value == value && onOff[0].value == value
		}
		else {
			result = onOff.size() > 1 && onOff[0].value == value && onOff[1].value == value
		}
	}
	result
}

private send(msg) {
	if ( sendPushMessage != "No" ) {
		log.debug( "sending push message" )
		sendPush( msg )
	}

	if ( phone ) {
		log.debug( "sending text message" )
		sendSms( phone, msg )
	}

	log.debug msg
}

def continueFlashing()
{
	unschedule()
	if (state.alarmActive) {
		flashLights(10)
		schedule(util.cronExpression(now() + 10000), "continueFlashing")
	}
}

private flashLights(numFlashes) {
	def onFor = 1000
	def offFor = 1000

	log.debug "FLASHING $numFlashes times"
	def delay = 1L
	numFlashes.times {
		log.trace "Switch on after  $delay msec"
		lights?.on(delay: delay)
		delay += onFor
		log.trace "Switch off after $delay msec"
		lights?.off(delay: delay)
		delay += offFor
	}
}

def switchHandler1(evt) {
	log.info evt.value

	// use Event rather than DeviceState because we may be changing DeviceState to only store changed values
	def recentStates = switch1.eventsSince(new Date(now() - 4000), [all:true, max: 10]).findAll{it.name == "switch"}
	log.debug "${recentStates?.size()} STATES FOUND, LAST AT ${recentStates ? recentStates[0].dateCreated : ''}"

	if (evt.isPhysical()) {
		if (evt.value == "on" && lastTwoStatesWere("on", recentStates, evt)) {
            def message = "double tap top = siren ON, changing mode to '${newMode}'"
			log.info message
            send(message)
            
            state.alarmActive = true
            if ( silent == "Yes" ) {
            	log.debug "Silent alarm only"
             	//alarms.on();
             	alarms?.strobe()
             }else{
             	alarms?.both()
             }
            
            if (lights) {
				log.debug "continue flashing lights"
				continueFlashing()
			}
			
            
                
		} else if (evt.value == "off" && lastTwoStatesWere("off", recentStates, evt)) {
            def message = "double tap bottom = siren OFF, changing mode to '${newMode}'"
			log.info message
            state.alarmActive = false
            alarms.off();
			send(message)
		}
        setLocationMode(newMode)
	}
	else {
		log.trace "Skipping digital on/off event"
	}
}

/*
def switchHandler2(evt) {
	log.info evt.value

	// use Event rather than DeviceState because we may be changing DeviceState to only store changed values
	def recentStates = switch2.eventsSince(new Date(now() - 4000), [all:true, max: 10]).findAll{it.name == "switch"}
	log.debug "${recentStates?.size()} STATES FOUND, LAST AT ${recentStates ? recentStates[0].dateCreated : ''}"

	if (evt.isPhysical()) {
		if (evt.value == "on" && lastTwoStatesWere("on", recentStates, evt)) {
            def message = "double tap top = siren ON, changing mode to '${newMode}'"
			log.info message
            
            if ( silent == "Yes" ) {
            	log.debug "Silent alarm only"
             	//alarms.on();
             	alarms?.strobe()
             }else{
             	alarms?.both()
             }
            
            if (lights) {
				log.debug "continue flashing lights"
				flashLights()
			}
			
            send(message)
                
		} else if (evt.value == "off" && lastTwoStatesWere("off", recentStates, evt)) {
            def message = "double tap bottom = siren OFF, changing mode to '${newMode}'"
			log.info message
            
            alarms.off();
			send(message)
		}
        setLocationMode(newMode)
	}
	else {
		log.trace "Skipping digital on/off event"
	}
}
*/