Turn on with motion unless turned off

Another small problem I had has been solved. When I turn off the light at the switch, I don’t want my motion sensor just turning it back on. I wrote this app so that it won’t turn on automatically for however many minutes after I turn it off. I currently have it set for one minute.

/**
 *  Turn on with motion unless turned off
 *
 *  Copyright 2015 Eric Roberts
 *
 *  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: "Turn on with motion unless turned off",
    namespace: "baldeagle072",
    author: "Eric Roberts",
    description: "Any motion detected will turn the lights on unless the switch has been manually switched off recently.",
    category: "Convenience",
    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("Devices") {
		input "motion", "capability.motionSensor", title: "Motion Sensor", multiple: false
        input "lights", "capability.switch", title: "Lights to turn on", multiple: true
	}
    section("Preferences") {
    	paragraph "If you turn off this light, the motion sensor will not turn on the lights for the specified minutes"
        input "switchLight", "capability.switch", title: "Switch", multiple: false
        input "minutes", "number", title: "Minutes"
    }
}

def installed() {
	log.debug "Installed with settings: ${settings}"
initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}

def initialize() {
	subscribe(motion, "motion", motionHandler)
    subscribe(switchLight, "switch", switchHandler)
    state.enabled = true
    state.runOff = true
}

def motionHandler(evt) {
	log.debug "Motion Handler - Evt value: ${evt.value}"
    if (evt.value == "active") {
    	if (state.enabled) {
        	log.debug("Turning on lights")
            lights?.on()
        } else {
        	log.debug("Motion is disabled - not turning on lights")
        }
    }
}

def switchHandler(evt) {
	log.debug "Switch Handler - Evt value: ${evt.value}, isPhysical: ${evt.isPhysical()}"
    if (evt.value == "off" && evt.isPhysical()) {
    	log.debug "Motion disabled"
    	state.enabled = false
        def runInMins = minutes * 60
        runIn(runInMins, enable)
    }
}

def enable() {
	log.debug "Motion enabled"
	state.enabled = true
}
4 Likes

I am intrigued by your app, but not quite skilled enough to follow your code. I wrote this app to assist me turning on a shower light when I open a shower door and turning off the bathroom light. I would like to do what you did and disable the motion sensor in the bathroom for a period of minutes when the shower door has been closed and switch 2 is on

the goal would be to turn on switch1 and turn off switch 2 after 10 seconds. I just don’t know how to disable the motion sensor in conjunction with this. Anyway, here is my code, maybe you can assist.

/**

preferences {
section (“When the door closes…”) {
input “contact1”, “capability.contactSensor”, title: “Where?”
}
section (“Turn on the shower light…”) {
input “switch1”, “capability.switch”, title: “Shower Light”
}
section (“And turn off the bathroom light…”){
input “switch2”, “capability.switch”, title: “Bathroom Dimmer”
}
section (“Disable the bathroom motion sensor…”){
input “motion1”, “capability.motionSensor”, title: “Which Motion Sensor”

}

}
def installed()
{
log.debug "Intalled with settings ${settings}"
subscribe(contact1, “contact”, showerEvent)
subscribe(motion1, “motion”, motionHandler)
// subscribe(switch1, “switch”, showerSwitchEvent)
// subscribe(switch2, “switch”, bathroomSwitchEvent)

}
def updated(){
log.debug "Updated with settings ${settings}"
unsubscribe()
subscribe(contact1, “contact”, showerEvent)
subscribe(motion1, “motion”, motionHandler)
// subscribe(switch1, “switch”, showerSwitchEvent)
// subscribe(switch2, “switch”, bathroomSwitchEvent)
}
def initialize() {
subscribe(motion1, “motion”, motionHandler)
state.enabled = true
state.runoff = true
}
def turnOffShower(){
log.debug "Turning off shower light"
switch1.off()

}
def startShower(){
log.debug "Turning off the bathroom light because you started your shower"
switch2.off()
}

def showerEvent(evt) {
log.trace "Currently the Shower Door is ${evt.value}"
def leaveOnOne = 1 * 60
if (evt.value == “open” || switch1.on()) {
// if (switch1.on()) {
log.trace "The bathroom and shower lights are on because you are either entering or leaving the shower, the shower light will remain on for 1 minute for your convenience."
switch1.on()
switch2.on()
runIn(leaveOnOne, turnOffShower)

} else if (evt.value == "closed") {
 def leaveOnTen = 1 * 10
 log.trace "I am turning off the bathroom light because you have entered the shower to take a shower"
    switch1.on()
    runIn(leaveOnTen, startShower)

// }

}
}

First, a suggestion - I would put all of my subscriptions in initialize() and just call initialize in installed() and updated(). This will make it so you don’t have to duplicate code.

To get it to “disable” the motion sensor, you need to first make sure it is not being controlled in another SmartApp or setting. You want the motion sensor to turn the light on and off from this app. You need to define your motionHandler() to turn the light on and off. I would then use your state.enabled as an if statement.You would then change the state.enabled in showerEvent(evt) where appropriate.

Hopefully that helps, let me know if you get stuck.

Also, instead of runIn, which can sometimes not be very accurate, you can use a delay. I haven’t used this yet as I have just recently learned about it. You then wouldn’t need the startShower or turnOffShower() functions. You would just use switch2.off([delay: leaveOnTen]) and switch2.off([delay: leaveOnOne]). I think I read that delay is not good for over 60 seconds, but what you have set up now is within that.

You are awesome! Delay worked and I was able to insert the state.enabled = true/false into my code and it works perfectly.

/**

  • Lights Off, When Closed
  • Author: SmartThings
    */
    definition(
    name: “Take A Shower”,
    namespace: “JDogg016”,
    author: “Justin Bennett”,
    description: “When you walk into the bathroom the bathroom light will come on. When you close the shower door, the bathroom light will go off after 5 seconds and the shower light will come on and the motion detection will be disabled for 30 minutes (during the shower). When you open the door, motion detection will re-enable and the light will come on.”,
    category: “Convenience”,
    iconUrl: “https://s3.amazonaws.com/smartapp-icons/Meta/light_contact-outlet.png”,
    iconX2Url: “https://s3.amazonaws.com/smartapp-icons/Meta/light_contact-outlet@2x.png
    )

