Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Better-Thermostat.device.groovy
- *
- * Variation of TWACK's "Zwave-Thermostat"
- * My Trane XL624 had conflicting humidity readings, so I modified TWACK's code to fix it.
- * I also integrated code by jwaymire
- *
- * Device type removes the sliders and replaces them with incremental
- * up and down buttons on each side of the heating and cooling setpoints.
- *
- * To use you must have IDE access on your account. Add a new device
- * type and add the custom commands:
- * heatLevelUp
- * heatLevelDown
- * coolLevelUp
- * coolLevelDown
- * switchMode
- * switchFanMode
- * Replace the starter code with this code and save the file. Go into
- * "My devices" and select the thermostat you want to change. Select "Edit"
- * and then change the "Type" to use this device type.
- *
- * Happy Hacking!
- *
- * twack@wackware.net
- * 20140209
- *
- */
- metadata {
- // Automatically generated. Make future change here.
- definition (name: "Better Thermostat - Trane XL624", author: "nick@nickdaria.com") {
- capability "Temperature Measurement"
- capability "Refresh"
- capability "Thermostat"
- capability "Configuration"
- capability "Polling"
- command "heatLevelUp"
- command "heatLevelDown"
- command "coolLevelUp"
- command "coolLevelDown"
- command "switchMode"
- command "switchFanMode"
- }
- // simulator metadata
- simulator {
- status "off" : "command: 4003, payload: 00"
- status "heat" : "command: 4003, payload: 01"
- status "cool" : "command: 4003, payload: 02"
- status "auto" : "command: 4003, payload: 03"
- status "emergencyHeat" : "command: 4003, payload: 04"
- status "fanAuto" : "command: 4403, payload: 00"
- status "fanOn" : "command: 4403, payload: 01"
- status "fanCirculate" : "command: 4403, payload: 06"
- status "heat 60" : "command: 4303, payload: 01 01 3C"
- status "heat 68" : "command: 4303, payload: 01 01 44"
- status "heat 72" : "command: 4303, payload: 01 01 48"
- status "cool 72" : "command: 4303, payload: 02 01 48"
- status "cool 76" : "command: 4303, payload: 02 01 4C"
- status "cool 80" : "command: 4303, payload: 02 01 50"
- status "temp 58" : "command: 3105, payload: 01 22 02 44"
- status "temp 62" : "command: 3105, payload: 01 22 02 6C"
- status "temp 70" : "command: 3105, payload: 01 22 02 BC"
- status "temp 74" : "command: 3105, payload: 01 22 02 E4"
- status "temp 78" : "command: 3105, payload: 01 22 03 0C"
- status "temp 82" : "command: 3105, payload: 01 22 03 34"
- status "idle" : "command: 4203, payload: 00"
- status "heating" : "command: 4203, payload: 01"
- status "cooling" : "command: 4203, payload: 02"
- status "fan only" : "command: 4203, payload: 03"
- status "pending heat" : "command: 4203, payload: 04"
- status "pending cool" : "command: 4203, payload: 05"
- status "vent economizer": "command: 4203, payload: 06"
- // reply messages
- reply "2502": "command: 2503, payload: FF"
- }
- 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("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
- state "off", label:'', action:"switchMode", icon:"st.thermostat.heating-cooling-off"
- state "heat", label:'', action:"switchMode", icon:"st.thermostat.heat"
- state "emergencyHeat", label:'', action:"switchMode", icon:"st.thermostat.emergency-heat"
- state "cool", label:'', action:"switchMode", icon:"st.thermostat.cool"
- state "auto", label:'', action:"switchMode", icon:"st.thermostat.auto"
- }
- standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
- state "fanAuto", label:'', action:"switchFanMode", icon:"st.thermostat.fan-auto"
- state "fanOn", label:'', action:"switchFanMode", icon:"st.thermostat.fan-on"
- state "fanCirculate", label:' ', action:"switchFanMode", icon:"st.thermostat.fan-circulate"
- }
- valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
- state "heat", label:'${currentValue}° heat', unit:"F", backgroundColor:"#ffffff"
- }
- valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
- state "cool", label:'${currentValue}° cool', unit:"F", backgroundColor:"#ffffff"
- }
- standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
- state "default", action:"polling.poll", icon:"st.secondary.refresh"
- }
- standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
- state "configure", label:' ', action:"configuration.configure", icon:"st.secondary.configure"
- }
- standardTile("heatLevelUp", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false, decoration: "flat") {
- state "heatLevelUp", label:' ', action:"heatLevelUp", icon:"st.thermostat.thermostat-up"
- }
- standardTile("heatLevelDown", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false, decoration: "flat") {
- state "heatLevelDown", label:' ', action:"heatLevelDown", icon:"st.thermostat.thermostat-down"
- }
- standardTile("coolLevelUp", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false, decoration: "flat") {
- state "coolLevelUp", label:' ', action:"coolLevelUp", icon:"st.thermostat.thermostat-up"
- }
- standardTile("coolLevelDown", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false, decoration: "flat") {
- state "coolLevelDown", label:' ', action:"coolLevelDown", icon:"st.thermostat.thermostat-down"
- }
- main "temperature"
- details(["temperature", "mode", "fanMode", "heatLevelDown", "heatingSetpoint", "heatLevelUp", "coolLevelDown", "coolingSetpoint", "coolLevelUp", "refresh", "configure"])
- }
- }
- def coolLevelUp(){
- int nextLevel = device.currentValue("coolingSetpoint") + 1
- if( nextLevel > 99){
- nextLevel = 99
- }
- log.debug "Setting cool set point up to: ${nextLevel}"
- setCoolingSetpoint(nextLevel)
- }
- def coolLevelDown(){
- int nextLevel = device.currentValue("coolingSetpoint") - 1
- if( nextLevel < 50){
- nextLevel = 50
- }
- log.debug "Setting cool set point down to: ${nextLevel}"
- setCoolingSetpoint(nextLevel)
- }
- def heatLevelUp(){
- int nextLevel = device.currentValue("heatingSetpoint") + 1
- if( nextLevel > 90){
- nextLevel = 90
- }
- log.debug "Setting heat set point up to: ${nextLevel}"
- setHeatingSetpoint(nextLevel)
- }
- def heatLevelDown(){
- int nextLevel = device.currentValue("heatingSetpoint") - 1
- if( nextLevel < 40){
- nextLevel = 40
- }
- log.debug "Setting heat set point down to: ${nextLevel}"
- setHeatingSetpoint(nextLevel)
- }
- def parse(String description)
- {
- def map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31: 3])))
- if (!map) {
- return null
- }
- def result = [map]
- if (map.isStateChange && map.name in ["heatingSetpoint","coolingSetpoint","thermostatMode"]) {
- def map2 = [
- name: "thermostatSetpoint",
- unit: "F"
- ]
- if (map.name == "thermostatMode") {
- updateState("lastTriedMode", map.value)
- if (map.value == "cool") {
- map2.value = device.latestValue("coolingSetpoint")
- log.info "THERMOSTAT, latest cooling setpoint = ${map2.value}"
- }
- else {
- map2.value = device.latestValue("heatingSetpoint")
- log.info "THERMOSTAT, latest heating setpoint = ${map2.value}"
- }
- }
- else {
- def mode = device.latestValue("thermostatMode")
- log.info "THERMOSTAT, latest mode = ${mode}"
- if ((map.name == "heatingSetpoint" && mode == "heat") || (map.name == "coolingSetpoint" && mode == "cool")) {
- map2.value = map.value
- map2.unit = map.unit
- }
- }
- if (map2.value != null) {
- log.debug "THERMOSTAT, adding setpoint event: $map"
- result << createEvent(map2)
- }
- } else if (map.name == "thermostatFanMode" && map.isStateChange) {
- updateState("lastTriedFanMode", map.value)
- }
- log.debug "Parse returned $result"
- result
- }
- // Event Generation
- def zwaveEvent(physicalgraph.zwave.commands.thermostatsetpointv2.ThermostatSetpointReport cmd)
- {
- def map = [:]
- map.value = cmd.scaledValue.toString()
- map.unit = cmd.scale == 1 ? "F" : "C"
- map.displayed = false
- switch (cmd.setpointType) {
- case 1:
- map.name = "heatingSetpoint"
- break;
- case 2:
- map.name = "coolingSetpoint"
- break;
- default:
- return [:]
- }
- // So we can respond with same format
- state.size = cmd.size
- state.scale = cmd.scale
- state.precision = cmd.precision
- map
- }
- def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv3.SensorMultilevelReport cmd)
- {
- log.debug "SensorMultilevelReport ${cmd}"
- def map = [:]
- switch (cmd.sensorType) {
- case 1:
- // temperature
- map.value = cmd.scaledSensorValue.toString()
- map.unit = cmd.scale == 1 ? "F" : "C"
- map.name = "temperature"
- break;
- case 5:
- // humidity
- map.value = cmd.scaledSensorValue.toInteger().toString()
- map.unit = "%"
- map.name = "humidity"
- break;
- }
- map
- }
- def zwaveEvent(physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport cmd)
- {
- def map = [:]
- switch (cmd.operatingState) {
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_IDLE:
- map.value = "idle"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_HEATING:
- map.value = "heating"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_COOLING:
- map.value = "cooling"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_FAN_ONLY:
- map.value = "fan only"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_HEAT:
- map.value = "pending heat"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_COOL:
- map.value = "pending cool"
- break
- case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_VENT_ECONOMIZER:
- map.value = "vent economizer"
- break
- }
- map.name = "thermostatOperatingState"
- map
- }
- def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport cmd) {
- def map = [:]
- switch (cmd.mode) {
- case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_OFF:
- map.value = "off"
- break
- case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_HEAT:
- map.value = "heat"
- break
- case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUXILIARY_HEAT:
- map.value = "emergencyHeat"
- break
- case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_COOL:
- map.value = "cool"
- break
- case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO:
- map.value = "auto"
- break
- }
- map.name = "thermostatMode"
- map
- }
- def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport cmd) {
- def map = [:]
- switch (cmd.fanMode) {
- case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_LOW:
- map.value = "fanAuto"
- break
- case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_LOW:
- map.value = "fanOn"
- break
- case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION:
- map.value = "fanCirculate"
- break
- }
- map.name = "thermostatFanMode"
- map.displayed = false
- map
- }
- def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) {
- def supportedModes = ""
- if(cmd.off) { supportedModes += "off " }
- if(cmd.heat) { supportedModes += "heat " }
- if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergencyHeat " }
- if(cmd.cool) { supportedModes += "cool " }
- if(cmd.auto) { supportedModes += "auto " }
- updateState("supportedModes", supportedModes)
- }
- def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
- def supportedFanModes = ""
- if(cmd.auto) { supportedFanModes += "fanAuto " }
- if(cmd.low) { supportedFanModes += "fanOn " }
- if(cmd.circulation) { supportedFanModes += "fanCirculate " }
- updateState("supportedFanModes", supportedFanModes)
- }
- def updateState(String name, String value) {
- state[name] = value
- device.updateDataValue(name, value)
- }
- def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
- log.debug "Zwave event received: $cmd"
- }
- def zwaveEvent(physicalgraph.zwave.Command cmd) {
- log.warn "Unexpected 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 setHeatingSetpoint(degreesF) {
- setHeatingSetpoint(degreesF.toDouble())
- }
- def setHeatingSetpoint(Double degreesF) {
- def p = (state.precision == null) ? 1 : state.precision
- delayBetween([
- zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 1, scale: 1, precision: p, scaledValue: degreesF).format(),
- zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()
- ])
- }
- def setCoolingSetpoint(degreesF) {
- setCoolingSetpoint(degreesF.toDouble())
- }
- def setCoolingSetpoint(Double degreesF) {
- def p = (state.precision == null) ? 1 : state.precision
- delayBetween([
- zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 2, scale: 1, precision: p, scaledValue: degreesF).format(),
- zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format()
- ])
- }
- def configure() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
- zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(),
- zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()
- ], 2300)
- }
- def modes() {
- ["off", "auto", "emergencyHeat", "heat", "cool"]
- }
- def switchMode() {
- def currentMode = device.currentState("thermostatMode")?.value
- def lastTriedMode = getDataByName("lastTriedMode") ?: currentMode ?: "off"
- def supportedModes = getDataByName("supportedModes")
- def modeOrder = modes()
- def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
- def nextMode = next(lastTriedMode)
- if (supportedModes?.contains(currentMode)) {
- while (!supportedModes.contains(nextMode) && nextMode != "off") {
- nextMode = next(nextMode)
- }
- }
- log.debug "Switching to mode: ${nextMode}"
- switchToMode(nextMode)
- }
- def switchToMode(nextMode) {
- def supportedModes = getDataByName("supportedModes")
- if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
- if (nextMode in modes()) {
- updateState("lastTriedMode", nextMode)
- return "$nextMode"()
- } else {
- log.debug("no mode method '$nextMode'")
- }
- }
- def switchFanMode() {
- def currentMode = device.currentState("thermostatFanMode")?.value
- def lastTriedMode = getDataByName("lastTriedFanMode") ?: currentMode ?: "off"
- def supportedModes = getDataByName("supportedFanModes") ?: "fanAuto fanOn"
- def modeOrder = ["fanAuto", "fanCirculate", "fanOn"]
- def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
- def nextMode = next(lastTriedMode)
- while (!supportedModes?.contains(nextMode) && nextMode != "fanAuto") {
- nextMode = next(nextMode)
- }
- switchToFanMode(nextMode)
- }
- def switchToFanMode(nextMode) {
- def supportedFanModes = getDataByName("supportedFanModes")
- if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
- def returnCommand
- if (nextMode == "fanAuto") {
- returnCommand = fanAuto()
- } else if (nextMode == "fanOn") {
- returnCommand = fanOn()
- } else if (nextMode == "fanCirculate") {
- returnCommand = fanCirculate()
- } else {
- log.debug("no fan mode '$nextMode'")
- }
- if(returnCommand) updateState("lastTriedFanMode", nextMode)
- returnCommand
- }
- def getDataByName(String name) {
- state[name] ?: device.getDataValue(name)
- }
- def getModeMap() { [
- "off": 0,
- "heat": 1,
- "cool": 2,
- "emergency heat": 4
- ]}
- def setThermostatMode(String value) {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[value]).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def getFanModeMap() { [
- "auto": 0,
- "on": 1,
- "circulate": 6
- ]}
- def setThermostatFanMode(String value) {
- delayBetween([
- zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[value]).format(),
- zwave.thermostatFanModeV3.thermostatFanModeGet().format()
- ])
- }
- def off() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: 0).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def heat() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: 1).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def emergencyHeat() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: 4).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def cool() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: 2).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def auto() {
- delayBetween([
- zwave.thermostatModeV2.thermostatModeSet(mode: 3).format(),
- zwave.thermostatModeV2.thermostatModeGet().format()
- ])
- }
- def fanOn() {
- delayBetween([
- zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 1).format(),
- zwave.thermostatFanModeV3.thermostatFanModeGet().format()
- ])
- }
- def fanAuto() {
- delayBetween([
- zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 0).format(),
- zwave.thermostatFanModeV3.thermostatFanModeGet().format()
- ])
- }
- def fanCirculate() {
- delayBetween([
- zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 6).format(),
- zwave.thermostatFanModeV3.thermostatFanModeGet().format()
- ])
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement