SmartThings Community

Motion activated thermostat

(Chris LeBlanc) #1

Below is the code I wrote for Motion/Contact Activated Thermostat.

I have three thermostats so it’s been tested thoroughly and I will say it sends commands flawlessly but there is one MAJOR bug in my setup (I use CT100 thermostats) which is that this SmartApp doesn’t seem to reliably update both cooling/heating setpoints on the device despite sending the commands. Usually it only updates one of them. I’ve tried many things to get it to work reliably but nothing really worked well.

This is the vanilla version which has no “hacks” to circumvent this problem. I tried things like adding a delay between setpoint commands and also using two of these SmartApps. The former “hack” increased the reliability at the cost of losing reliability due to delayed functions being unreliable in SmartThings.

As of writing this edit I’ve started using Routines (which actually have the same problem sometimes as well and don’t really work to the full extent this app did). I say this only because I wanted to be clear that this code is no longer actively maintained.

(Craig) #2

@leblaaanc

I agree this is straight forward. Before people start troubleshooting this, it appears like you are trying to re-invent the wheel. I do this exact set of functions using the hello, home dashboard built in apps. Is there a reason why that wouldn’t work?

(Chris LeBlanc) #3

What hello home turns a single thermostat on based on motion? I have three floors and I don’t want the third floor activated until someone is actually up there.

(cslee) #4

Any update on this app ?

(cslee) #5

It works for me. I’ve change to to have an option to turn off thermostat instead of setback. Here’s the code so far:
I also wanted to create a resume on motion to previous setting when motion happens within 20 mins of turning off.

/**

preferences {

section("On this thermostat... ") {
    input "thermostat", "capability.thermostat"
}
section("When movement is detected by any of these...") {
    input "motion", "capability.motionSensor", title: "Motion Sensor(s)", multiple: true,  required: false
}
section("Or when any of these are open...") {
    input "contact", "capability.contactSensor", title: "Contact Sensor", multiple: true,  required: false
}
section("Delay the no motion event...") {
    input "delayNoMotionEvent", "number", title: "Minutes", description: "60 minutes",  required: false
}
section("Set thermostat to Off when no motion timed-out") {
    input "noMotionOff", "boolean", title: "Yes?"
}
section("Enable motion after idle resume") {
    input "motionAfterIdle", "boolean", title: "Yes?"
}
section("Resume the motion event...") {
    input "resumeMotionEvent", "number", title: "Minutes", description: "20 minutes",  required: false
}
section("Set motion air conditioning setting..."){
    input "coolingSetpointMotion", "number", title: "Degrees?"
}
section("Set motion heat setting...") {
    input "heatingSetpointMotion", "number", title: "Degrees?"
}
section("Set no motion air conditioning setting..."){
    input "coolingSetpointNoMotion", "number", title: "Degrees?"
}
section("Set no motion heat setting...") {
    input "heatingSetpointNoMotion", "number", title: "Degrees?"
}

}

def installed()
{
subscribe(motion, “motion”, eventHandler)
subscribe(contact, “contact”, eventHandler)
}

def updated()
{
unsubscribe()

subscribe(motion, "motion", eventHandler)
subscribe(contact, "contact", eventHandler)

}

def eventHandler(evt)
{
log.debug “device: $device, value: $evt.value, event: $evt, settings: $settings, handlerName: ${evt.handlerName}”

// set the delay, defaulting to 60 minutes
def delay = (delayNoMotionEvent != null && delayNoMotionEvent != "") ? delayNoMotionEvent * 60 : 3600

// set the resumedelay, defaulting to 20 minutes
def resumedelay = (resumeMotionEvent != null && resumeMotionEvent != "") ? resumeMotionEvent * 20 : 3600

// unschedule delay since motion is detected and set temp to active state
if (evt.value == 'active' || evt.value == 'open') 
{
    log.debug "unscheduling no motion temp timer"
    unschedule(setTemp)
    log.debug "setting motion temp"
    setTemp('motion')
} 
else
{
    // schedule delay since no motion on any device is found
    if (motion.find{it.currentState('motion').value == "active"} == null &&	
    contact.find{it.currentState('contact').value == "open"} == null) 
    {
        log.debug "will set no motion temp in $delay secs"        
        runIn(delay, setTemp)		
    }
}

}

def setTemp(state)
{

if (state == "motion") 
{
    // thermostat.setCoolingSetpoint(coolingSetpointMotion)
    // thermostat.setHeatingSetpoint(heatingSetpointMotion)
}
else 
{ 
    if (noMotionOff) {
       thermostat.off()
    }
    else
    {
       thermostat.setCoolingSetpoint(coolingSetpointNoMotion)
       thermostat.setHeatingSetpoint(heatingSetpointNoMotion)
    }
    
}

}

(cslee) #6

you’re right it stops running after awhile ? wonder why?

(Chris LeBlanc) #7

Hey cslee… This source code is a bit older than what I am using currently. What I’ve found is the app works fine as long as you aren’t trying to set both heating and cooling at the same time. I am not certain why this is a problem but it does work significantly more reliably either setpoints set, not both.

(cslee) #8

That’s not too useful. Do you need to check the mode before setting the setpoints then?

(Chris LeBlanc) #9

I’m not sure what you mean. It works as long as you live in a part of the us that has long, consistent summers and winters :slight_smile:

(cslee) #10

Ya, So you have to change the program comes winter. In california, the seasons are not so well defined.

(cslee) #11

perhaps, there needs to be a delay in-between setting the set points.

(Chris LeBlanc) #12

Well, as my original post suggests, I’ve tried this and for whatever reason it made no difference. I think at one point I had a 10s delay between.

Let me see if I can post up my new code.

(Chris LeBlanc) #13

Here’s my latest source code stored on Github as suggested by SmartThings.

Motion/Contact Activated Thermostat

(cslee) #14

Thanks, I’ll give it a try

(Jarred Pettijohn) #15

So, did your fixes in the latest code solve the issue where it would stop running @leblaaanc?

(Chris LeBlanc) #16

No, for the longest time I have just been running the cooling setpoint only (just omit the heating values in the settings of the app).

I just recently set both and have seen it fail to set the heating setpoint already once though admittedly I’m not paying as much attention to it since the weather is pretty close to my setpoints at the moment.

(Jarred Pettijohn) #17

I’m brand new to this, so my apologies on if my ignorance is showing here.

I’m wondering what type of thermostat you are running this against and if you think that may make a difference? I just installed a ST hub, motion sensor, and a Honeywell Zwave enabled thermostat at my fire station and I am wanting to start with this code as it mostly does what I’m wanting to accomplish.

So anyway, I’ll test it against my thermostat and see what happens and report it back here.

(Chris LeBlanc) #18

This SmartApp should work with any thermostat which claims to be a thermostat device.

(Brad Kowal) #19

Thank you for writing this smartapp

would it be possible for you to add a between time of day for sensing?

there are people home by day that prefer the temperature higher, when I get home after 5pm I like it 2 or 3 degrees cooler based on the living-room motion sensor temperature.

thanks in advance