preferences {
section (“When the door closes…”) {
input “contact1”, “capability.contactSensor”, title: “Where?”
}
section (“Turn on the shower light…”) {
input “switch1”, “capability.switch”, title: “Shower Light”
}
section (“And turn off the bathroom light…”){
input “switch2”, “capability.switch”, title: “Bathroom Dimmer”
}
section (“Disable the bathroom motion sensor…”){
input “motion1”, “capability.motionSensor”, title: “Which Motion Sensor”

}

}
def initialize() {
subscribe(contact1, “contact”, showerEvent)
subscribe(motion1, “motion”, motionHandler)
state.enabled = true
state.runOff = true

}
def installed()
{
log.debug "Intalled with settings ${settings}"
initialize ()
// subscribe(switch1, “switch”, showerSwitchEvent)
subscribe(switch2, “switch”, bathroomSwitchEvent)

}
def updated(){
log.debug "Updated with settings ${settings}"
unsubscribe()
subscribe(contact1, “contact”, showerEvent)
subscribe(motion1, “motion”, motionHandler)
// subscribe(switch1, “switch”, showerSwitchEvent)
subscribe(switch2, “switch”, bathroomSwitchEvent)

}
def enable() {
log.trace "Motion enabled"
state.enabled = true
}
def motionHandler(evt) {
log.trace "Motion Handler - Evt value ${evt.value}"
if (evt.value == “active”) {
if (state.enabled) {
log.trace (“I am turning on the lights because there was motion”)
switch2?.on()
} else {
log.trace (“Motion is disabled - not turning on lights”)
}
}
}

def showerEvent(evt) {
log.trace "Currently the Shower Door is ${evt.value}"
if (evt.value == “open”) {
state.enabled = true
log.trace "The bathroom and shower lights are on because you are entering or exiting the shower, the shower light will remain on for 5 seconds for your convenience and I have enabled the motion sensor"
switch2.on()
switch1?.off([delay: 5 * 1000]);

} else if (evt.value == "closed" || switch2.on()) {
   log.trace "I am turning off the bathroom light because you have entered the shower to take a shower, I am also disabling the motion sensor."
   state.enabled = false
   switch1.on()
    switch2?.off([delay: 5 * 1000]);
    runIn(30 * 60, enable)

}
}

It’s looking good. I see you took the subscriptions from installed() and put it in initialize(). You should do the same with updated(), because initialize is not being called in updated() and therefore not resetting the state variable. Also, with the code right now, you have some unnecessary subscriptions (switch1, switch2) and you are not using state.runOff. Were you planning on using those for something else?