Ask for help: Room Temp rises above xx then turn on xx


(Yuxiao) #1

I got a smart outlet with my air conditioner and I want to turn on the air conditioner when the temp rises above a certain degrees.(Not smart AC, I just plug the AC outlet in the smart Outlet.).
More specific, I want turn on the switch when the Temp rises above 26 only when the mode is Home and detect motion.
So is there any smartapp I can use? Since I cannot find one.


(Andy) #2

I use the SmartRules app from @obycode to handle a similar scenario with ceiling fans.


(Yuxiao) #3

but this cannot set up when TEMP rises above 26 degree


(Bruce) #4

You can use this SmartApp:


(Yuxiao) #5

This doesn’t work! I don’t have a thermost!


(Bruce) #6

It’s a virtual thermostat. All you need is any device that reports temperature, such as a motion sensor, contact sensor, etc. There is no real thermostat involved. Obviously, you have to measure temperature some how!


(Bruce) #7

Re-reading your original post, you might need minor mods to this to add the motion qualifier for when it comes on. I could do that for you if you want. What kind of motion sensor do you have? It probably reports temperature also. So you would be all set.

Minor mod would mean that AC would come on when temperature is over 79° F (or whatever) AND mode is Home AND motion is active.


(Yuxiao) #8

I got a Motion Sensor that can also detect Temp AND also a Temp/Humidity sensor.
I would like that I can choose motion sensor and Temp sensor different . And minor mods you talks about is really good for me I think! If you can do it, I would be really thanks!


(Bruce) #9

I will do it in a few minutes, it is very simple, and I will post it here. Yes, the temperature must be selected separately. If you select more than one temperature sensor, it will average them. So you can select both of yours if you want. The mod to the app is for selecting the motion sensor and restricting ON for only when there is motion active.

When motion stops, do you want it to turn off?


(Yuxiao) #10

I want it has a option to turn off since I may want turn off in some reason and may not.


(Bruce) #11

Here is the modified app, below. I have not addressed the motion-off case yet. Why don’t you see if this works for you, and let me know. You can use the ST app to turn off the AC, or it will turn off when the temp is where the setpoint is.

/**
*  Virtual Thermostat - Nest without a Nest
*
*  Author: An Nguyen, modified by Bruce Ravenel to add motion test
*
*/
definition(
    name: "Virtual Thermostat - Nest without a Nest",
    namespace: "amn0408",
    author: "An Nguyen",
    description: "A virtual thermostat for homes not compatible with Nest. Get enhanced control over your heating and cooling devices with temperature readings from multiple sensors, mode-based thermostat settings, and if you have a humidity sensor, feels-like temperatures. Based on the original Virtual Thermostat and Green Thermostat apps.",
    category: "Green Living",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/temp_thermo-switch.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/temp_thermo-switch@2x.png"
)

preferences {
    page(name: "modePage", title:"Mode", nextPage:"thermostatPage", uninstall: true) {
        section () {
            paragraph "Let's tell the virtual thermostat what mode to be on."
            input "mode", "enum", title: "Set thermostat mode to", metadata: [values: ["Heating","Cooling"]], required:true   
        }
    }
    page(name: "thermostatPage", title:"Thermostat", nextPage: "sensitivityPage") {
        section () {
            paragraph "Let's tell the virtual thermostat about your desired temperatures."
        }
        section("When home during the day,") {
                input "homeHeat",  "decimal", title:"Set heating temperature to (ex. 72)", required:true
                input "homeCool",  "decimal", title:"Set cooling temperature to (ex. 76)", required:true
        }
        section("When home at night") {
            input "nightHeat", "decimal", title:"Set heating temperature to (ex. 68)", required: true
            input "nightCool", "decimal", title:"Set cooling temperature to (ex. 80)", required: true
        }
        section("When away") {
            input "awayHeat", "decimal", title:"Set heating temperature to (ex. 60)", required: true
            input "awayCool", "decimal", title:"Set cooling temperature to (ex. 85)", required: true
        }
    }
    page(name: "sensitivityPage", title:"Sensitivity", nextPage:"sensorsPage") {
        section(){
            paragraph "Let's tell the virtual thermostat how sensitive to be. Most thermostats use 2 degree changes to control switches. Smaller values lead to more consistent temperatures, but will turn switches on and off more often."
        } 
        section(){
            paragraph "Let's tell the thermostat when to turn switches on."
            input "onThreshold", "decimal", title: "Turn on when temperature is this far from setpoint", required: true
        }
        section(){
            paragraph "Let's tell the thermostat when to turn off."
            input "offThreshold", "decimal", title: "Turn off when temperature reaches & goes this far beyond setpoint", required: true
        }
    }
    page(name: "sensorsPage", title:"Sensors", nextPage: "switchesPage") {
        section(){
            paragraph "Let's tell the virtual thermostat what sensors to use."
            input "temperatureSensors", "capability.temperatureMeasurement", title: "Get temperature readings from these sensors", multiple: true, required: true
            input "humiditySensors", "capability.relativeHumidityMeasurement", title: "Get humidity readings from these sensors", multiple: true, required: false
            input "motionSensors", "capability.motionSensor", title: "Select motion sensors to enable cooling", multiple: true, required: false
        }
    }
    page(name: "switchesPage", title:"Switches", nextPage: "SmartThingsPage") {
        section(){
            paragraph "Let's tell the virtual thermostat what outlets to use."
            input "coolOutlets", "capability.switch", title: "Control these switches when cooling", multiple: true
            input "heatOutlets", "capability.switch", title: "Control these switches when heating ", multiple: true
        }
    }
    page(name: "SmartThingsPage", title: "Name app and configure modes", install: true, uninstall: true) {
        section() {
            label title: "Assign a name", required: false
            mode title: "Set for specific mode(s)", required: false
        }
    }
}

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

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

