Turning a light on, then back off again


(Paul) #1

Hello,
I’m still fumbling my way through groovy… so sorry if this is obvious. I’m trying to write a smart app that will turn a switch on when a contact sensor is closed, then wait 25 seconds, and then turn the switch back off. I want it to always turn the switch back off, regardless if the contact sensor remains closed, or if it is opened.

here is the code I’m using:

preferences {
section ("When the door closes...") {
	input "contact1", "capability.contactSensor", title: "Where?"
}
section ("Turn on a switch...") {
	input "switch1", "capability.switch"
}
section("Then, turn it off how many seconds later?") {
	input "secondsLater", "number", title: "When?"
}

}


def installed()
{
	subscribe(contact1, "contact.closed", contactClosedHandler)
}

def updated()
{
	unsubscribe()
	subscribe(contact1, "contact.closed", contactClosedHandler)
}

def contactClosedHandler(evt) {
	switch1.on()	//When the contact is closed, turn on the switch
  	runIn(secondsLater, turnOffSwitch)		//Wait some number of seconds, then turn off the switch
}

def turnOffSwitch() {
	switch1.off()
}

That should work, right? I must be missing something here!

Thanks…


(Convinced ST will never be unbroken…) #2

RunIn doesn’t work with schedules less than a minute. Try runOnce.


(Paul) #3

Thanks, Scott… that’s what I was missing. I actually ended up using switch.off(delay: 25000) because I was having trouble with the date/time math for runOnce.


(Eric) #4

@NorCalLights, can you post your last working example? There’s a couple Things I’d like to pulse in my setup.


#5

I am looking to do something similar.
I want a light to turn on a few seconds after the door is knocked on to make the home look occupied then the light would turn off after a specified amount of time.

Is there an app already made for this?


(Paul) #6

@ero4444 @Kooltaco my code is at the bottom here.

@ero4444 the thing to remember with switch.on(delay: milliseconds) is that the function executes immediately, but the action delays. So if you want to pulse, I think you’d have write something like:

switch.on( )
switch.off(delay: 1000)
switch.on(delay: 2000)
switch.off(delay: 3000)

But I haven’t tried that live…

@Kooltaco you can modify this code to register on a knock, but I don’t know of any existing smart apps that do what you’re asking. It’s basically impossible to search published smart apps, so I could be wrong.

/**
 *  Contact Closed, Switch On, then switch off
 *
 *  Copyright 2014 Paul Toben with help from Smartthings example code
 *
 *  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: "Contact Closed, Switch On",
    namespace: "",
    author: "Paul Toben",
    description: "Turns a switch on when a contact sensor is closed, then turns it back off again.",
    category: "Green Living",
    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 the door closes...") {
		input "contact1", "capability.contactSensor", title: "Where?"
	}
	section ("Turn on a switch...") {
		input "switch1", "capability.switch"
	}
	section("Turn it off how many seconds later?") {
		input "secondsLater", "number", title: "When?"
	}

}


def installed() {
	subscribe(contact1, "contact.closed", contactClosedHandler)
}

def updated() {
	unsubscribe()
	subscribe(contact1, "contact.closed", contactClosedHandler)
}

def contactClosedHandler(evt) {
	switch1.on()
    log.debug "Switch is on"
	def delay = secondsLater * 1000
    log.debug "Delay is ${delay} ms"
	switch1.off(delay: delay)
    log.debug "Switch is off"
}

(Paul) #7

@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()
}

#8

@NorCalLights
Thanks for this!!!
I will apply this app right away👍