[RELEASE] 5-2 Day Programmable Thermostat Scheduler (Weekday, Weekend) with Remote Temperature Sensor for each Schedule

This is a 5-2 Day Thermostat with Remote Sensor Scheduler with advanced features SmartApp

This advanced version includes support for using multiple Remote Temperature Sensors (e.g. different rooms) to control the thermostat and also using cooling/heating appliances.
(See below for basic version)



Key Features Include:

  • 4 schedules per day for weekdays and 4 schedules per day for a weekend
  • Use remote temperature sensors
    • average multiple temperature sensors
    • set target temperature for each schedule or globally for all schedules
  • Use thermostat or heating/cooling appliances (heaters, window A/C, fans, etc)
  • Set fan mode for each schedule
  • Supports temperature in C and F with 0.1 degree resolution
  • Shutting down thermostat if doors/windows are left open
  • Thermostat temporary hold (hold manually adjusted temperature until next scheduled change)
  • Battery saver mode (reduces verification communications, only enable if you have a strong mesh with repeaters especially while using remote temperature sensors)
  • Supports ST DeadZones for DTHs
  • Limit Mode of operations
  • Supports multiple thermostats
  • Switch HVAC mode based on external temperature sensors
  • Verification engine to compensate for lost commands due to connectivity issues
  • Lock temperature setpoints (reset changes made on thermostat)
  • Automatic app update notifications

Works with any SmartThings compatible thermostat including Z-Wave/ZigBee/EcoBee/Nest etc

Using Remote Temperature Sensors

Please note that if you’re using external temperature sensor(s) in the SmartApp, it will set the thermostat setpoints to around 85F for heating and around 60F for cooling until the external sensor temperature(s) indicates that the desired temperature has been achieved after which the setpoints will be reversed to turn the thermostat off. This is normal behavior, please ensure that your thermostat is using factory settings and the setpoints range are not limited.

Installation instructions available here

The Advanced version of this app is available on the RBoy Apps server

Refer to our facebook page http://www.facebook.com/RBoySTApps to get the latest news and updates.


You can also check out the following thermostat management apps


This code below is for a basic 5-2 Day Programmable Thermostat (Weekday and Weekend) with 4 programmable timers for each day.

BASIC 5-2 DAY PROGRAMMABLE THERMOSTAT SCHEDULER (without Remote Temperature Sensor)

/* **DISCLAIMER**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 
 
/**
 *  5-2 Day Thermostat
 *
 * Base code from mwoodengr@hotmail.com, bugfixed and enhanced by RBoy Apps
 * Changes Copyright RBoy Apps, redistribution of any changes or modified code is not allowed without permission
 * Version 2.1.0
 * 2015-10-3 - Fixed an issue with selecting multiple thermostats and for recent platform changes
 *
 */
