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"
}
}
*/