@Kooltaco
So I was looking for a project to teach myself more about scheduling events… I ended up writing the Knock Knock app you were looking for. It will turn up to 3 lights on in your house (with 5s delays between each) if acceleration is detected and a door contact does not open after 10 seconds. Then it waits for a bit, and turns them off again.
Here’s the code. Note that the variables for timing are currently hardwired in… the preferences don’t work yet. If I have time, I’ll clean that up later.
/**
* Knock Knock, Lights On
*
* Copyright 2014 Paul Toben
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Knock Knock, Lights On",
namespace: "",
author: "Paul Toben",
description: "Turn the lights on when a knock is detected, then turn them back off again.",
category: "",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
preferences {
section("When a knock is detected..."){
input "accelerationSensor", "capability.accelerationSensor", title: "Where?"
}
section("Turn these lights on in order...") {
input "switch1", "capability.switch", title: "First Switch"
input "switch2", "capability.switch", title: "Second Switch"
input "switch3", "capability.switch", title: "Third Switch"
}
section("Unless...") {
input "contact1", "capability.contactSensor", title: "This contact opens..."
input "deltaSeconds", "decimal", title "... in This Many Seconds." //not yet implemented
}
section("And then restore the light's states after...") {
input "restoreOff", "number", title "Minutes" //not yet implemented
}
}
def installed() {
log.debug "Installed"
subscribe(accelerationSensor, "acceleration.active", accelerationActiveHandler)
}
def updated() {
log.debug "Updated..."
unsubscribe()
subscribe(accelerationSensor, "acceleration.active", accelerationActiveHandler)
}
def accelerationActiveHandler(evt) {
log.debug "accel detected"
def deltaSecondsH = 10
def timeAgo = new Date(now() - (1000 * deltaSecondsH))
def recentEvents = accelerationSensor.eventsSince(timeAgo) //look back for other accel events
log.trace "Found ${recentEvents?.size() ?: 0} accel events in the last $deltaSeconds seconds"
def alreadyCheck = recentEvents.count { it.value && it.value == "active" } > 1
if (alreadyCheck) {
log.debug "A knock was detected, but I've already scheduled doorOpenCheck()"
} else {
log.debug "A knock was detected. Scheduling doorOpenCheck for $deltaSeconds in the future"
def doorOpenCheckDelay = new Date(now() + (1000 * deltaSecondsH)) //Calculate schedule for doorOpenCheck()
runOnce(doorOpenCheckDelay, doorOpenCheck)
}
}
def doorOpenCheck() {
log.debug "Now in doorOpenCheck()"
def deltaSecondsG = 10
def doorAgo = new Date(now() - (1000 * deltaSecondsG)) //calculate how far to look back in the log
def recentEvents = contact1.eventsSince(doorAgo) //look back for any contact open events
log.trace "Found $recentEvents door open events in the last $deltaSeconds seconds"
def doorCheck = recentEvents.count { it.value && it.value == "open" } > 0
if (doorCheck) {
log.debug "$door1 opened. Doing nothing."
} else {
log.debug "$door1 did not open. Scheduling lights to turn on."
turnLightsOn()
}
}
def turnLightsOn() {
log.debug "now in turnLightsOn()"
switch1.on()
switch2.on(delay: 5000)
switch3.on(delay: 10000)
def offMinutes = 1 * 60
runIn(offMinutes, turnLightsOff)
}
def turnLightsOff() {
log.debug "now in turnLightsOff()"
switch1.off(delay: 10000)
switch2.off(delay: 5000)
switch3.off()
}