definition(
		name: "5-2 Day Thermostat",
		namespace: "rboy",
		author: "RBoy Apps",
		description: "Weekday and Weekend Thermostat",
    	category: "Green Living",
    	iconUrl: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving.png",
    	iconX2Url: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving@2x.png",
    	iconX3Url: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving@3x.png")

preferences {
	section("Choose thermostat (s)") {
		input "thermostats", "capability.thermostat", required: true, multiple:true
	}

    section("Switch HVAC mode (auto to cool/heat) based on the outside temperature (optional)") {
		input "temperatureSensor", "capability.temperatureMeasurement", required: false
		input "temperatureH", "number", title: "Switch to heating temperature", required: false, description: "Temperature below which switch to heat mode"
		input "temperatureC", "number", title: "Switch to cooling temperature", required: false, description: "Temperature above which switch to cool mode"
	}

	section("Monday to Friday Schedule") {
		input "time1", "time", title: "Wake Time", required: true
		input "tempSetpoint1", "number", title: "Wake Heat Temp", required: true
		input "tempSetpointA", "number", title: "Wake Cool Temp", required: true
		input "time2", "time", title: "Leave Time", required: true
		input "tempSetpoint2", "number", title: "Leave Heat Temp", required: true
		input "tempSetpointB", "number", title: "Leave Cool Temp", required: true
		input "time3", "time", title: "Return Time", required: true
		input "tempSetpoint3", "number", title: "Return Heat Temp", required: true
		input "tempSetpointC", "number", title: "Return Cool Temp", required: true
		input "time4", "time", title: "Sleep Time", required: true
		input "tempSetpoint4", "number", title: "Sleep Heat Temp", required: true
		input "tempSetpointD", "number", title: "Sleep Cool Temp", required: true
	}
	section("Saturday and Sunday Schedule") {
		input "time11", "time", title: "Wake Time", required: true
		input "tempSetpoint11", "number", title: "Wake Heat Temp", required: true
		input "tempSetpointAA", "number", title: "Wake Cool Temp", required: true
		input "time21", "time", title: "Leave Time", required: true
		input "tempSetpoint21", "number", title: "Leave Heat Temp", required: true
		input "tempSetpointBB", "number", title: "Leave Cool Temp", required: true
		input "time31", "time", title: "Return Time", required: true
		input "tempSetpoint31", "number", title: "Return Heat Temp", required: true
		input "tempSetpointCC", "number", title: "Return Cool Temp", required: true
		input "time41", "time", title: "Sleep Time", required: true
		input "tempSetpoint41", "number", title: "Sleep Heat Temp", required: true
		input "tempSetpointDD", "number", title: "Sleep Cool Temp", required: true
	}
}

def installed()
{
	subscribeToEvents()
}

def updated()
{
    unsubscribe()
	subscribeToEvents()
}

def subscribeToEvents() {
	subscribe(temperatureSensor, "temperature", temperatureHandler)
    subscribe(location, modeChangeHandler)

    initialize()
}

// Handle mode changes, reinitialize the current temperature and timers after a mode change, this is to workaround the issue of the last timer firing while in a non running mode, resume operations when supported modes are set
def modeChangeHandler(evt) {
	log.debug "Reinitializing thermostats on mode change notification, new mode $evt.value"
	//sendNotificationEvent("$thermostats Reinitializing on mode change notification, new mode $evt.value")
    initialize()
}

// This section sets the HVAC mode based outside temperature. HVAC fan mode is set to "auto".
def temperatureHandler(evt) {
	log.debug "Heat mode switch temperature $temperatureH, cool mode switch temperature $temperatureC"
    
	if (temperatureH == null || temperatureC == null) { // We are in Auto mode or user doesn't want us to switch modes
		return
	}
	
    thermostats.each { thermostat ->
        def extTemp = temperatureSensor.currentTemperature
        log.debug "External temperature is: $extTemp"
        def thermostatState = thermostat.currentThermostatMode
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "HVAC current mode $thermostatState"
        log.debug "HVAC Fan current mode $thermostatFan"
        if (extTemp < temperatureH) {
            if (thermostatState == "cool") {
                def hvacmode = "heat"
                thermostat.setThermostatMode(hvacmode)
                log.debug "HVAC mode set to $hvacmode"
            }
        }
        else if (extTemp > temperatureC) {
            if (thermostatState == "heat") {
                def hvacmode = "cool"
                thermostat.setThermostatMode(hvacmode)
                log.debug "HVAC mode set to $hvacmode"
            }
        }

        if (thermostatFan != "fanAuto") {
            thermostat.setThermostatFanMode("auto")
            log.debug "HVAC fan mode set to auto"
        }
    }
}

// This section determines which day it is.
def initialize() {
	log.trace "Initialized with $settings"

	unschedule()
	def calendar = Calendar.getInstance()
	calendar.setTimeZone(location.timeZone)
	def today = calendar.get(Calendar.DAY_OF_WEEK)
   	def timeNow = now()
	def midnightToday = timeToday("2000-01-01T23:59:59.999-0000", location.timeZone)
   	log.debug("Current time is ${(new Date(timeNow)).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
	log.debug("Midnight today is ${midnightToday.format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
   	log.trace("Weekday schedule1 ${timeToday(time1, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekday schedule2 ${timeToday(time2, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekday schedule3 ${timeToday(time3, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekday schedule4 ${timeToday(time4, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekend schedule1 ${timeToday(time11, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekend schedule2 ${timeToday(time21, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekend schedule3 ${timeToday(time31, location.timeZone).format("HH:mm z", location.timeZone)}")
   	log.trace("Weekend schedule4 ${timeToday(time41, location.timeZone).format("HH:mm z", location.timeZone)}")

	// This section is where the time/temperature schedule is set
	switch (today) {
		case Calendar.MONDAY:
		case Calendar.TUESDAY:
		case Calendar.WEDNESDAY:
		case Calendar.THURSDAY:
        	if (timeNow >= timeToday(time1, location.timeZone).time && timeNow < timeToday(time2, location.timeZone).time) { // Are we between 1st time and 2nd time
        		changeTemp1()
            	schedule(timeToday(time2, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
        	}
        	else if (timeNow >= timeToday(time2, location.timeZone).time && timeNow < timeToday(time3, location.timeZone).time) { // Are we between 2nd time and 3rd time
            	changeTemp2()
				schedule(timeToday(time3, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time3, location.timeZone).time && timeNow < timeToday(time4, location.timeZone).time) { // Are we between 3rd time and 4th time
            	changeTemp3()
				schedule(timeToday(time4, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time4, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time and midnight, schedule next day
            	changeTemp4()
				schedule(timeToday(time1, location.timeZone) + 1, initialize)
                log.info("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time1, location.timeZone).time) { // Are we between midnight yesterday and 1st time, schedule today
            	changeTemp4()
				schedule(timeToday(time1, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
			break
			
		case Calendar.FRIDAY:
        	if (timeNow >= timeToday(time1, location.timeZone).time && timeNow < timeToday(time2, location.timeZone).time) { // Are we between 1st time and 2nd time
        		changeTemp1()
            	schedule(timeToday(time2, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
        	}
        	else if (timeNow >= timeToday(time2, location.timeZone).time && timeNow < timeToday(time3, location.timeZone).time) { // Are we between 2nd time and 3rd time
            	changeTemp2()
				schedule(timeToday(time3, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time3, location.timeZone).time && timeNow < timeToday(time4, location.timeZone).time) { // Are we between 3rd time and 4th time
            	changeTemp3()
				schedule(timeToday(time4, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time4, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time Friday and midnight, we schedule Saturday
            	changeTemp4()
				schedule(timeToday(time11, location.timeZone) + 1, initialize)
                log.info("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time11, location.timeZone).time) { // Are we between midnight Friday and 1st time on Saturday, we schedule Saturday
            	changeTemp4()
				schedule(timeToday(time11, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
			break

		case Calendar.SATURDAY:
            if (timeNow >= timeToday(time11, location.timeZone).time && timeNow < timeToday(time21, location.timeZone).time) { // Are we between 1st time and 2nd time
        		changeTemp11()
            	schedule(timeToday(time21, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
        	}
        	else if (timeNow >= timeToday(time21, location.timeZone).time && timeNow < timeToday(time31, location.timeZone).time) { // Are we between 2nd time and 3rd time
            	changeTemp21()
				schedule(timeToday(time31, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time31, location.timeZone).time && timeNow < timeToday(time41, location.timeZone).time) { // Are we between 3rd time and 4th time
            	changeTemp31()
				schedule(timeToday(time41, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time41, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time and midnight, schedule the next day
            	changeTemp41()
				schedule(timeToday(time11, location.timeZone) + 1, initialize)
                log.info("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time11, location.timeZone).time) { // Are we between midnight yesterday and 1st time, schedule today
            	changeTemp41()
				schedule(timeToday(time11, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
			break
            
		case Calendar.SUNDAY:
            if (timeNow >= timeToday(time11, location.timeZone).time && timeNow < timeToday(time21, location.timeZone).time) { // Are we between 1st time and 2nd time
        		changeTemp11()
            	schedule(timeToday(time21, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
        	}
        	else if (timeNow >= timeToday(time21, location.timeZone).time && timeNow < timeToday(time31, location.timeZone).time) { // Are we between 2nd time and 3rd time
            	changeTemp21()
				schedule(timeToday(time31, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time31, location.timeZone).time && timeNow < timeToday(time41, location.timeZone).time) { // Are we between 3rd time and 4th time
            	changeTemp31()
				schedule(timeToday(time41, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= timeToday(time41, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time Sunday and midnight, we schedule Monday
            	changeTemp41()
				schedule(timeToday(time1, location.timeZone) + 1, initialize)
                log.info("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
            else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time1, location.timeZone).time) { // Are we between midnight Sunday and 1st time on Monday, we schedule Monday
            	changeTemp41()
				schedule(timeToday(time1, location.timeZone), initialize)
                log.info("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
                //sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
            }
			break
	}
}

// This section is where the thermostat temperature settings are set. 
def changeTemp1() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint1)
            thermostat.setCoolingSetpoint(tempSetpointA)
            log.info "Set $thermostat Heat $tempSetpoint1°, Cool $tempSetpointA°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint1)
            log.info "Set $thermostat Heat $tempSetpoint1°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointA)
            log.info "Set $thermostat Cool $tempSetpointA°"
        }
    }
}

def changeTemp2() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint2)
            thermostat.setCoolingSetpoint(tempSetpointB)
            log.info "Set $thermostat Heat $tempSetpoint2°, Cool $tempSetpointB°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint2)
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointB)
        }
    }
}

def changeTemp3() {
    thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint3)
            thermostat.setCoolingSetpoint(tempSetpointC)
            log.info "Set $thermostat Heat $tempSetpoint3°, Cool $tempSetpointC°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint3)
            log.info "Set $thermostat Heat $tempSetpoint3°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointC)
            log.info "Set $thermostat Cool $tempSetpointC°"
        }
    }
}

def changeTemp4() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint4)
            thermostat.setCoolingSetpoint(tempSetpointD)
            log.info "Set $thermostat Heat $tempSetpoint4°, Cool $tempSetpointD°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint4)
            log.info "Set $thermostat Heat $tempSetpoint4°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointD)
            log.info "Set $thermostat Cool $tempSetpointD°"
        }
    }
}

def changeTemp11() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint11)
            thermostat.setCoolingSetpoint(tempSetpointAA)
            log.info "Set $thermostat Heat $tempSetpoint11°, Cool $tempSetpointAA°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint11)
            log.info "Set $thermostat Heat $tempSetpoint11°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointAA)
            log.info "Set $thermostat Cool $tempSetpointAA°"
        }
    }
}

def changeTemp21() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint21)
            thermostat.setCoolingSetpoint(tempSetpointBB)
            log.info "Set $thermostat Heat $tempSetpoint21°, Cool $tempSetpointBB°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint21)
            log.info "Set $thermostat Heat $tempSetpoint21°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointBB)
            log.info "Set $thermostat Cool $tempSetpointBB°"
        }
    }
}

def changeTemp31() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint31)
            thermostat.setCoolingSetpoint(tempSetpointCC)
            log.info "Set $thermostat Heat $tempSetpoint31°, Cool $tempSetpointCC°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint31)
            log.info "Set $thermostat Heat $tempSetpoint31°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointCC)
            log.info "Set $thermostat Cool $tempSetpointCC°"
        }
    }
}

def changeTemp41() {
	thermostats.each { thermostat ->
        def thermostatState = thermostat.currentThermostatMode
        log.debug "Thermostat mode = $thermostatState"
        def thermostatFan = thermostat.currentThermostatFanMode
        log.debug "Thermostat fan = $thermostatFan"
        if (thermostatState == "auto") {
            thermostat.setHeatingSetpoint(tempSetpoint41)
            thermostat.setCoolingSetpoint(tempSetpointDD)
            log.info "Set $thermostat Heat $tempSetpoint41°, Cool $tempSetpointDD°"
        }
        else if (thermostatState == "heat") {
            thermostat.setHeatingSetpoint(tempSetpoint41)
            log.info "Set $thermostat Heat $tempSetpoint41°"
        }
        else {
            thermostat.setCoolingSetpoint(tempSetpointDD)
            log.info "Set $thermostat Cool $tempSetpointDD°"
        }
    }
}

The latest versions are available on the RBoy Apps server

© RBoy Apps

11 Likes

Cool… Thanks for sharing. I’m definitely going to take a look at this. I just re-programmed by Honeywell and thought I should be able to do it with SmartThings, but didn’t, at the time, think there was a program option for it.

Question: Does this set the programming on the Themostat? That is…will this push the programming to device so that it will run independent of SmartThings? I guess I don’t want to see a situation where ST hiccups and doesn’t turn off/on one of the programming modes.

Relates Question: If the answer to the above is no, do I need to shut off all programming on the thermostat itself or will ST and the internal programming be potentially battling each other?

1 Like

This is just a generic smart app designed to work wtih any thermostat so it only programs the “current” temperature and sets up timers on the ST platform to change the thermostat temperature at the user entered times. So yes it runs on the ST platform.
And no it doesn’t disable any other programs or schedules so you have setup so you will need to take of any conflicts.
E.g. I have set this program to use when in Home and night mode only and ensured nothing else is changing the temperature on the thermostat in those modes.

Just fixed a bug when crossing over midnight causing the scheduler to skip a day at times.

Wiredly there’s a bug in the platform, after schedule the apps needs to call unschedule() before scheduling the next schedule or it stops working after 2-3 schedules.

I installed this SmartApp and tried programming for one of my thermostats. When I hit “done” I get “an unexpected error occurred” and nothing is saved. Could this be because I have not yet deleted other temperature changes tied to modes?

I would hate to delete all my existing temperature changes and find out this SmartApp still doesn’t work…

Thanks

No, just take the latest code, I just updated it. Maybe you got some old code. It’s working because I’m running it right now. You don’t need to change anything. I have other temperature apps also connected and no issues at all. I think it just may be a bug.

If you can, in your IDE open the Live Debugger and if you get the error, let me know what line it shows up in.

Code detail says it was updated 11/13/14 (today). I re-published, logged out of ST. Logged back in, entered some time and temperature data. Hit “done”… same error…

I don’t see the live debugger in IDE… where can I find it?

Thanks

Can you help me with data you’ve entered. Also did you enter the external temperature ? Did you enter all temperatures for weekday and weekend?

When you open the IDE to the left of the Documentation link is a link called Live Logging (the URL is https://graph.api.smartthings.com/ide/logs)

I think you may need to enable it once in your settings? (am not sure).

But once in the live logging, then update the app and all the debug messages should show up there with the error and location.

I’m current using this on 2 thermostats, but I’m not using the external temperature option.

and yes it was updated multiple times today, I just updated it about 15 minutes ago. Try taking the latest code right now if you haven’t.

OK… logs updated so quickly it took me a couple of tries to get the data before it scrolled off the screen…

‎9‎:‎23‎:‎07‎ ‎PM: error java.text.ParseException: Unparseable date: “2014-11-13Tnull” @ line 135

BTW, I am not using the external temperature option either.

It looks like your time input was wrong or your system isn’t setup right. It isn’t able to get the date from your system.

Try this, delete the app all together from your list of my smart apps. Then create a new apps and copy the paste the code and start over. It may be an installation issue, someone from the ST team told me that the date used by ST is when the app was first installed, possibly in this case it didn’t register a date due to some bug. Try clean over.

Check your input specifially, see this line:
“2014-11-13Tnull”

Usualy it’s a DateTTime, in your case the time is null, so it’s not taking the inputs properly, possible Time2 (leave time)

I was not completing the leave and return fields… thought they were optional… my bad…

After entering times and temps for all fields, the app installed and seems to be working.

Sorry for all the trouble… Thanks for your patience and assistance.

Glad you took the time to develop this app. I ran out of patience waiting for ST to release the “Comfort” module that is supposed to enhance Thermostat control. Now I hear it has been delayed until after the new year,

Be glad to be of help, I just put a new app to change the thermostat based on motion in the room.

This is good feedback let me see if I can make it mandatory to include all times.

Done.

I know ST’s slow, I understand they need to focus on the platform and it’s performance and stability and if they can do just that I’d be okay.

I don’t mind making apps for the community I just wish that ST had a better support on the community forum. There are just a few folks who seems to be from ST and I don’t hear from them much / get much support on issues to help us get these apps out of the doors.

I hear you… and agree. Gets pretty frustrating sometimes…

Fixed an issue with external temp sensor, now added independent cooling and heating switching temperatures for external temp sensor to avoid oscillation

Added support to detect mode changes so that the latest temp is reset when an active mode is set (e.g. returning from away to home and thermostat is only set to run while in home mode, it will reset the temp to the current scheduled temp when the mode changes to home)

Can you tell me where I can get the most up to date code for the 5-2 Programmable Thermostat Scheduler you created?