Turn a light on when motion is detected, and then leave it on?

Hello all-

Sorry for another question that might already be answered elsewhere. I’m using the new app and have been getting confused reading posts that are likely for the old app.

I made an automation: if motion is detected on my doorbell camera, turn on my foyer light, and shut it off after 1 minute. That’s all fine, but I don’t want it to shut the light off if it was already on. Can someone point me in a direction that might help? Should I be figuring out “modes” (home, away, etc.)?

Korey

check out Smart Lighting in Automations, if you select More Options at the bottom of the rule after you set it up, you can choose only if switch is on or off

1 Like

Ah, I see. I think I set mine up as a “custom automation”, which seems to have far fewer options. Thanks. I’ll try it out.

I tried the Smart Lights automation, and it’s not working as expected. I set the automation to turn back off after 2 minutes, and under more options, I set up “Only if switch VSLivingRm2 is off.” VSLivingRm2 is the switch that I’m turning on and off. So, I turned that switch off and triggered my motion sensor.

When I do that, the lights come on but don’t turn back off. When I set it to “only if switch is on”, then the light doesn’t trigger at all. When I remove this condition, then the lights come on and turn back off, as expected, but I’m no better off.

Am I misunderstanding how this is supposed to work?

1 Like

I’m having the exact same issue with my porch light/motion sensor in Smart Lights. I want it to only turn off if it wasn’t on to begin with.
It turns on just fine, but won’t turn back off when set up in Smart Lights 5 minutes after motion sensor is finished detecting motion.

In the new app I can make it turn off after a certain time, but you can’t change the status of a device that you use for a condition (I cannot understand why you can’t), so no way to make the automation work only if the light is off.

What model Doorbell do you have? I know that the Ring doorbells tend to register light changes as motion so you get stuck in a loop. You can use webcore and create a rule that works around that. But webcore requires the Classic app to initially set up. You can find more about webcore and do a search on what others have done to get around the light setting off motion at https://community.webcore.co

