Can someone help me write a code for a contact sensor

Already have something i use in my garage :smile:

/**
 *  Dual Zone Smart Night Light
 *
 *  Author: tslagle13
 *
 */
definition(
    name: "Dual Zone Smart Night Light",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Turns on lights using motion and contact sensor. Both values must be closed/not active in order for lights to turn off.",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_motion-outlet-luminance.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_motion-outlet-luminance@2x.png"
)

preferences {
	section("Control these lights..."){
		input "lights", "capability.switch", multiple: true
	}
	section("Turning on when a contact opens and there's movement..."){
		input "motionSensor", "capability.motionSensor", title: "Where?"
        input "contactSensor", "capability.contactSensor", title: "Which?"
	}
	section("And then off when it's light or there's been no movement for..."){
		input "delayMinutes", "number", title: "Minutes?"
	}
}



def installed() {
	initialize()
}

def updated() {
	unsubscribe()
	unschedule()
	initialize()
}

def initialize() {
	subscribe(motionSensor, "motion", motionHandler)
    subscribe(contactSensor, "contact.open", contactHandler)
    subscribe(contactSensor, "contact.closed", contactHandler)
}
    
def motionHandler(evt) {
	log.debug "$evt.name: $evt.value"
	if (evt.value == "active") {
		
			log.debug "turning on lights due to motion"
			lights.on()
			state.lastStatus = "on"
		
		state.motionStopTime = null
	}
	else {																					// Motion has stoped
		state.motionStopTime = now()																																// The on button was NOT pushed so...
        	if(delayMinutes) {																	// If the user set a delay then...
				runIn(delayMinutes*60, turnOffMotionAfterDelay, [overwrite: false])				// Schedule the "lights off" for later.
			} else {																			// Otherwise...
				turnOffMotionAfterDelay()														// Run the lights off now.
			
       } 
	}
}

def contactHandler(evt) {
	log.debug "$evt.name: $evt.value"
	if (evt.value == "open") {
		
			log.debug "turning on lights due to motion"
			lights.on()
			state.lastStatus = "on"
		
		state.motionStopTime = null
	}
	else {																					// Motion has stoped
		state.motionStopTime = now()
																																// The on button was NOT pushed so...
        	if(delayMinutes) {																	// If the user set a delay then...
				runIn(delayMinutes*60, turnOffMotionAfterDelay, [overwrite: false])				// Schedule the "lights off" for later.
			} else {																			// Otherwise...
				turnOffMotionAfterDelay()														// Run the lights off now.
			}
        
	}
}

def turnOffMotionAfterDelay(evt) {
	log.debug "In turnOffMotionAfterDelay"
	if (state.motionStopTime && state.lastStatus != "off") {
		def elapsed = now() - state.motionStopTime
		if (elapsed >= (delayMinutes ?: 0) * 60000L) {
			lights.off()
			state.lastStatus = "off"
		}
	}
}

Basically the contact sensor and motion use the same “delay timer” the last event to happen will control the event timer. Basically the last contact closed or motion inactive call will start the turn off sequence.

1 Like

@tslagle13 That is pretty close to what he wants. It still needs to take into account that a person might be in the shower with the door closed. In that scenario the lights could go off because of no motion and the door being closed.

Well… how can a smart app “sense” someone in the shower without a sensor to do the sensing in that area?

damn. Tslagle just owned you both, eagle and jody. :stuck_out_tongue_winking_eye: I think he wins the badge.

@tslagle13 humidity sensor above the shower?

Haha. This was not at all my intention… but i’ll take the badge non the less :wink:

I have pseudo-code on my whiteboard. I will try and build it tomorrow. I think you need to take into account the proximity of door opens and closures. If someone leaves out of the bathroom and does not close the door, the light should go off after a certain period of time. There are also other scenarios where this could end up with someone in the dark.

I believe the idea is to do it with the closed door senario:

1 Like

I open and close my garage door within a matter of seconds many times a day. Lights come on and turn off as expected.

The motion.inactive event will turn the lights off after the specified amount of time

The smart app above was written with the exact same scenario in mind. Just in a garage not a bathroom lol

Unless they are motionless in the tub/shower for 35 minutes. That is a real world example that happens at my house.

1 Like

@borya should give the @tslagle13 code a go and see how it works.

This is true. I’m wondering how you would account in a smart app for a “fake” non-motion event though.

(i’m not trying to prove my code or anything, i know it works in my home… nor am i trying disprove yours… i have a genuine interest in how you would account for this.) :smile:

My code would definitely work for the general someone is taking a pee or doing their hair scenario though… lol

If someone is motionless for large periods of time in the bathroom i can’t help you lol :stuck_out_tongue:

I am just doing this as a challenge. I gave up on trying to figure it out once before, but this post has sparked my interest in it. I think I have a solution that might work, but I won’t know until I get some actual code.

I think that the only way to stop a “fake” non-motion would be to make it dependent on the door sensor being at the very least open a 2nd time in a specific time space.

Let’s say a person went into the bathroom closed the door and is taking a bath, if the motion sensor doesn’t see motion but the door was never open again after being closed then it should not make an action

This would work in most cases… But then someone opens the door to grab a toothbrush and it would throw the whole sequence off.

1 Like

Hence, the challenge aspect of this. The bathroom is probably the hardest room in the house.

Agreed :smile:

Here’s my philosophy when i write an app. I try not to assume for any variable. If i don’t have emperical data about a situation i tend to not write it into an app. This is what I would do.

  1. You could custom make a trip sensor for the bath that would override all the different inputs for the smart app. SO when someone enters the shower the light stays on permanently.

2.You could use a moisture sensor in the bathtub that would also do the same thing when water is detected. Same thing here. It would over ride the other sensor inputs until no water is detected.

Agreed, but that’s why I have an absolute restart sequence timer for however long I think would be the minimum.

Most importantly as long as my wife doesn’t have the lights turn off on her which I think they won’t, if the lights stay on because something out of normal occurred than no problem.

P.S. who takes baths anymore? lol!

This bathroom occupancy thing was one thing I wanted to use ST for in the beginning but it’s too complicated for our household. In the end, this simple motion switch did it for us and it still works when the internet goes bonkers. I just have to make sure to move the shower door a bit to reset the motion counter.

http://amzn.com/B005WM3ALC

The problem isn’t the bath lol. It’s that fact that the motion sensor doesn’t sense a person behind the shower door.

1 Like