def initialize()
{
    for (sensor in temperatureSensors)
        subscribe(sensor, "temperature", evtHandler)
    for (sensor in humiditySensors)
        subscribe(sensor, "humidity", evtHandler)
    subscribe(location, changedLocationMode)
    subscribe(app, appTouch)
    subscribe(heatOutlets, "switch.off", offHandler)
    subscribe(coolOutlets, "switch.off", offHandler)
    
    def temp = getReadings("temperature")
    log.debug "Temp: $temp"

    def humidity = getReadings("humidity")
    log.debug "Humidity: $humidity"   

    def feelsLike = getFeelsLike(temp, humidity)
    log.debug "Feels Like: $feelsLike"       
	
    //Keeps track of whether or not the outlets are turned on by the app. This is to 
    //prevent sending too many commands if it is taking awhile to cool or heat. Note: If  
    //the user manually  changes the state of an outlet, it will stay in that state until 
    //the threshold is triggered again.
	state.outlets = ""
    
    setSetpoint(feelsLike)
}

//Function getReadings: Gets readings from sensors and averages
def double getReadings(type)
{
    def currentReadings = 0
    def numSensors = 0
    
    def sensors = temperatureSensors
    if (type == "humidity")
        sensors = humiditySensors

    for (sensor in sensors)
    {
        if (sensor.latestValue(type) != null)
        {
            currentReadings = currentReadings + sensor.latestValue(type)
            numSensors = numSensors + 1
        }
    }
    //Only average if there are multiple readings and sensors
    if (currentReadings != 0 && numSensors != 0)
    {
        currentReadings = currentReadings / numSensors
    }
    
    return currentReadings
}

//Function getFeelsLike: Calculates feels-like temperature based on Wikipedia formula
def double getFeelsLike(t,h)
{
    //Formula is derived from NOAA table for temperatures above 70F. Only use the formula when temperature is at least 70F and humidity is greater than zero (same as at least one humidity sensor selected)
    if (t >=70 && h > 0) {
        def feelsLike = 0.363445176 + 0.988622465*t + 4.777114035*h -0.114037667*t*h - 0.000850208*t**2 - 0.020716198*h**2 + 0.000687678*t**2*h + 0.000274954*t*h**2
        log.debug("Feels Like Calc: $feelsLike")
        //Formula is an approximation. Use the warmer temperature.
        if (feelsLike > t)
            return feelsLike
        else
            return t
    }
    else
        return t
}

//Function setSetpoint: Determines the setpoints based on mode
def setSetpoint(temp)
{
    if (location.mode == "Home" ) {
        evaluate(temp, homeHeat, homeCool)
    }
    if (location.mode == "Away" ) {
        evaluate(temp, awayHeat, awayCool)
    }
    if (location.mode == "Night" ) {
        evaluate(temp, nightHeat, nightCool)
    }
}

//Function evtHandler: Main event handler
def evtHandler(evt)
{
    def temp = getReadings("temperature")
    log.info "Temp: $temp"

    def humidity = getReadings("humidity")
    log.info "Humidity: $humidity"

    def feelsLike = getFeelsLike(temp, humidity)
    log.info "Feels Like: $feelsLike"

    setSetpoint(feelsLike)
}

