DVCSMP-1174

FIX - Ecobee - Thermostat isn't responding to routines
This commit is contained in:
Warodom Khamphanchai
2015-10-28 12:46:44 -07:00
parent 90dee51255
commit 1b9d2fe9ce
3 changed files with 947 additions and 1023 deletions

View File

@@ -0,0 +1,66 @@
/**
* Ecobee Sensor
*
* Copyright 2015 Juan Risso
*
* 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.
*
*/
metadata {
definition (name: "Ecobee Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Sensor"
capability "Temperature Measurement"
capability "Motion Sensor"
capability "Refresh"
capability "Polling"
}
simulator {
// TODO: define status and reply messages here
}
tiles {
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°', unit:"F",
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
standardTile("motion", "device.motion") {
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main (["temperature","motion"])
details(["temperature","motion","refresh"])
}
}
def refresh() {
log.debug "refresh..."
poll()
}
void poll() {
log.debug "Executing 'poll' using parent SmartApp"
parent.pollChildren(this)
}

View File

@@ -35,18 +35,18 @@ metadata {
simulator { } simulator { }
tiles { tiles {
valueTile("temperature", "device.temperature", width: 2, height: 2) { valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°', unit:"F", state("temperature", label:'${currentValue}°', unit:"F",
backgroundColors:[ backgroundColors:[
[value: 31, color: "#153591"], [value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"], [value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"], [value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"], [value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"], [value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"], [value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"] [value: 96, color: "#bc2323"]
] ]
) )
} }
standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") { standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
@@ -55,7 +55,7 @@ metadata {
state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool" state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool"
state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto" state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto"
state "auxHeatOnly", action:"switchMode", icon: "st.thermostat.emergency-heat" state "auxHeatOnly", action:"switchMode", icon: "st.thermostat.emergency-heat"
state "updating", label:"Working", icon: "st.secondary.secondary" state "updating", label:"Working", icon: "st.secondary.secondary"
} }
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") { standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
state "auto", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "on" state "auto", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "on"
@@ -63,17 +63,17 @@ metadata {
state "off", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "circulate" state "off", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "circulate"
state "circulate", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "auto" state "circulate", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "auto"
} }
standardTile("upButtonControl", "device.thermostatSetpoint", inactiveLabel: false, decoration: "flat") { standardTile("upButtonControl", "device.thermostatSetpoint", inactiveLabel: false, decoration: "flat") {
state "setpoint", action:"raiseSetpoint", backgroundColor:"#d04e00", icon:"st.thermostat.thermostat-up" state "setpoint", action:"raiseSetpoint", icon:"st.thermostat.thermostat-up"
} }
valueTile("thermostatSetpoint", "device.thermostatSetpoint", width: 1, height: 1, decoration: "flat") { valueTile("thermostatSetpoint", "device.thermostatSetpoint", width: 1, height: 1, decoration: "flat") {
state "thermostatSetpoint", label:'${currentValue}' state "thermostatSetpoint", label:'${currentValue}°'
} }
valueTile("currentStatus", "device.thermostatStatus", height: 1, width: 2, decoration: "flat") { valueTile("currentStatus", "device.thermostatStatus", height: 1, width: 2, decoration: "flat") {
state "thermostatStatus", label:'${currentValue}', backgroundColor:"#ffffff" state "thermostatStatus", label:'${currentValue}', backgroundColor:"#ffffff"
} }
standardTile("downButtonControl", "device.thermostatSetpoint", inactiveLabel: false, decoration: "flat") { standardTile("downButtonControl", "device.thermostatSetpoint", inactiveLabel: false, decoration: "flat") {
state "setpoint", action:"lowerSetpoint", backgroundColor:"#d04e00", icon:"st.thermostat.thermostat-down" state "setpoint", action:"lowerSetpoint", icon:"st.thermostat.thermostat-down"
} }
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) { controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00" state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00"
@@ -91,10 +91,11 @@ metadata {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh" state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
} }
standardTile("resumeProgram", "device.resumeProgram", inactiveLabel: false, decoration: "flat") { standardTile("resumeProgram", "device.resumeProgram", inactiveLabel: false, decoration: "flat") {
state "resume", label:'Resume Program', action:"device.resumeProgram", icon:"st.sonos.play-icon" state "resume", action:"resumeProgram", nextState: "updating", label:'Resume Schedule', icon:"st.samsung.da.oven_ic_send"
state "updating", label:"Working", icon: "st.secondary.secondary"
} }
main "temperature" main "temperature"
details(["temperature", "upButtonControl", "thermostatSetpoint", "currentStatus", "downButtonControl", "mode", "resumeProgram", "refresh"]) details(["temperature", "upButtonControl", "thermostatSetpoint", "currentStatus", "downButtonControl", "mode", "resumeProgram", "refresh"])
} }
} }
@@ -117,192 +118,187 @@ def parse(String description) {
} }
def refresh() def refresh() {
{ log.debug "refresh called"
log.debug "refresh called" poll()
poll() log.debug "refresh ended"
log.debug "refresh ended"
}
def go()
{
log.debug "before:go tile tapped"
poll()
log.debug "after"
} }
void poll() { void poll() {
log.debug "Executing 'poll' using parent SmartApp" log.debug "Executing 'poll' using parent SmartApp"
def results = parent.pollChild(this) def results = parent.pollChild(this)
parseEventData(results) generateEvent(results) //parse received message from parent
generateStatusEvent()
} }
def parseEventData(Map results) def generateEvent(Map results) {
{
log.debug "parsing data $results" log.debug "parsing data $results"
if(results) if(results) {
{
results.each { name, value -> results.each { name, value ->
def linkText = getLinkText(device) def linkText = getLinkText(device)
def isChange = false def isChange = false
def isDisplayed = true def isDisplayed = true
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint") { if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint") {
def sendValue = value? convertTemperatureIfNeeded(value.toDouble(), "F", 1): value //API return temperature value in F
isChange = isTemperatureStateChange(device, name, value.toString()) isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange isDisplayed = isChange
sendEvent( sendEvent(
name: name, name: name,
value: value, value: sendValue,
unit: "F", unit: location.temperatureScale,
linkText: linkText, linkText: linkText,
descriptionText: getThermostatDescriptionText(name, value, linkText), descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name, handlerName: name,
isStateChange: isChange, isStateChange: isChange,
displayed: isDisplayed) displayed: isDisplayed)
} } else {
else { isChange = isStateChange(device, name, value.toString())
isChange = isStateChange(device, name, value.toString()) isDisplayed = isChange
isDisplayed = isChange
sendEvent(
name: name,
value: value.toString(),
linkText: linkText,
descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name,
isStateChange: isChange,
displayed: isDisplayed)
}
}
generateSetpointEvent ()
generateStatusEvent ()
}
}
void generateEvent(Map results)
{
log.debug "parsing data $results"
if(results)
{
results.each { name, value ->
def linkText = getLinkText(device)
def isChange = false
def isDisplayed = true
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint") {
isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange
sendEvent( sendEvent(
name: name, name: name,
value: value, value: value.toString(),
unit: "F", linkText: linkText,
linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText),
descriptionText: getThermostatDescriptionText(name, value, linkText), handlerName: name,
handlerName: name, isStateChange: isChange,
isStateChange: isChange, displayed: isDisplayed)
displayed: isDisplayed)
}
else {
isChange = isStateChange(device, name, value.toString())
isDisplayed = isChange
sendEvent( }
name: name,
value: value.toString(),
linkText: linkText,
descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name,
isStateChange: isChange,
displayed: isDisplayed)
}
} }
generateSetpointEvent () generateSetpointEvent ()
generateStatusEvent() generateStatusEvent ()
} }
} }
private getThermostatDescriptionText(name, value, linkText) //return descriptionText to be shown on mobile activity feed
{ private getThermostatDescriptionText(name, value, linkText) {
if(name == "temperature") if(name == "temperature") {
{ return "$linkText temperature is $value°F"
return "$linkText was $value°F"
} else if(name == "heatingSetpoint") {
return "heating setpoint is $value°F"
} else if(name == "coolingSetpoint"){
return "cooling setpoint is $value°F"
} else if (name == "thermostatMode") {
return "thermostat mode is ${value}"
} else if (name == "thermostatFanMode") {
return "thermostat fan mode is ${value}"
} else {
return "${name} = ${value}"
} }
else if(name == "heatingSetpoint") }
{
return "latest heating setpoint was $value°F" void setHeatingSetpoint(setpoint) {
setHeatingSetpoint(setpoint.toDouble())
}
void setHeatingSetpoint(Double setpoint) {
// def mode = device.currentValue("thermostatMode")
def heatingSetpoint = setpoint
def coolingSetpoint = device.currentValue("coolingSetpoint").toDouble()
def deviceId = device.deviceNetworkId.split(/\./).last()
//enforce limits of heatingSetpoint
if (heatingSetpoint > 79) {
heatingSetpoint = 79
} else if (heatingSetpoint < 45) {
heatingSetpoint = 45
} }
else if(name == "coolingSetpoint")
{ //enforce limits of heatingSetpoint vs coolingSetpoint
return "latest cooling setpoint was $value°F" if (heatingSetpoint >= coolingSetpoint) {
coolingSetpoint = heatingSetpoint
}
log.debug "Sending setHeatingSetpoint> coolingSetpoint: ${coolingSetpoint}, heatingSetpoint: ${heatingSetpoint}"
if (parent.setHold (this, heatingSetpoint, coolingSetpoint, deviceId)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
log.debug "Done setHeatingSetpoint> coolingSetpoint: ${coolingSetpoint}, heatingSetpoint: ${heatingSetpoint}"
generateSetpointEvent()
generateStatusEvent()
} else {
log.error "Error setHeatingSetpoint(setpoint)" //This error is handled by the connect app
} }
else if (name == "thermostatMode")
{
return "thermostat mode is ${value}"
}
else
{
return "${name} = ${value}"
}
} }
void setCoolingSetpoint(setpoint) {
void setHeatingSetpoint(degreesF) { setCoolingSetpoint(setpoint.toDouble())
setHeatingSetpoint(degreesF.toDouble())
} }
void setHeatingSetpoint(Double degreesF) { void setCoolingSetpoint(Double setpoint) {
log.debug "setHeatingSetpoint({$degreesF})" // def mode = device.currentValue("thermostatMode")
sendEvent("name":"heatingSetpoint", "value":degreesF) def heatingSetpoint = device.currentValue("heatingSetpoint").toDouble()
Double coolingSetpoint = device.currentValue("coolingSetpoint") def coolingSetpoint = setpoint
log.debug "coolingSetpoint: $coolingSetpoint" def deviceId = device.deviceNetworkId.split(/\./).last()
parent.setHold(this, degreesF, coolingSetpoint)
if (coolingSetpoint > 92) {
coolingSetpoint = 92
} else if (coolingSetpoint < 65) {
coolingSetpoint = 65
}
//enforce limits of heatingSetpoint vs coolingSetpoint
if (heatingSetpoint >= coolingSetpoint) {
heatingSetpoint = coolingSetpoint
}
log.debug "Sending setCoolingSetpoint> coolingSetpoint: ${coolingSetpoint}, heatingSetpoint: ${heatingSetpoint}"
if (parent.setHold (this, heatingSetpoint, coolingSetpoint, deviceId)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
log.debug "Done setCoolingSetpoint>> coolingSetpoint = ${coolingSetpoint}, heatingSetpoint = ${heatingSetpoint}"
generateSetpointEvent()
generateStatusEvent()
} else {
log.error "Error setCoolingSetpoint(setpoint)" //This error is handled by the connect app
}
} }
void setCoolingSetpoint(degreesF) { void resumeProgram() {
setCoolingSetpoint(degreesF.toDouble())
}
void setCoolingSetpoint(Double degreesF) { log.debug "resumeProgram() is called"
log.debug "setCoolingSetpoint({$degreesF})" sendEvent("name":"thermostatStatus", "value":"resuming schedule", "description":statusText, displayed: false)
sendEvent("name":"coolingSetpoint", "value":degreesF) def deviceId = device.deviceNetworkId.split(/\./).last()
Double heatingSetpoint = device.currentValue("heatingSetpoint") if (parent.resumeProgram(this, deviceId)) {
parent.setHold(this, heatingSetpoint, degreesF) sendEvent("name":"thermostatStatus", "value":"setpoint is updating", "description":statusText, displayed: false)
} runIn(5, "poll")
log.debug "resumeProgram() is done"
sendEvent("name":"resumeProgram", "value":"resume", descriptionText: "resumeProgram is done", displayed: false, isStateChange: true)
} else {
sendEvent("name":"thermostatStatus", "value":"failed resume click refresh", "description":statusText, displayed: false)
log.error "Error resumeProgram() check parent.resumeProgram(this, deviceId)"
}
def configure() {
}
def resumeProgram() {
parent.resumeProgram(this)
} }
def modes() { def modes() {
if (state.modes) { if (state.modes) {
log.debug "Modes = ${state.modes}" log.debug "Modes = ${state.modes}"
return state.modes return state.modes
} }
else { else {
state.modes = parent.availableModes(this) state.modes = parent.availableModes(this)
log.debug "Modes = ${state.modes}" log.debug "Modes = ${state.modes}"
return state.modes return state.modes
} }
} }
def fanModes() { def fanModes() {
["off", "on", "auto", "circulate"] ["off", "on", "auto", "circulate"]
} }
def switchMode() { def switchMode() {
log.debug "in switchMode" log.debug "in switchMode"
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
@@ -314,7 +310,7 @@ def switchMode() {
} }
def switchToMode(nextMode) { def switchToMode(nextMode) {
log.debug "In switchToMode = ${nextMode}" log.debug "In switchToMode = ${nextMode}"
if (nextMode in modes()) { if (nextMode in modes()) {
state.lastTriedMode = nextMode state.lastTriedMode = nextMode
"$nextMode"() "$nextMode"()
@@ -386,290 +382,310 @@ def setThermostatFanMode(String value) {
} }
def generateModeEvent(mode) { def generateModeEvent(mode) {
sendEvent(name: "thermostatMode", value: mode, descriptionText: "$device.displayName is in ${mode} mode", displayed: true)
sendEvent(name: "thermostatMode", value: mode, descriptionText: "$device.displayName is in ${mode} mode", displayed: true, isStateChange: true)
} }
def generateFanModeEvent(fanMode) { def generateFanModeEvent(fanMode) {
sendEvent(name: "thermostatFanMode", value: fanMode, descriptionText: "$device.displayName fan is in ${mode} mode", displayed: true)
sendEvent(name: "thermostatFanMode", value: fanMode, descriptionText: "$device.displayName fan is in ${mode} mode", displayed: true, isStateChange: true)
} }
def generateOperatingStateEvent(operatingState) { def generateOperatingStateEvent(operatingState) {
sendEvent(name: "thermostatOperatingState", value: operatingState, descriptionText: "$device.displayName is ${operatingState}", displayed: true)
sendEvent(name: "thermostatOperatingState", value: operatingState, descriptionText: "$device.displayName is ${operatingState}", displayed: true, isStateChange: true)
} }
def off() { def off() {
log.debug "off" log.debug "off"
generateModeEvent("off") def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"off")) if (parent.setMode (this,"off", deviceId))
generateModeEvent("off") generateModeEvent("off")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
generateModeEvent(currentMode) // reset the tile back generateModeEvent(currentMode) // reset the tile back
} }
generateSetpointEvent() generateSetpointEvent()
generateStatusEvent() generateStatusEvent()
} }
def heat() { def heat() {
log.debug "heat" log.debug "heat"
generateModeEvent("heat") def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"heat")) if (parent.setMode (this,"heat", deviceId))
generateModeEvent("heat") generateModeEvent("heat")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
generateModeEvent(currentMode) // reset the tile back generateModeEvent(currentMode) // reset the tile back
} }
generateSetpointEvent() generateSetpointEvent()
generateStatusEvent() generateStatusEvent()
} }
def auxHeatOnly() { def auxHeatOnly() {
log.debug "auxHeatOnly" log.debug "auxHeatOnly"
generateModeEvent("auxHeatOnly") def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"auxHeatOnly")) if (parent.setMode (this,"auxHeatOnly", deviceId))
generateModeEvent("auxHeatOnly") generateModeEvent("auxHeatOnly")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
generateModeEvent(currentMode) // reset the tile back generateModeEvent(currentMode) // reset the tile back
} }
generateSetpointEvent() generateSetpointEvent()
generateStatusEvent() generateStatusEvent()
} }
def cool() { def cool() {
log.debug "cool" log.debug "cool"
generateModeEvent("cool") def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"cool")) if (parent.setMode (this,"cool", deviceId))
generateModeEvent("cool") generateModeEvent("cool")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
generateModeEvent(currentMode) // reset the tile back generateModeEvent(currentMode) // reset the tile back
} }
generateSetpointEvent() generateSetpointEvent()
generateStatusEvent() generateStatusEvent()
} }
def auto() { def auto() {
log.debug "auto" log.debug "auto"
generateModeEvent("auto") def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"auto")) if (parent.setMode (this,"auto", deviceId))
generateModeEvent("auto") generateModeEvent("auto")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
generateModeEvent(currentMode) // reset the tile back generateModeEvent(currentMode) // reset the tile back
} }
generateSetpointEvent() generateSetpointEvent()
generateStatusEvent() generateStatusEvent()
} }
def fanOn() { def fanOn() {
log.debug "fanOn" log.debug "fanOn"
parent.setFanMode (this,"on") // parent.setFanMode (this,"on")
} }
def fanAuto() { def fanAuto() {
log.debug "fanAuto" log.debug "fanAuto"
parent.setFanMode (this,"auto") // parent.setFanMode (this,"auto")
} }
def fanCirculate() { def fanCirculate() {
log.debug "fanCirculate" log.debug "fanCirculate"
parent.setFanMode (this,"circulate") // parent.setFanMode (this,"circulate")
} }
def fanOff() { def fanOff() {
log.debug "fanOff" log.debug "fanOff"
parent.setFanMode (this,"off") // parent.setFanMode (this,"off")
} }
def generateSetpointEvent() { def generateSetpointEvent() {
log.debug "Generate SetPoint Event" log.debug "Generate SetPoint Event"
def mode = device.currentValue("thermostatMode") def mode = device.currentValue("thermostatMode")
log.debug "Current Mode = ${mode}" log.debug "Current Mode = ${mode}"
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger() def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
log.debug "Heating Setpoint = ${heatingSetpoint}" log.debug "Heating Setpoint = ${heatingSetpoint}"
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger() def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
log.debug "Cooling Setpoint = ${coolingSetpoint}" log.debug "Cooling Setpoint = ${coolingSetpoint}"
if (mode == "heat") { if (mode == "heat") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°") sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString())
} }
else if (mode == "cool") { else if (mode == "cool") {
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString()+"°") sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString())
} else if (mode == "auto") { } else if (mode == "auto") {
sendEvent("name":"thermostatSetpoint", "value":"Auto") sendEvent("name":"thermostatSetpoint", "value":"Auto")
} else if (mode == "off") { } else if (mode == "off") {
sendEvent("name":"thermostatSetpoint", "value":"Off") sendEvent("name":"thermostatSetpoint", "value":"Off")
} else if (mode == "emergencyHeat") { } else if (mode == "emergencyHeat") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°") sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString())
} }
} }
void raiseSetpoint() { void raiseSetpoint() {
log.debug "Raise SetPoint"
def mode = device.currentValue("thermostatMode") def mode = device.currentValue("thermostatMode")
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger() def targetvalue
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
log.debug "Current Mode = ${mode}" if (mode == "off" || mode == "auto") {
log.warn "this mode: $mode does not allow raiseSetpoint"
} else {
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
def thermostatSetpoint = device.currentValue("thermostatSetpoint").toInteger()
log.debug "raiseSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
if (mode == "heat") { if (device.latestState('thermostatSetpoint')) {
targetvalue = device.latestState('thermostatSetpoint').value as Integer
} else {
targetvalue = 0
}
targetvalue = targetvalue + 1
heatingSetpoint++ if (mode == "heat" && targetvalue > 79) {
targetvalue = 79
} else if (mode == "cool" && targetvalue > 92) {
targetvalue = 92
}
if (heatingSetpoint > 99) sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
heatingSetpoint = 99 log.info "In mode $mode raiseSetpoint() to $targetvalue"
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°")
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint)
parent.setHold (this, heatingSetpoint, coolingSetpoint)
log.debug "New Heating Setpoint = ${heatingSetpoint}"
}
else if (mode == "cool") {
coolingSetpoint++
if (coolingSetpoint > 99)
coolingSetpoint = 99
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString()+"°")
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
parent.setHold (this, heatingSetpoint, coolingSetpoint)
log.debug "New Cooling Setpoint = ${coolingSetpoint}"
}
generateStatusEvent()
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
}
} }
//called by tile when user hit raise temperature button on UI
void lowerSetpoint() { void lowerSetpoint() {
log.debug "Lower SetPoint" def mode = device.currentValue("thermostatMode")
def targetvalue
if (mode == "off" || mode == "auto") {
log.warn "this mode: $mode does not allow lowerSetpoint"
} else {
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
def thermostatSetpoint = device.currentValue("thermostatSetpoint").toInteger()
log.debug "lowerSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
if (device.latestState('thermostatSetpoint')) {
targetvalue = device.latestState('thermostatSetpoint').value as Integer
} else {
targetvalue = 0
}
targetvalue = targetvalue - 1
if (mode == "heat" && targetvalue.toInteger() < 45) {
targetvalue = 45
} else if (mode == "cool" && targetvalue.toInteger() < 65) {
targetvalue = 65
}
sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
log.info "In mode $mode lowerSetpoint() to $targetvalue"
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
}
}
//called by raiseSetpoint() and lowerSetpoint()
void alterSetpoint(temp) {
def mode = device.currentValue("thermostatMode") def mode = device.currentValue("thermostatMode")
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger() def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger() def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
def deviceId = device.deviceNetworkId.split(/\./).last()
log.debug "Current Mode = ${mode}, Current Heating Setpoint = ${heatingSetpoint}, Current Cooling Setpoint = ${coolingSetpoint}" def targetHeatingSetpoint
def targetCoolingSetpoint
if (mode == "heat" || mode == "emergencyHeat") { //step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat"){
if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = coolingSetpoint
}
} else if (mode == "cool") {
//enforce limits before sending request to cloud
if (temp.value < heatingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = heatingSetpoint
targetCoolingSetpoint = temp.value
}
}
heatingSetpoint-- log.debug "alterSetpoint >> in mode ${mode} trying to change heatingSetpoint to ${targetHeatingSetpoint} " +
"coolingSetpoint to ${targetCoolingSetpoint}"
if (heatingSetpoint < 32) //step2: call parent.setHold to send http request to 3rd party cloud
heatingSetpoint = 32 if (parent.setHold(this, targetHeatingSetpoint, targetCoolingSetpoint, deviceId)) {
sendEvent("name": "thermostatSetpoint", "value": temp.value.toString(), displayed: false)
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°") sendEvent("name": "heatingSetpoint", "value": targetHeatingSetpoint)
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint) sendEvent("name": "coolingSetpoint", "value": targetCoolingSetpoint)
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
parent.setHold (this, heatingSetpoint, coolingSetpoint) } else {
log.error "Error alterSetpoint()"
log.debug "New Heating Setpoint = ${heatingSetpoint}" if (mode == "heat"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} } else if (mode == "cool") {
else if (mode == "cool") { sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
}
coolingSetpoint-- }
generateStatusEvent()
if (coolingSetpoint < 32)
coolingSetpoint = 32
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString()+"°")
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
parent.setHold (this, heatingSetpoint, coolingSetpoint)
log.debug "New Cooling Setpoint = ${coolingSetpoint}"
}
generateStatusEvent()
} }
def generateStatusEvent() { def generateStatusEvent() {
def mode = device.currentValue("thermostatMode") def mode = device.currentValue("thermostatMode")
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger() def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger() def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
def temperature = device.currentValue("temperature").toInteger() def temperature = device.currentValue("temperature").toInteger()
def statusText def statusText
log.debug "Generate Status Event for Mode = ${mode}" log.debug "Generate Status Event for Mode = ${mode}"
log.debug "Temperature = ${temperature}" log.debug "Temperature = ${temperature}"
log.debug "Heating set point = ${heatingSetpoint}" log.debug "Heating set point = ${heatingSetpoint}"
log.debug "Cooling set point = ${coolingSetpoint}" log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}" log.debug "HVAC Mode = ${mode}"
if (mode == "heat") { if (mode == "heat") {
if (temperature >= heatingSetpoint) if (temperature >= heatingSetpoint)
statusText = "Right Now: Idle" statusText = "Right Now: Idle"
else else
statusText = "Heating to ${heatingSetpoint}° F" statusText = "Heating to ${heatingSetpoint}° F"
} else if (mode == "cool") { } else if (mode == "cool") {
if (temperature <= coolingSetpoint) if (temperature <= coolingSetpoint)
statusText = "Right Now: Idle" statusText = "Right Now: Idle"
else else
statusText = "Cooling to ${coolingSetpoint}° F" statusText = "Cooling to ${coolingSetpoint}° F"
} else if (mode == "auto") { } else if (mode == "auto") {
statusText = "Right Now: Auto" statusText = "Right Now: Auto"
} else if (mode == "off") { } else if (mode == "off") {
statusText = "Right Now: Off" statusText = "Right Now: Off"
} else if (mode == "emergencyHeat") { } else if (mode == "emergencyHeat") {
statusText = "Emergency Heat" statusText = "Emergency Heat"
} else { } else {
statusText = "?" statusText = "?"
} }
log.debug "Generate Status Event = ${statusText}" log.debug "Generate Status Event = ${statusText}"
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true, isStateChange: true) sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true)
} }

File diff suppressed because it is too large Load Diff