Annnnnnd here we go (based on a schedule, zip code will follow). I haven’t had a chance to test it more than a few times but it seems to be working just fine on both the simulator and with my things. Within the app on my phone, I created two new modes for setting up the time frame.
/**
preferences {
section(“When there’s movement”) {
input “motion1”, “capability.motionSensor”, title: “Where?”, multiple: true
}
section("Turn on") {
input "switch1", "capability.switch", title: "Switch"
}
section("After this time") {
input "onTime", "time", title: "Time of Day", required: false
}
section("Change to this mode") {
input "newMode", "text", title: "Mode"
}
section("Until when") {
input"offTime", "time", title: "Time of Day", required: false
}
section("Then change to this mode") {
input"oldMode", "text", title: "mode"
}
section("And stay on for") {
input "minutes1", "number", title: "Amount"
}
}
def installed() {
subscribe(motion1, “motion.active”, motionActiveHandler)
schedule(“0 * * * * ?”, “scheduleCheck”)
initialize()
}
def updated() {
unsubscribe()
subscribe(motion1, “motion.active”, motionActiveHandler)
unschedule()
schedule(“0 * * * * ?”, “scheduleCheck”)
initialize()
}
def initialize() {
schedule(onTime, changeModeOn)
schedule(offTime, changeModeOff)
}
def changeModeOn() {
setLocationMode(newMode)
}
def changeModeOff() {
setLocationMode(oldMode)
}
def motionActiveHandler(evt) {
log.debug "$evt.name: $evt.value"
if (location.mode == newMode) {
if (evt.value == “active”) {
log.debug "turning on light"
switch1.on()
}
state.inactiveAt = now()
}
else if (evt.value == “inactive”) {
if(!state.inactiveAt) {
state.inactiveAt = now()
}
}
}
def scheduleCheck() {
log.debug "schedule check, ts = ${state.inactiveAt}"
if (state.inactiveAt) {
def elapsed = now() - state.inactiveAt
def threshold = 1000 * 60 * minutes1
if (elapsed >= threshold) {
log.debug "turning off lights"
switch1.off()
state.inactiveAt = null
}
else {
log.debug “${elapsed / 1000} sec since motion stopped”
}
}
}