From 771926c33730b7490ce9b06f184910ca37bfc986 Mon Sep 17 00:00:00 2001 From: marstorp Date: Wed, 5 Jul 2017 16:50:30 -0700 Subject: [PATCH] ICP-1148 Support Thermostat Dynamic data Adding support for dynamic thermostat and fan modes to TCC DTH. Also replaced capability "Polling" with "Refresh" and runEvery5Minutes("refresh") as polling capability is unreliable. Also removed capability "Relative Humidity Measurement" as Honeywell Z-Wave Thermostat (YTH8320ZW1007/U) doesn't support humidity. --- .../zwave-thermostat.groovy | 96 +++++++++---------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy b/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy index 743ab0f..5caf602 100644 --- a/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy +++ b/devicetypes/smartthings/zwave-thermostat.src/zwave-thermostat.groovy @@ -15,10 +15,9 @@ metadata { definition (name: "Z-Wave Thermostat", namespace: "smartthings", author: "SmartThings") { capability "Actuator" capability "Temperature Measurement" - capability "Relative Humidity Measurement" capability "Thermostat" capability "Configuration" - capability "Polling" + capability "Refresh" capability "Sensor" capability "Health Check" @@ -117,7 +116,7 @@ metadata { state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff" } standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") { - state "default", action:"polling.poll", icon:"st.secondary.refresh" + state "default", action:"refresh.refresh", icon:"st.secondary.refresh" } main "temperature" details(["temperature", "mode", "fanMode", "heatSliderControl", "heatingSetpoint", "coolSliderControl", "coolingSetpoint", "refresh"]) @@ -125,13 +124,20 @@ metadata { } def installed(){ - // Device-Watch simply pings if no device events received for 32min(checkInterval) - sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + sendHubCommand(new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format())) + initialize() } def updated(){ + initialize() +} + +def initialize() { // Device-Watch simply pings if no device events received for 32min(checkInterval) sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + unschedule() + runEvery5Minutes("refresh") + refresh() } def parse(String description) @@ -149,6 +155,7 @@ def parse(String description) ] if (map.name == "thermostatMode") { state.lastTriedMode = map.value + map.data = [supportedThermostatModes:state.supportedThermostatModes] if (map.value == "cool") { map2.value = device.latestValue("coolingSetpoint") log.info "THERMOSTAT, latest cooling setpoint = ${map2.value}" @@ -172,6 +179,7 @@ def parse(String description) } } else if (map.name == "thermostatFanMode" && map.isStateChange) { state.lastTriedFanMode = map.value + map.data = [supportedThermostatFanModes: state.supportedThermostatFanModes] } log.debug "Parse returned $result" result @@ -305,26 +313,26 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanMod } def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) { - def supportedModes = "" - if(cmd.off) { supportedModes += "off " } - if(cmd.heat) { supportedModes += "heat " } - if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergency heat " } - if(cmd.cool) { supportedModes += "cool " } - if(cmd.auto) { supportedModes += "auto " } + def supportedModes = [] + if(cmd.off) { supportedModes << "off" } + if(cmd.heat) { supportedModes << "heat" } + if(cmd.cool) { supportedModes << "cool" } + if(cmd.auto) { supportedModes << "auto" } + if(cmd.auxiliaryemergencyHeat) { supportedModes << "emergency heat" } - state.supportedModes = supportedModes - // No events to be generated, return empty map + state.supportedThermostatModes = supportedModes + sendEvent(name: "supportedThermostatModes", value: supportedModes, displayed: false) return [:] } def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) { - def supportedFanModes = "" - if(cmd.auto) { supportedFanModes += "auto " } // "fanAuto " - if(cmd.low) { supportedFanModes += "on " } // "fanOn" - if(cmd.circulation) { supportedFanModes += "circulate " } // "fanCirculate" + def supportedFanModes = [] + if(cmd.auto) { supportedFanModes << "auto" } // "fanAuto " + if(cmd.circulation) { supportedFanModes << "circulate" } // "fanCirculate" + if(cmd.low) { supportedFanModes << "on" } // "fanOn" - state.supportedFanModes = supportedFanModes - // No events to be generated, return empty map + state.supportedThermostatFanModes = supportedFanModes + sendEvent(name: "supportedThermostatFanModes", value: supportedFanModes, displayed: false) return [:] } @@ -337,15 +345,17 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) { } // Command Implementations -def poll() { - delayBetween([ - zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature - zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(), - zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(), - zwave.thermostatModeV2.thermostatModeGet().format(), - zwave.thermostatFanModeV3.thermostatFanModeGet().format(), - zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format() - ], 2300) +def refresh() { + def cmds = [] + cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format()) + cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format()) + cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format()) + cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format()) + cmds << new physicalgraph.device.HubAction(zwave.sensorMultilevelV2.sensorMultilevelGet().format()) // current temperature + cmds << new physicalgraph.device.HubAction(zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()) + cmds << new physicalgraph.device.HubAction(zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()) + cmds << new physicalgraph.device.HubAction(zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format()) + sendHubCommand(cmds) } def quickSetHeat(degrees) { @@ -416,28 +426,14 @@ def ping() { poll() } -def configure() { - delayBetween([ - zwave.thermostatModeV2.thermostatModeSupportedGet().format(), - zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(), - zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(), - zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature - zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(), - zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(), - zwave.thermostatModeV2.thermostatModeGet().format(), - zwave.thermostatFanModeV3.thermostatFanModeGet().format(), - zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format() - ], 2300) -} - def modes() { - ["off", "heat", "cool", "auto", "emergency heat"] + return state.supportedThermostatModes } def switchMode() { def currentMode = device.currentState("thermostatMode")?.value - def lastTriedMode = state.lastTriedMode ?: currentMode ?: "off" - def supportedModes = getDataByName("supportedModes") + def lastTriedMode = state.lastTriedMode ?: currentMode ?: ["off"] + def supportedModes = getDataByName("supportedThermostatModes") def modeOrder = modes() def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] } def nextMode = next(lastTriedMode) @@ -454,7 +450,7 @@ def switchMode() { } def switchToMode(nextMode) { - def supportedModes = getDataByName("supportedModes") + def supportedModes = getDataByName("supportedThermostatModes") if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported" if (nextMode in modes()) { state.lastTriedMode = nextMode @@ -466,9 +462,9 @@ def switchToMode(nextMode) { def switchFanMode() { def currentMode = device.currentState("thermostatFanMode")?.value - def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: "off" - def supportedModes = getDataByName("supportedFanModes") ?: "auto on" // "fanAuto fanOn" - def modeOrder = ["auto", "circulate", "on"] // "fanAuto", "fanCirculate", "fanOn" + def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: ["off"] + def supportedModes = getDataByName("supportedThermostatFanModes") ?: ["auto", "on"] + def modeOrder = state.supportedThermostatFanModes def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] } def nextMode = next(lastTriedMode) while (!supportedModes?.contains(nextMode) && nextMode != "auto") { // "fanAuto" @@ -478,7 +474,7 @@ def switchFanMode() { } def switchToFanMode(nextMode) { - def supportedFanModes = getDataByName("supportedFanModes") + def supportedFanModes = getDataByName("supportedThermostatFanModes") if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported" def returnCommand