/**

  • LightsFollowMeConditionally

Yes, I have a Ring. I don’t think I’ve got a loop issue, because the light doesn’t affect much.

Thanks for the webcore advice. The reading I’ve done confuses me because of the new vs. classic app. But I’d like to start learning it. Thanks for the starting point

I’m afraid I can’t figure out what you’re trying to tell me here.

Hi Korey99.
Load up the code and run it in the IDE. Not sure if it helps your situation, but maybe you can learn something helpful to you from it.

My code turns on lights for the following situation:

Turns on my defined lights at some time (in minutes before) sunset. Turns them off at a specific time. During this time interval, motion and arrival by geolocation (Like, when I arrive within the geofence) are ignored. The lights are “sticky” on. Meaning, that even if I turn them off by switch, they will turn on again within a minute.

Outside of that time interval, the lights will come on by motion or by my arrival within the geofence if the light sensor is below a certain level (say 35 Lux). In this case, if the light comes on via motion or arrival, they will turn off in N minutes.

Though the code is crude and could stand some cleanup & simplification, it definitely works.

Oh, OK. Thanks! I’d be happy to try it, but I don’t think your code pasted in properly.

Well, that’s important. :slight_smile: Trying again.

/**

  • LightsFollowMeConditionally
  • Copyright 2015 michael lupo
  • 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: “LightsFollowMeConditionally”,
namespace: “mikelupo”,
author: “michael lupo”,
description: “Detected motion turns on switch devices (for a duration, in seconds) when the detected light falls below a given level.”,
category: “Safety & Security”,
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 motion is detected on …”) {
input “motionSensor”,“capability.motionSensor”, title: “Select a motion sensor”, multiple: true
}
section ("…and sample the light value from (Sensor)") {
input “lightSensor”, “capability.illuminanceMeasurement”, title: “Select an illuminance sensor”
input “lightValue”, “number”, title: “Lux Value is darker than”, required: true
}
section ("…and turn on if one of these peeps becomes present") {
input “presenceSensor”, “capability.presenceSensor”, title: “people”, required: false, multiple:true
}
section(“Turn on the following…”) {
input “lights”, “capability.switch”, title: “Turn on?”, required: false, multiple: true
input “offset”, “number”, title: “Turn on this many minutes before sunset”
}
section(“When turned on by motion, turn it off after…”){
input “seconds”, “number”, title: “Seconds”, required: true
}
section(“Turn off lights at…”) {
input “timeToRun”, “time”
}
}

//this code is becoming a bit rotton. It might be time to remove it.
def myIlluminanceHandler(evt) {
def currentIlluminance = “{evt.integerValue}" def lastKnownIlluminance = state.lastKnownIlluminance log.debug "The current illumanance sent by the event is: {evt.integerValue}”
log.debug “The last known illuminance was: {lastKnownIlluminance}" log.debug "Your selected LUX value is: {lightValue}”

    //now update the persisted stored value (state) to hold the new value.
    state.lastKnownIlluminance = evt.integerValue
    def lastStatus = state.lastStatus

}

//Turn on the lights by motion. Ignore the event if the lights are in the “sticky” on routine.
//otherwise, we turn the lights on if the illuminance is low enough. (i.e. before sunset but it’s dark enough, or after midnight)
//Be advised: that the sensor samples one per hour. So we could possibly miss the first events of the hour. Hopefully though,
//the sticky routine will workaround this for us as the lights should be on at sunset.
def myMotionHandler(evt) {
if (state.isTurnedOnBySunset == true) {
log.debug (“myMotionHandler: Lights are operated by Cron right now. Ignoring motion events”)
return
}

	def motionValue = "${evt.value}"
	log.debug "The motion sent by the event is: ${motionValue}"

    def lastKnownIlluminanceValue = state.lastKnownIlluminance
    log.debug "Last known illuminance is: ${lastKnownIlluminanceValue}"

    def lastStatus = "${state.lastStatus}"
    log.debug "Last status: ${lastStatus}"

    if ( "${motionValue}" == "active" && lastKnownIlluminanceValue.intValue() < lightValue  && lastStatus != "on") {
    		log.debug("Turning the light on")
            lights.on()
            state.lastStatus = "on"
            log.debug "Updating last status from ${lastStatus} to ${state.lastStatus}"
            state.isTurnedOnByMotion = true

            //turn off the light after motion is stopped and the given delay is expired if the light was turned on by motion.
    } else if ("${motionValue}" == "inactive" && lastStatus == "on" && state.isTurnedOnByMotion == true) {
            //This sets a timer to call the "scheduledTurnOff" method when the light comes on as a result of motion.
            //def delay = seconds * 60   //use this if we decide to use minutes instead of seconds.
            def delay = seconds
            log.debug "Will turn off the light in ${delay} seconds"
            runIn(delay, "scheduledTurnOff")
    } else if ("${motionValue}" == "active" && lastStatus == "on" && state.isTurnedOnByMotion == true) {
    		def delay = seconds
    } else if ("${motionValue}" == "active" && lastStatus == "on" && state.isTurnedOnByMotion == false) {
    		log.debug "The light was turned on manually, we will not turn it off by timer."
    }

}

//TODO: create a status.motionDetected map to know whether the light was turned on as a result of motion, or as a result of a manual toggle.
def mySwitchHandler(evt) {
log.debug("-----------------------------------------------------------")
for (myLight in lights) {
log.debug “mySwitchHandler: The light: {myLight} has been turned {myLight.latestValue(“switch”)}”
}
log.debug("-----------------------------------------------------------")

//this handles the case where we may have turned the light off manually or via the timer.
if ("${evt.value}" == "off"){
	state.isTurnedOnByMotion = false
}
state.lastStatus = "${evt.value}"

}

def myPresenceHandler(evt) {
//if the lights are on because of the sunset -> 23:59, then let’s ignore the event…because the lights are already on.
if (state.isTurnedOnBySunset == true) {
log.debug (“myPresenceHandler: Lights are operated by Cron right now. Ignoring presence events”)
return
}

    def lastKnownIlluminanceValue = state.lastKnownIlluminance
    log.debug "Last known illuminance is: ${lastKnownIlluminanceValue}"

    def lastStatus = "${state.lastStatus}"
    log.debug "Last status: ${lastStatus}"

if ("${evt.value}" == "present") {
	log.debug("Someone came home")
    if ( lastKnownIlluminanceValue.intValue() < lightValue  && lastStatus != "on") {
    		log.debug("Turning the light on because someone came home")
            lights.on()
            state.lastStatus = "on"
            log.debug "Updating last status from ${lastStatus} to ${state.lastStatus}"
            state.isTurnedOnByPresence = true
            def delay = seconds
            log.debug "Will turn off the light in ${delay} seconds"
            runIn(delay, "scheduledTurnOff")

            //turn off the light after motion is stopped and the given delay is expired if the light was turned on by motion.
    } else if (lastStatus == "on" && state.isTurnedOnByPresence == true) {
            //This sets a timer to call the "scheduledTurnOff" method when the light comes on as a result of motion.
            //def delay = seconds * 60   //use this if we decide to use minutes instead of seconds.
            def delay = seconds
            log.debug "Will turn off the light in ${delay} seconds"
            runIn(delay, "scheduledTurnOff")
    } else if (lastStatus == "on" && state.isTurnedOnByPresence == true) {
    		def delay = seconds
    } else if (lastStatus == "on" && state.isTurnedOnByPresence == false) {
    		log.debug "The light was already turned on and therefore we will not turn it off by timer."
    }
} else { 
    log.debug("Someone left. Buh bye!")
}

}

def installed() {
//state is a persistently stored map.
state.lastKnownIlluminance = 0;
log.debug “Installed with settings: ${settings}”
subscribe(lightSensor, “illuminance”, myIlluminanceHandler)
subscribe(motionSensor, “motion”, myMotionHandler)
subscribe(lights, “switch.on”, mySwitchHandler)
subscribe(lights, “switch.off”, mySwitchHandler)
subscribe(presenceSensor, “presence”, myPresenceHandler)

    //By adding the sunset/sunrise handlers, we have new handlers that can help us set states.
    //subscribe(location, "sunset", sunsetHandler)
	//subscribe(location, "sunrise", sunriseHandler)
    
    //this is only here to test since I only get one sunset per day. Maybe I can use this with an offset?
    def sunset = getSunriseAndSunset(zipCode: "02769").sunset
    //calculate the offset
	def timeBeforeSunset = new Date(sunset.time - (offset * 60 * 1000))

	log.debug "Scheduling for: $timeBeforeSunset (sunset is $sunset)"

	//schedule this to run daily at a specific time.
	schedule(timeBeforeSunset, turnOnLightsByCronHandler)
    
    //this is the handler that should turn off the lights when we hit the specified hard-coded time.
    schedule(timeToRun, turnOffLightsByCronHandler)
    
    //this is intended to turn the lights back on if we're in the between Sunset and 23:59 routine.
    runEvery1Minute(stickyLightsOnHandler)

    //initializing this state.
    state.isTurnedOnByMotion = false
    state.isTurnedOnBySunset = false

}

def updated() {
log.debug “Updated with settings: ${settings}”

unsubscribe()
installed()

}

//if the lights are supposed to be turned on, and someone accidentally turned them off, we turn them back on.
def stickyLightsOnHandler() {
def sunset = getSunriseAndSunset(zipCode: “02769”).sunset
log.debug “Today’s sunset will be at: ${sunset}”
if (state.isTurnedOnBySunset == true) {

	//there is something wrong here. I am getting NPE in the if statement. TODO: figure out how to detect the current light value.

// for (myLight in lights) {
// if ({myLight.latestValue("switch")} == "off") { // myLight.on() // log.debug "stickyLightsOnHandler: The light: {myLight} has been turned ${myLight.latestValue(“switch”)} because it was off and they should be on because of CRON!"
// }
// }
//just shotgun approach. I liked the for loop approach better, but I can’t figure out what is wrong.
lights.on()
}
}

def turnOffLightsByCronHandler() {
state.isTurnedOnBySunset = false
lights.off()
}

def turnOnLightsByCronHandler() {
state.isTurnedOnBySunset = true
lights.on()
}

//def sunsetHandler(evt) {
// log.debug “Sun has set!”
// state.isTurnedOnBySunset = true
// lights.on()
//}

//def sunriseHandler(evt) {
//    log.debug "Sun has risen!"
//    lights.off()
//}

def scheduledTurnOff() {
	lights.off()
}

It seems to not respect the preformatted text in this forum. I apologize. I could paste it into a text file, zip it up and then send it via an email if you really need.
And sorry for my delay to answer your original reply back.

I think it’s pasted in OK now. The last part I see is the function definition for scheduledTurnOff().

I am using the new app, and I haven’t done any code in the IDE yet. I’ll look into how to get started with that, then give it a shot. Thanks!

i’ve found this issue too…
anyone else got a simple solution to this issue?
@asb924