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

@@ -22,31 +22,31 @@ metadata {
capability "Polling" capability "Polling"
capability "Sensor" capability "Sensor"
capability "Refresh" capability "Refresh"
command "generateEvent" command "generateEvent"
command "raiseSetpoint" command "raiseSetpoint"
command "lowerSetpoint" command "lowerSetpoint"
command "resumeProgram" command "resumeProgram"
command "switchMode" command "switchMode"
attribute "thermostatSetpoint","number" attribute "thermostatSetpoint","number"
attribute "thermostatStatus","string" attribute "thermostatStatus","string"
} }
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") {
@@ -54,27 +54,27 @@ metadata {
state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat" state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat"
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"
state "on", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "off" state "on", label:'Fan: ${currentValue}', action:"switchFanMode", nextState: "off"
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,22 +91,23 @@ 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"])
} }
} }
/* /*
preferences { preferences {
input "highTemperature", "number", title: "Auto Mode High Temperature:", defaultValue: 80 input "highTemperature", "number", title: "Auto Mode High Temperature:", defaultValue: 80
input "lowTemperature", "number", title: "Auto Mode Low Temperature:", defaultValue: 70 input "lowTemperature", "number", title: "Auto Mode Low Temperature:", defaultValue: 70
input name: "holdType", type: "enum", title: "Hold Type", description: "When changing temperature, use Temporary or Permanent hold", required: true, options:["Temporary", "Permanent"] input name: "holdType", type: "enum", title: "Hold Type", description: "When changing temperature, use Temporary or Permanent hold", required: true, options:["Temporary", "Permanent"]
} }
*/ */
@@ -114,195 +115,190 @@ metadata {
def parse(String description) { def parse(String description) {
log.debug "Parsing '${description}'" log.debug "Parsing '${description}'"
// TODO: handle '' attribute // TODO: handle '' attribute
} }
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") {
isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange
sendEvent(
name: name,
value: value,
unit: "F",
linkText: linkText,
descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name,
isStateChange: isChange,
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 ()
generateStatusEvent ()
}
}
void generateEvent(Map results) if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint") {
{ def sendValue = value? convertTemperatureIfNeeded(value.toDouble(), "F", 1): value //API return temperature value in F
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()) 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( sendEvent(
name: name, name: name,
value: value.toString(), value: value.toString(),
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)
} }
} }
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"()
@@ -376,300 +372,320 @@ def getDataByName(String name) {
def setThermostatMode(String value) { def setThermostatMode(String value) {
log.debug "setThermostatMode({$value})" log.debug "setThermostatMode({$value})"
} }
def setThermostatFanMode(String value) { def setThermostatFanMode(String value) {
log.debug "setThermostatFanMode({$value})" log.debug "setThermostatFanMode({$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") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°")
}
else if (mode == "cool") {
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString()+"°")
} else if (mode == "auto") { if (mode == "heat") {
sendEvent("name":"thermostatSetpoint", "value":"Auto")
} else if (mode == "off") { sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString())
sendEvent("name":"thermostatSetpoint", "value":"Off")
} else if (mode == "emergencyHeat") { }
else if (mode == "cool") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°")
} sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString())
} else if (mode == "auto") {
sendEvent("name":"thermostatSetpoint", "value":"Auto")
} else if (mode == "off") {
sendEvent("name":"thermostatSetpoint", "value":"Off")
} else if (mode == "emergencyHeat") {
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 == "heat") {
heatingSetpoint++
if (heatingSetpoint > 99)
heatingSetpoint = 99
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()
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 (device.latestState('thermostatSetpoint')) {
targetvalue = device.latestState('thermostatSetpoint').value as Integer
} else {
targetvalue = 0
}
targetvalue = targetvalue + 1
if (mode == "heat" && targetvalue > 79) {
targetvalue = 79
} else if (mode == "cool" && targetvalue > 92) {
targetvalue = 92
}
sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
log.info "In mode $mode raiseSetpoint() to $targetvalue"
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 mode = device.currentValue("thermostatMode")
def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger() def targetvalue
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
log.debug "Current Mode = ${mode}, Current Heating Setpoint = ${heatingSetpoint}, Current Cooling Setpoint = ${coolingSetpoint}"
if (mode == "heat" || mode == "emergencyHeat") {
heatingSetpoint--
if (heatingSetpoint < 32)
heatingSetpoint = 32
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint.toString()+"°") if (mode == "off" || mode == "auto") {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint) log.warn "this mode: $mode does not allow lowerSetpoint"
} else {
parent.setHold (this, heatingSetpoint, coolingSetpoint) def heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
log.debug "New Heating Setpoint = ${heatingSetpoint}" def thermostatSetpoint = device.currentValue("thermostatSetpoint").toInteger()
log.debug "lowerSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
} if (device.latestState('thermostatSetpoint')) {
else if (mode == "cool") { targetvalue = device.latestState('thermostatSetpoint').value as Integer
} else {
coolingSetpoint-- targetvalue = 0
}
if (coolingSetpoint < 32) targetvalue = targetvalue - 1
coolingSetpoint = 32
if (mode == "heat" && targetvalue.toInteger() < 45) {
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint.toString()+"°") targetvalue = 45
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint) } else if (mode == "cool" && targetvalue.toInteger() < 65) {
targetvalue = 65
parent.setHold (this, heatingSetpoint, coolingSetpoint) }
log.debug "New Cooling Setpoint = ${coolingSetpoint}" sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
log.info "In mode $mode lowerSetpoint() to $targetvalue"
}
generateStatusEvent() 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 heatingSetpoint = device.currentValue("heatingSetpoint").toInteger()
def coolingSetpoint = device.currentValue("coolingSetpoint").toInteger()
def deviceId = device.deviceNetworkId.split(/\./).last()
def targetHeatingSetpoint
def targetCoolingSetpoint
//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
}
}
log.debug "alterSetpoint >> in mode ${mode} trying to change heatingSetpoint to ${targetHeatingSetpoint} " +
"coolingSetpoint to ${targetCoolingSetpoint}"
//step2: call parent.setHold to send http request to 3rd party cloud
if (parent.setHold(this, targetHeatingSetpoint, targetCoolingSetpoint, deviceId)) {
sendEvent("name": "thermostatSetpoint", "value": temp.value.toString(), displayed: false)
sendEvent("name": "heatingSetpoint", "value": targetHeatingSetpoint)
sendEvent("name": "coolingSetpoint", "value": targetCoolingSetpoint)
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
} else {
log.error "Error alterSetpoint()"
if (mode == "heat"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} else if (mode == "cool") {
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
}
}
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
log.debug "Generate Status Event for Mode = ${mode}"
log.debug "Temperature = ${temperature}"
log.debug "Heating set point = ${heatingSetpoint}"
log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}"
if (mode == "heat") {
if (temperature >= heatingSetpoint)
statusText = "Right Now: Idle"
else
statusText = "Heating to ${heatingSetpoint}° F"
} else if (mode == "cool") {
if (temperature <= coolingSetpoint)
statusText = "Right Now: Idle"
else
statusText = "Cooling to ${coolingSetpoint}° F"
} else if (mode == "auto") {
statusText = "Right Now: Auto"
} else if (mode == "off") {
statusText = "Right Now: Off"
} else if (mode == "emergencyHeat") {
statusText = "Emergency Heat"
} else {
statusText = "?"
}
log.debug "Generate Status Event = ${statusText}"
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true, isStateChange: true)
}
def statusText
log.debug "Generate Status Event for Mode = ${mode}"
log.debug "Temperature = ${temperature}"
log.debug "Heating set point = ${heatingSetpoint}"
log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}"
if (mode == "heat") {
if (temperature >= heatingSetpoint)
statusText = "Right Now: Idle"
else
statusText = "Heating to ${heatingSetpoint}° F"
} else if (mode == "cool") {
if (temperature <= coolingSetpoint)
statusText = "Right Now: Idle"
else
statusText = "Cooling to ${coolingSetpoint}° F"
} else if (mode == "auto") {
statusText = "Right Now: Auto"
} else if (mode == "off") {
statusText = "Right Now: Off"
} else if (mode == "emergencyHeat") {
statusText = "Emergency Heat"
} else {
statusText = "?"
}
log.debug "Generate Status Event = ${statusText}"
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true)
}

File diff suppressed because it is too large Load Diff