//Function changedLocationMode: Event handler when mode is changed
def changedLocationMode(evt)
{
    log.info "changedLocationMode: $evt, $settings"
    evtHandler(evt)
}

//Function appTouch: Event handler when SmartApp is touched
def appTouch(evt)
{
    log.info "appTouch: $evt, $lastTemp, $settings"
    evtHandler(evt)
}

//Function evaluation: Evaluates temperature and control outlets
private evaluate(currentTemp, desiredHeatTemp, desiredCoolTemp)
{
    log.debug "Evaluating temperature ($currentTemp, $desiredHeatTemp, $desiredCoolTemp, $mode)"
    if (mode == "Cooling") {
        // Cooling
        if (currentTemp - desiredCoolTemp >= onThreshold && state.outlets != "on") {
        	if(motionSensors) {
        		def motionOn = false
        		motionSensors.each {motionOn = motionOn || it.currentMotion == "active"}
                        log.debug "motion: $motionOn"
            	        if(motionOn) {
                	    coolOutlets.on()
            		    state.outlets = "on"
            		    log.debug "Need to cool: Turning outlets on"
                        }
        	} else {
                coolOutlets.on()
            	state.outlets = "on"
            	log.debug "Need to cool: Turning outlets on"
                }
        }
        else if (desiredCoolTemp - currentTemp >= offThreshold && state.outlets != "off") {
            coolOutlets.off()
            state.outlets = "off"
            log.debug "Done cooling: Turning outlets off"
        }
    }
    else {
        // Heating
        if (desiredHeatTemp - currentTemp >= onThreshold && state.outlets != "on") {
            heatOutlets.on()
            state.outlets = "on"
            log.debug "Need to heat: Turning outlets on"
        }
        else if (currentTemp - desiredHeatTemp >= offThreshold && state.outlets != "off") {
            heatOutlets.off()
            state.outlets = "off"
            log.debug "Done heating: Turning outlets off"
        }
    }
}

def offHandler(evt) {
	state.outlets = "off"
}

// Event catchall
def event(evt)
{
    log.info "value: $evt.value, event: $evt, settings: $settings, handlerName: ${evt.handlerName}"
}

(Yuxiao) #12

It shows error when I put the code

grails.validation.ValidationException: Validation Error(s) occurred during save():

  • Field error in object ‘physicalgraph.app.InstalledSmartApp’ on field ‘state’: rejected value [COMPLETE]; codes [physicalgraph.app.InstalledSmartApp.state.validator.error.physicalgraph.app.InstalledSmartApp.state,physicalgraph.app.InstalledSmartApp.state.validator.error.state,physicalgraph.app.InstalledSmartApp.state.validator.error.physicalgraph.app.InstallationState,physicalgraph.app.InstalledSmartApp.state.validator.error,installedSmartApp.state.validator.error.physicalgraph.app.InstalledSmartApp.state,installedSmartApp.state.validator.error.state,installedSmartApp.state.validator.error.physicalgraph.app.InstallationState,installedSmartApp.state.validator.error,physicalgraph.app.InstalledSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstalledSmartApp.state,physicalgraph.app.InstalledSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.state,physicalgraph.app.InstalledSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstallationState,physicalgraph.app.InstalledSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required,installedSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstalledSmartApp.state,installedSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.state,installedSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstallationState,installedSmartApp.state.Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required,Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstalledSmartApp.state,Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.state,Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required.physicalgraph.app.InstallationState,Input ‘[homeHeat, homeCool, nightHeat, nightCool, awayHeat, awayCool]’ is required]; arguments [state,class physicalgraph.app.InstalledSmartApp,COMPLETE]; default message [[{1}]类的属性[{0}]的值[{2}]未能通过自定义的验证]

(Bruce) #13

When I install it, there is no error. You must fill in the selections.


(Bruce) #14

I found a bug in the code, it has been modified above, so you should recopy it. Be sure you get all of the code when you copy and paste!


(Bruce) #15

You probably did not copy ALL of the code when you created the app. Try again.


(Brice; SmartRulesApp.com) #16

SmartRules can handle triggering when a temperature sensor goes above a given value. You can also add conditions like checking if mode is home and while motion is active if you want. I think to make the rule do what you want, you might want it to trigger on either temperature rising above 26 or motion being detected, then add conditions for temperature is above 26 and motion is active and mode is home. Then another rule to turn it off when the temperature drops below 25 (for example).


(Aaron Santana) #17

I don’t know about an app which can be helpful for you, but you can try searching on different Website, I am sure you will find a solution.