Last active
April 17, 2020 01:21
-
-
Save imnotbob/5c850b85db06a5db4b0e6b941d9f74e1 to your computer and use it in GitHub Desktop.
New zxt120 driver for Hubitat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ZXT-120 IR Sender Unit from Remotec | |
* | |
* Author: ERS from Ronald Gouldner (based on [email protected] version) | |
* | |
* Updates merged from Tim Owen for learning; resume commands | |
* | |
* Date: 2020-3-25 | |
* Code: https://github.com/gouldner/ST-Devices/src/ZXT-120 | |
* | |
* Copyright (C) 2016 | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of this | |
* software and associated documentation files (the "Software"), to deal in the Software | |
* without restriction, including without limitation the rights to use, copy, modify, | |
* merge, publish, distribute, sublicense, and - or sell copies of the Software, and to | |
* permit persons to whom the Software is furnished to do so, subject to the following | |
* conditions: The above copyright notice and this permission notice shall be included | |
* in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
def devVer() { return "1.0.2"} | |
/* | |
* The ZXT-120 does not "listen" for commands sent to the HVAC from other devics nor does it listen-receive status from the HVAC unit. | |
* It also does not report states correctly if asked for several items. On resume it is not likely to go back to the last operating state. | |
* This means if control of the HVAC unit externally the 'rememembered' state (HVAC mode, set temps) in this dth would be wrong | |
* until this dth sends new commands to the HVAC unit. Immediately after sending commands the unit should be in the requested state. | |
* | |
* KEEP THIS IN MIND WHEN DESIGNING YOUR AUTOMATIONS. IT IS A GOOD IDEA TO SEND THE SETTINGS YOU WANT and not believe previous settings will remain, | |
*,AND NOT HAVE OTHER THINGS CHANGE settings. | |
* THE ONLY BENFIT OF POLLING THIS DEVICE IS TO GET UPDATED BATTERY STATUS AND TEMPERATURE READING (SENSOR IS ON THE ZXT (not the HVAC)) | |
* | |
* command optimizations in applications using this device MUST BE avoided because of the likely hood of inaccurate readings. | |
*/ | |
preferences { | |
input("remoteCode", "number", title: "Remote Code", description: "The number of the remote to emulate") | |
input("tempOffset", "enum", title: "Temp correction offset (degrees C)?", options: ["-5","-4","-3","-2","-1","0","1","2","3","4","5"]) | |
input("onCommand", "enum", title: "Command to send when 'On' Button is Pressed?", options: ["emulate(resume)","on(resume)","cool","heat","dry"]) | |
input("learningPosition", "number", title: "Learning Position?", description: "IR Code to Store") | |
input("debugEnable", "bool", title: "Enable debug logging?") | |
} | |
metadata { | |
definition (name: "ZXT-120 IR Sender", namespace: "gouldner", author: "Ronald Gouldner", vid: "SmartThings-smartthings-Z-Wave_Thermostat") { | |
capability "Actuator" | |
capability "Temperature Measurement" | |
capability "Thermostat" | |
capability "Configuration" | |
capability "Polling" | |
capability "Sensor" | |
capability "Battery" | |
capability "Refresh" | |
capability "FanControl" | |
// Commands that this device-type exposes for controlling the ZXT-120 directly | |
// command "fanLow" | |
// command "fanMed" | |
// command "fanHigh" | |
// command "switchFanMode" | |
command "switchFanOscillate" | |
command "swingModeOn" | |
command "swingModeOff" | |
command "on" | |
command "off" | |
//commands for thermostat interface | |
command "fanOnly" | |
command "eco" | |
command "dry" | |
command "setDrySetpoint", ["number"] | |
command "setAutoSetpoint", ["number"] | |
command "autoChangeover" | |
command "setLearningPosition", ["number"] | |
command "issueLearningCommand" | |
/* | |
command "levelUpDown" | |
command "levelUp" | |
command "levelDown" | |
*/ | |
attribute "swingMode", "STRING" | |
attribute "currentConfigCode", "STRING" | |
attribute "currentTempOffset", "STRING" | |
attribute "currentemitterPower", "STRING" | |
attribute "currentsurroundIR", "STRING" | |
attribute "drySetpoint", "STRING" | |
attribute "autoSetpoint", "STRING" | |
attribute "reportedCoolingSetpoint", "STRING" | |
attribute "reportedHeatingSetpoint", "STRING" | |
attribute "learningPosition", "NUMBER" | |
attribute "learningPositionTemp", "STRING" | |
// Z-Wave description of the ZXT-120 device | |
fingerprint deviceId: "0x0806" | |
fingerprint inClusters: "0x20,0x27,0x31,0x40,0x43,0x44,0x70,0x72,0x80,0x86" | |
} | |
} | |
def initialize() { | |
log.trace "initialize()" | |
} | |
def installed() { | |
log.trace "installed()" | |
String tempscale = getTemperatureScale() | |
def tz = location.timeZone | |
if(!tz || !(tempscale == "F" || tempscale == "C")) { | |
log.warn "Timezone (${tz}) or Temperature Scale (${tempscale}) not set" | |
} | |
// set some dummy values, until someone sends us commands | |
// the zxt does not 'read' state from the HVAC, so commands must be sent for it to reflect 'somewhat accurate' state. | |
if(tempscale=='F') { | |
sendEvent(name:"coolingSetpoint", value:80) | |
sendEvent(name:"heatingSetpoint", value:67) | |
}else{ | |
sendEvent(name:"coolingSetpoint", value:28) | |
sendEvent(name:"heatingSetpoint", value:19) | |
} | |
sendEvent(name:"thermostatFanMode", value:'auto') | |
configure() | |
} | |
def ping() { | |
log.trace "ping()" | |
poll() | |
} | |
def configure() { | |
log.trace "configure()" | |
def cmd = [ | |
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format() ] + | |
setRemoteCode() + // update the device's remote code to ensure it provides proper mode info | |
setTempOffset() + [ | |
zwave.thermostatModeV2.thermostatModeSupportedGet().format(), // Request the device's supported modes | |
zwave.thermostatFanModeV2.thermostatFanModeSupportedGet().format(), // Request the device's supported fan modes | |
] | |
cmd << zwave.configurationV1.configurationGet(parameterNumber: commandParameters["remoteCode"]).format() // remote code | |
cmd << zwave.configurationV1.configurationGet(parameterNumber: commandParameters["tempOffsetParam"]).format() // temp offset | |
cmd << zwave.configurationV1.configurationGet(parameterNumber: commandParameters["oscillateSetting"]).format() // oscillate setting | |
cmd << zwave.configurationV1.configurationGet(parameterNumber: commandParameters["emitterPowerSetting"]).format() // emitter setting | |
cmd << zwave.configurationV1.configurationGet(parameterNumber: commandParameters["surroundIRSetting"]).format() // surround IR setting | |
delayBetween(cmd, 1300) | |
} | |
def updated() { | |
log.trace "updated()" | |
Long t=now() | |
if(!state.updatedLastRanAt || t >= (Long)state.updatedLastRanAt + 2000L) { | |
state.updatedLastRanAt = t | |
state.tempUnit = getTemperatureScale() | |
unschedule() | |
/* this block will poll to auto-update the temperature reading at the zxt ever 3 mins | |
def random = new Random() | |
def random_int = random.nextInt(60) | |
def random_dint = random.nextInt(3) | |
schedule("${random_int} ${random_dint}/3 * * * ?", pollLite) | |
log.info "POLL-LITE scheduled (${random_int} ${random_dint}/3 * * * ?)" // every 3 mins | |
*/ | |
state.swVersion = devVer() | |
if(debugEnable) runIn(1800,logsOff) | |
configure() // no commands after this | |
} else { | |
log.trace "updated(): Ran within last 2 seconds - SKIPPING" | |
return null | |
} | |
} | |
void logsOff() { | |
debug "debug logging disabled..." | |
device.updateSetting("debugEnable",[value:"false",type:"bool"]) | |
} | |
/* NEEDED IF YOU UNCOMMENT auto-update | |
def pollLite() { | |
//log.info "PollLite.." | |
def tz = location.timeZone | |
def tempscale = getTemperatureScale() | |
if(!tz || !(tempscale == "F" || tempscale == "C")) { | |
log.warn "Timezone (${tz}) or Temperature Scale (${tempscale}) not set" | |
return | |
} | |
sendHubCommand(new hubitat.device.HubAction(zwave.sensorMultilevelV2.sensorMultilevelGet().format())) // current temperature | |
Date now=new Date() | |
String nowString = now.format("MMM/dd HH:mm",tz) | |
device.updateDataValue("lastPoll", nowString) | |
//sendEvent("name":"lastPoll", "value":nowString, displayed: false) | |
} | |
*/ | |
def refresh() { | |
Date now=new Date() | |
def tz = location.timeZone | |
String nowString = now.format("MMM/dd HH:mm",tz) | |
device.updateDataValue("lastPoll", nowString) | |
def commands = [] | |
commands << zwave.sensorMultilevelV2.sensorMultilevelGet().format() // current temperature | |
commands << zwave.batteryV1.batteryGet().format() // current battery level | |
// commands << zwave.thermostatModeV2.thermostatModeGet().format() // thermostat mode (seems to give back cool always?) | |
// commands << zwave.thermostatFanModeV2.thermostatFanModeGet().format() // fan speed | |
// add requests for each thermostat setpoint available on the device | |
// def supportedModes = getDataByName("supportedModes") | |
// for (Integer setpoint in [1,2,8,10]) { // these return junk values | |
// commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: setpoint).format() | |
// } | |
delayBetween(commands, standardDelay) | |
} | |
def poll() { | |
log.info "Polling" | |
refresh() // nothing after this | |
} | |
def parse(String description) | |
{ | |
//log.info "Parsing Description=$description" | |
// BasicV1, BatteryV1, ConfigurationV1, ThermostatModeV2, ThermostatOperatingStateV1(NOT SUPPORTED), ThermostatSetpointV2, ThermostatFanModeV2, SensorMultilevelV1, SWITCHALLV1 | |
//def map = createEvent(zwaveEvent(zwave.parse(description, [0x80:1, 0x70:1, 0x40:2, 0x42:1, 0x43:2, 0x44:2, 0x31:2, 0x27:1 ]))) | |
// 0X20=Basic - V1 supported | |
// 0x27=Switch All - V1 supported | |
// 0X31=Sensor Multilevel - V1 supported | |
// 0X40=Thermostat Mode - V2 supported | |
// -- 0x42=Thermostat Operating State (NOT SUPPORTED, was in original device handler) | |
// 0x43=Thermostat Setpoint - V2 supported | |
// 0x44=Thermostat Fan Mode - V2 supported | |
// 0x70=Configuration - V1 supported | |
// 0x72=Manufacturer Specific - V1 supported | |
// 0x80=Battery - V1 supported | |
// 0x86=Version - V1 supported | |
def myzwave = zwave.parse(description, [0x20:1, 0x80:1, 0x70:1, 0x72:1, 0x40:2, 0x43:2, 0x44:2, 0x31:1, 0x27:1, 0x86:1 ]) | |
def map = [] | |
def result=null | |
if(myzwave) { | |
debug "parse myzwave is ${myzwave}" | |
result=zwaveEvent(myzwave) | |
map = createEvent(result) | |
} else { | |
debug "Non-parsed event. Perhaps wrong version is being handled?: ${description}" | |
return null | |
} | |
if(!map) { | |
//log.warn "parse called generating null map....why is this possible ? description=$description map=$map myzwave=$myzwave" | |
return null | |
} | |
debug "Parsed ${description} to command ${myzwave} to result ${result.inspect()} map=${map}" | |
result = [map] | |
String mapName=(String)map.name | |
String mapVal=(String)map.value | |
if(map && map.name in ["heatingSetpoint","coolingSetpoint","drySetpoint", "autoSetpoint", "thermostatMode"]) { | |
// fill in thermstatSetpoint and OperatingState as 'estimates' | |
def map2 = [ | |
name: "thermostatSetpoint", | |
unit: getTemperatureScale(), | |
displayed: false | |
] | |
def map3 = [ | |
name: "thermostatOperatingState", | |
displayed: false | |
] | |
if(mapName == "thermostatMode") { | |
String lastTriedMode=getDataByName("lastTriedMode") | |
if(lastTriedMode!=mapVal && mapVal!="off") updateState("lastTriedMode", mapVal) | |
if(mapVal == "cool") { | |
def t0=device.latestValue("coolingSetpoint") | |
// map2.value = t0 | |
log.info "last stored cooling setpoint = ${t0}" | |
map3.value = "cooling" | |
} | |
else if(mapVal == "heat") { | |
def t0=device.latestValue("heatingSetpoint") | |
// map2.value = t0 | |
log.info "last stored heating setpoint = ${t0}" | |
map3.value = "heating" | |
} | |
else if(mapVal == "dry") { | |
def t0=device.latestValue("drySetpoint") | |
// map2.value = t0 | |
log.info "last stored dry setpoint = ${t0}" | |
map.value= "cool" | |
map3.value = "cooling" | |
} | |
else if(mapVal == "auto") { | |
def t0=device.latestValue("autoSetpoint") | |
// map2.value = t0 | |
log.info "last stored auto setpoint = ${t0}" | |
map3.value = "heating" | |
} | |
else if(mapVal == "off") { | |
map3.value = "idle" | |
} | |
else if(mapVal == "fanOnly") { | |
map.value= "off" | |
map3.value = "fan only" | |
sendEvent(name:"thermostatFanMode", value: "on") | |
} | |
} else { | |
String mode = device.latestValue("thermostatMode") | |
//log.info "THERMOSTAT, latest mode = ${mode}" | |
if( (mapName == "heatingSetpoint" && mode == "heat") || | |
(mapName == "coolingSetpoint" && mode == "cool") || | |
(mapName == "drySetpoint" && mode == "dry") || | |
(mapName == "autoSetpoint" && mode == "auto") ) { | |
map2.value = mapVal | |
map2.unit = map.unit | |
} else { | |
//log.debug "mode $mode did not match $map" | |
} | |
} | |
if(map2.value != null) { | |
debug "THERMOSTAT setpoint, adding setpoint event: $map2" | |
result << createEvent(map2) | |
} | |
if(map3.value != null) { | |
debug "THERMOSTAT, adding operating state event: $map3" | |
result << createEvent(map3) | |
} | |
} else if(mapName == "thermostatFanMode") { | |
updateState("lastTriedFanMode", mapVal) | |
} | |
//log.debug "Parse returned $result" | |
result | |
} | |
def zwaveEvent(hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointReport cmd) { | |
debug "ThermostatSetpointReport...cmd=$cmd" | |
def cmdScale = cmd.scale == 1 ? "F" : "C" | |
def map = [:] | |
def convertedDegrees = convertTemperatureIfNeeded(cmd.scaledValue, cmdScale, cmd.precision) | |
String tscale=getTemperatureScale() | |
map.value = "${ tscale=='F' ? Math.round(convertedDegrees.toDouble()) : convertedDegrees.toDouble()}".toString() // Math.trunc()? | |
map.unit = tscale | |
//map.displayed = false | |
switch (cmd.setpointType) { | |
case hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1: | |
map.name = "heatingSetpoint" | |
break; | |
case hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_COOLING_1: | |
map.name = "coolingSetpoint" | |
break; | |
case hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_DRY_AIR: | |
map.name = "drySetpoint" | |
break; | |
case hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_AUTO_CHANGEOVER: | |
map.name = "autoSetpoint" | |
break; | |
default: | |
debug "Thermostat Setpoint Report for setpointType ${cmd.setpointType} = ${map.value} ${map.unit}" | |
return [:] | |
} | |
// So we can respond with same format | |
state.scale = cmd.scale | |
//state.precision = cmd.precision | |
state.precision = 1 | |
log.info "Thermostat Setpoint Report for ${map.name} = ${map.value} ${map.unit}" | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd) { | |
debug "SensorMultilevelReport...cmd=$cmd" | |
def map = [:] | |
switch (cmd.sensorType) { | |
case 1: | |
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? "F" : "C", cmd.precision) | |
map.unit = getTemperatureScale() | |
map.name = "temperature" | |
//log.info "SensorMultilevelReport temperature map.value=${map.value} ${map.unit}" | |
break; | |
default: | |
log.warn "Unknown sensorType ${cmd.sensorType} from device" // 5 is humidity in V2 and later | |
break; | |
} | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport cmd) { | |
def map = [:] | |
map.name = "thermostatFanMode" | |
def map1=[:] | |
map1.name = "speed" | |
debug "FanModeReport $cmd" | |
switch (cmd.fanMode) { | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_LOW: | |
map.value = "auto" | |
map1.value = "low" | |
break | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_HIGH: | |
map.value = "auto" | |
map1.value = "high" | |
break | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_MEDIUM: | |
map.value = "auto" | |
map1.value = "medium" | |
break | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_LOW: | |
map.value = "on" | |
map1.value = "low" | |
break | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_HIGH: | |
map.value = "on" | |
map1.value = "high" | |
break | |
case hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_MEDIUM: | |
map.value = "on" | |
map1.value = "medium" | |
break | |
/* | |
case hubitat.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION: | |
map.value = "circulate" | |
break | |
*/ | |
} | |
device.updateDataValue("actualFanMode", "${cmd.fanMode}") | |
log.info "FanModeReport ${map.value} ${cmd.fanMode}" | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport cmd) { | |
def map = [:] | |
debug "ThermostatModeReport $cmd" | |
switch (cmd.mode) { | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_OFF: | |
map.value = "off" | |
break | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_HEAT: | |
map.value = "heat" | |
break | |
/* | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUXILIARY_HEAT: | |
map.value = "emergencyHeat" | |
break | |
*/ | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_COOL: | |
map.value = "cool" | |
break | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO: | |
map.value = "auto" | |
break | |
//non standard | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_RESUME: | |
map.value = "resume" | |
break | |
// non standard - operating state | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_FAN_ONLY: | |
map.value = "fanOnly" | |
break | |
//non standard | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_DRY_AIR: | |
map.value = "dry" | |
break | |
//non standard | |
case hubitat.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO_CHANGEOVER: | |
map.value = "autoChangeover" | |
break | |
} | |
device.updateDataValue("actualMode", "${cmd.mode}") | |
map.name = "thermostatMode" | |
log.info "Thermostat Mode reported : ${map.value.toString().capitalize()} ${cmd.mode}" | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) { | |
def map = [:] | |
debug "thermostatModeSupported $cmd" | |
def val = [] | |
String supportedModes = "" | |
if(cmd.off || cmd.off==null) { supportedModes += "off "; val << "off" } | |
if(cmd.heat || cmd.heat==null) { supportedModes += "heat "; val << "heat" } | |
//if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergencyHeat " } | |
if(cmd.cool || cmd.cool==null) { supportedModes += "cool "; val << "cool" } | |
if(cmd.auto || cmd.auto==null) { supportedModes += "auto "; val << "auto" } | |
// nonstandard | |
if(cmd.fanOnly) { supportedModes += "fanOnly " } | |
if(cmd.dryAir) { supportedModes += "dry " } | |
if(cmd.resume || cmd.resume==null ) { supportedModes += "resume " } | |
//if(cmd.autoChangeover) { supportedModes += "autoChangeover " } | |
if(val) { | |
map.name = "supportedThermostatModes" | |
map.value=val | |
} | |
log.info "Supported Modes: ${supportedModes}" | |
updateState("supportedModes", supportedModes) | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeSupportedReport cmd) { | |
def map = [:] | |
debug "fanModeSupported $cmd" | |
def val=[] | |
String supportedFanModes = "" | |
if(cmd.auto) { supportedFanModes += "fanAuto "; val << "auto" } | |
if(cmd.low) { supportedFanModes += "fanLow " } | |
if(cmd.medium) { supportedFanModes += "fanMedium " } | |
if(cmd.high) { supportedFanModes += "fanHigh " } | |
val << "on" | |
if(val) { | |
map.name = "supportedThermostatFanModes" | |
map.value=val | |
} | |
log.info "Supported Fan Modes: ${supportedFanModes}" | |
updateState("supportedFanModes", supportedFanModes) | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) { | |
def map = [:] | |
debug "Battery report $cmd" | |
map.name = "battery" | |
map.value = cmd.batteryLevel > 0 ? cmd.batteryLevel.toString() : 1 | |
map.unit = "%" | |
map.displayed = false | |
map | |
} | |
private Map getCommandParameters() { [ | |
"remoteCode": 27, | |
"tempOffsetParam": 37, | |
"oscillateSetting": 33, | |
"emitterPowerSetting": 28, | |
"surroundIRSetting": 32, | |
"learningMode": 25, | |
]} | |
def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) { | |
def map = [:] | |
debug "ConfigurationReport $cmd" | |
map.displayed = false | |
switch (cmd.parameterNumber) { | |
// remote code | |
case (Integer)commandParameters["remoteCode"]: | |
map.name = "currentConfigCode" | |
def short remoteCodeLow = cmd.configurationValue[1] | |
def short remoteCodeHigh = cmd.configurationValue[0] | |
map.value = (remoteCodeHigh << 8) + remoteCodeLow | |
//log.info "reported currentConfigCode=$map.value" | |
break | |
case (Integer)commandParameters["tempOffsetParam"]: | |
map.name = "currentTempOffset" | |
def short offset = cmd.configurationValue[0] | |
if(offset >= 0xFB) { // Hex FB-FF represent negative offsets FF=-1 - FB=-5 | |
offset = offset - 256 | |
} | |
map.value = offset | |
//log.info "reported offset=$map.value C" | |
break | |
case (Integer)commandParameters["emitterPowerSetting"]: | |
String power = (cmd.configurationValue[0] == 0) ? "normal" : "high" | |
map.name = "currentemitterPower" | |
map.value = power | |
//log.info "reported power ${cmd.configurationValue[0]} ${power}" | |
break | |
case (Integer)commandParameters["surroundIRSetting"]: | |
String surround = (cmd.configurationValue[0] == 0) ? "disabled" : "enabled" | |
map.name = "currentsurroundIR" | |
map.value = surround | |
//log.info "reported surround ${cmd.configurationValue[0]} ${surround}" | |
break | |
case (Integer)commandParameters["oscillateSetting"]: | |
String oscillateMode = (cmd.configurationValue[0] == 0) ? "off" : "auto" // THIS IS OFF, AUTO (default) | |
map.name = "swingMode" | |
map.value = oscillateMode | |
//log.info "reported swing mode = ${oscillateMode}" | |
state.swingMode = oscillateMode | |
break | |
default: | |
log.warn "Unknown configuration report ${cmd.parameterNumber}" | |
break; | |
} | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv1.ManufacturerSpecificReport cmd) { | |
debug "MSR report $cmd" | |
def map = [:] | |
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) | |
device.updateDataValue("MSR", msr) | |
device.updateDataValue("manufacturer", cmd.manufacturerName) | |
//createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false]) | |
map | |
} | |
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) { | |
def map = [:] | |
debug "Basic report: $cmd typically on/off reports" | |
map | |
} | |
def zwaveEvent(hubitat.zwave.Command cmd) { | |
def map = [:] | |
log.warn "Unexpected zwave command $cmd" | |
map | |
} | |
private Map getModeMap() { [ | |
//ENUM ["auto", "off", "heat", "emergency heat", "cool"] | |
"off": 0, //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_OFF, | |
"heat": 1, //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_HEAT, | |
"cool": 2, //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_COOL, | |
"auto": 3, //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_AUTO, | |
// these are non-standard | |
"fanOnly": 6, | |
"resume": 5, // ON //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_RESUME, | |
"dry": 8, //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_DRY_AIR, | |
"autoChangeover": 10 //hubitat.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_AUTO_CHANGEOVER | |
]} | |
def setThermostatMode(String value) { | |
def commands = [] | |
def degrees = 0 | |
log.debug "setting thermostat mode $value ${modeMap[value]}" | |
commands << zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[value]).format() | |
commands << zwave.thermostatModeV2.thermostatModeGet().format() | |
if(value == "cool") { | |
degrees = device.currentValue("coolingSetpoint") | |
if(degrees) { | |
commands << setCoolingSetpoint(degrees, true, true) | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 2).format() | |
} else log.warn "mode is cool without stored coolingSetpoint" | |
} else if(value == "heat") { | |
degrees = device.currentValue("heatingSetpoint") | |
if(degrees) { | |
commands << setHeatingSetpoint(degrees, true, true) | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 1).format() | |
} else log.warn "mode is heat without stored heatingSetpoint" | |
} else if(value in ["auto", "dry"]) { | |
degrees = device.currentValue("thermostatSetpoint") | |
if(degrees) { | |
if(value == "auto"){ | |
commands << setAutoSetpoint(degrees, true, true) | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 10).format() | |
}else{ | |
commands << setDrySetpoint(degrees, true, true) | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 8).format() | |
} | |
} else log.warn "mode is auto without stored thermostatSetpoint" | |
} else if(value in ["dry","off", "resume", "fanOnly"]) { | |
debug "Dry, Resume or Off, fanOnly, no need to send temp" | |
} else { | |
log.warn("Unknown thermostat mode set:$value") | |
return null | |
} | |
delayBetween(commands, 2300) | |
} | |
def auto() { | |
log.debug "${device.name} received AUTO request" | |
setThermostatMode("auto") | |
} | |
def cool() { | |
log.debug "${device.name} received COOL request" | |
setThermostatMode("cool") | |
} | |
def emergencyHeat() { | |
log.warn "setting emergencyheat() not supported" | |
return null | |
setThermostatMode("emergencyHeat") | |
} | |
def heat() { | |
log.debug "${device.name} received HEAT request" | |
setThermostatMode("heat") | |
} | |
def off() { | |
log.debug "${device.name} received OFF request" | |
setThermostatMode("off") | |
} | |
def on() { | |
String onCommandVal = onCommand == null ? "emulate(resume)" : onCommand | |
log.debug "${device.name} received on request onCommandVal=${onCommandVal}" | |
//input("onCommand", "enum", title: "Command to send when 'On' Button is Pressed?", options: ["on(resume)","emulate(resume)","cool","heat","dry"]) | |
switch (onCommandVal) { | |
case "emulate(resume)": | |
String lastTriedMode=getDataByName("lastTriedMode") | |
debug "emulating resume $lastTriedMode" | |
if(lastTriedMode) { setThermostatMode(lastTriedMode); break } | |
else log.warn "resume command without saved mode $lastTriedMode" | |
case "on(resume)": | |
debug "issuing setThermostatMode:on" | |
setThermostatMode("resume") | |
break; | |
case ['cool','heat','dry']: | |
debug "issuing setThermostatMode:${onCommandVal}" | |
setThermostatMode(onCommandVal) | |
break; | |
default: | |
log.warn "Configuration Error: unknown onCommandVal: ${onCommandVal}" | |
return null | |
break; | |
} | |
} | |
def fanOnly() { | |
log.debug "${device.name} received fanOnly mode request" | |
setThermostatMode("fanOnly") | |
} | |
def eco() { | |
log.debug "${device.name} received ECO request" | |
setThermostatMode("off") | |
} | |
def dry() { | |
log.debug "${device.name} received DRY request" | |
setThermostatMode("dry") | |
} | |
def autoChangeover() { | |
log.debug "${device.name} received AUTOCHANGEOVER request" | |
setThermostatMode("autoChangeover") | |
} | |
/* | |
private Map getSetpointMap() { [ | |
"heatingSetpoint": hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1, | |
"coolingSetpoint": hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_COOLING_1, | |
"drySetpoint": hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_DRY_AIR, | |
"autoSetpoint": hubitat.zwave.commands.thermostatsetpointv2.ThermostatSetpointSet.SETPOINT_TYPE_AUTO_CHANGEOVER | |
]} | |
*/ | |
def setHeatingSetpoint(degrees) { | |
setHeatingSetpoint(degrees.toDouble()) | |
} | |
def setHeatingSetpoint(Double degrees, Boolean nocheck = false, Boolean returnCommand=false, Integer delay = 2300) { | |
log.trace "setHeatingSetpoint($degrees, $delay)" | |
def commands = [] | |
String hvacMode = device.latestValue("thermostatMode") | |
def convertedDegrees = checkValidTemp(degrees) | |
if(nocheck || hvacMode in ["heat"]) { | |
convertedDegrees=convertToDevice(convertedDegrees) | |
def deviceScale = state?.scale != null ? state.scale : 1 | |
String deviceScaleString = deviceScale == 1 ? "F" : "C" | |
debug "setHeatingSetpoint({$convertedDegrees} ${deviceScaleString})" | |
Integer p = (state?.precision == null) ? 1 : state.precision | |
def cmd = zwave.thermostatSetpointV2.thermostatSetpointSet(setpointType: 1, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format() | |
if(returnCommand) return cmd | |
commands << cmd | |
} else { | |
log.warn "setting heatingSetpoint but cannot change heat setpoint due to hvacMode: ${hvacMode}" | |
sendEvent(name:'heatingSetpoint', value: convertedDegrees) | |
return null | |
} | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 1).format() | |
delayBetween(commands, delay) | |
} | |
def setCoolingSetpoint(degrees) { | |
setCoolingSetpoint(degrees.toDouble()) | |
} | |
def setCoolingSetpoint(Double degrees, Boolean nocheck = false, Boolean returnCommand=false, Integer delay=2300) { | |
log.trace "setCoolingSetpoint($degrees, $delay)" | |
def commands = [] | |
String hvacMode = device.latestValue("thermostatMode") | |
def convertedDegrees = checkValidTemp(degrees) | |
if(nocheck || hvacMode in ["cool"]) { | |
convertedDegrees=convertToDevice(convertedDegrees) | |
def deviceScale = state?.scale != null ? state.scale : 1 | |
String deviceScaleString = deviceScale == 1 ? "F" : "C" | |
debug "setCoolingSetpoint({$convertedDegrees} ${deviceScaleString})" | |
Integer p = (state?.precision == null) ? 1 : state.precision | |
def cmd= zwave.thermostatSetpointV2.thermostatSetpointSet(setpointType: 2, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format() | |
if(returnCommand) return cmd | |
commands << cmd | |
} else { | |
log.warn "setting coolingSetpoint but cannot change cool setpoint due to hvacMode: ${hvacMode}" | |
sendEvent(name:'coolingSetpoint', value: convertedDegrees) | |
return null | |
} | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 2).format() | |
delayBetween(commands, delay) | |
} | |
def setDrySetpoint(degrees) { | |
setDrySetpoint(degrees.toDouble()) | |
} | |
def setDrySetpoint(Double degrees, nocheck = false, Integer delay = 2300) { | |
log.trace "setDrySetpoint($degrees, $delay)" | |
def commands = [] | |
String hvacMode = device.latestValue("thermostatMode") | |
def convertedDegrees = checkValidTemp(degrees) | |
if(nocheck || hvacMode in ["dry"]) { | |
convertedDegrees=convertToDevice(convertedDegrees) | |
def deviceScale = state?.scale != null ? state.scale : 1 | |
String deviceScaleString = deviceScale == 1 ? "F" : "C" | |
debug "setDrySetpoint({$convertedDegrees} ${deviceScaleString})" | |
Integer p = (state?.precision == null) ? 1 : state.precision | |
commands << zwave.thermostatSetpointV2.thermostatSetpointSet(setpointType: 8, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format() | |
} else { | |
log.warn "setting drySetpoint but cannot change dry setpoint due to hvacMode: ${hvacMode}" | |
sendEvent(name:'drySetpoint', value: convertedDegrees) | |
return null | |
} | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 8).format() | |
delayBetween(commands, delay) | |
} | |
def setAutoSetpoint(degrees) { | |
setAutoSetpoint(degrees.toDouble()) | |
} | |
def setAutoSetpoint(Double degrees, nocheck = false, Integer delay = 2300) { | |
log.trace "setAutoSetpoint($degrees, $delay)" | |
def commands = [] | |
String hvacMode = device.latestValue("thermostatMode") | |
def convertedDegrees = checkValidTemp(degrees) | |
if(nocheck || hvacMode in ["auto"]) { | |
convertedDegrees=convertToDevice(convertedDegrees) | |
def deviceScale = state?.scale != null ? state.scale : 1 | |
String deviceScaleString = deviceScale == 1 ? "F" : "C" | |
debug "setAutoSetpoint({$convertedDegrees} ${deviceScaleString})" | |
Integer p = (state?.precision == null) ? 1 : state.precision | |
commands << zwave.thermostatSetpointV2.thermostatSetpointSet(setpointType: 10, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format() | |
} else { | |
log.warn "setting autoSetpoint but cannot change auto setpoint due to hvacMode: ${hvacMode}" | |
sendEvent(name:'autoSetpoint', value: convertedDegrees) | |
return null | |
} | |
commands << zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 10).format() | |
delayBetween(commands, delay) | |
} | |
def convertToDevice(degrees) { | |
def deviceScale = state?.scale != null ? state.scale : 1 | |
String deviceScaleString = deviceScale == 1 ? "F" : "C" | |
String locationScale = getTemperatureScale() | |
def convertedDegrees = degrees | |
if(locationScale == "C" && deviceScaleString == "F") { | |
convertedDegrees = celsiusToFahrenheit(degrees).round(0).toInteger | |
} else if(locationScale == "F" && deviceScaleString == "C") { | |
def tval = fahrenheitToCelsius(degrees).toDouble() | |
convertedDegrees = Math.round(tval.round(1) * 2) / 2.0f | |
//convertedDegrees = tval.round(0) | |
debug "tval ${tval} ${convertedDegrees}" | |
} | |
Integer p = (state?.precision == null) ? 1 : state.precision | |
switch (p) { | |
case 0: | |
convertedDegrees = Math.ceil(convertedDegrees) | |
break | |
default: | |
break | |
} | |
return convertedDegrees | |
} | |
def checkValidTemp(degrees) { | |
String locationScale = getTemperatureScale() | |
def override = false | |
def overrideDegrees = degrees | |
if(locationScale == "F") { | |
overrideDegrees = Math.round(overrideDegrees) | |
// ZXT-120 lowest settings is 67 | |
if(overrideDegrees < 67) { | |
overrideDegrees = 67 | |
override = true | |
} | |
// ZXT-120 highest setting is 84 | |
if(overrideDegrees > 84) { | |
overrideDegrees = 84 | |
override = true | |
} | |
} else if(locationScale == "C") { | |
overrideDegrees = Math.round(overrideDegrees * 2.0D) / 2.0D | |
// ZXT-120 lowest settings is 19 C | |
if(overrideDegrees < 19) { | |
overrideDegrees = 19 | |
override = true | |
} | |
// ZXT-120 highest setting is 28 C | |
if(overrideDegrees > 28) { | |
overrideDegrees = 28 | |
override = true | |
} | |
} else { log.error "checkValidTemp: unknown device scale" } | |
if(override || degrees!=overrideDegrees) { | |
log.warn "overriding temp ${degrees} to ${overrideDegrees}" | |
} | |
return overrideDegrees | |
} | |
def setLearningPosition(position) { | |
log.debug "Setting learning postition: $position" | |
sendEvent("name":"learningPosition", "value":learningPosition) | |
def ctemp = 0 | |
if (position < 12) { | |
ctemp=position+17 | |
} else { | |
ctemp=position+7 | |
} | |
def ftempLow=(Math.ceil(((ctemp*9)/5)+32)).toInteger() | |
def ftempHigh=ftempLow+1 | |
String positionTemp = "not set" | |
switch (position) { | |
case 0: | |
positionTemp = 'Off' | |
break | |
case 1: | |
positionTemp = 'On(resume)' | |
break | |
case [3,4,5,6,8,9,10,11]: | |
positionTemp = "cool ${ctemp}C ${ftempLow}-${ftempHigh}F" | |
break | |
case [2,7]: | |
positionTemp = "cool ${ctemp}C ${ftempLow}F" | |
break | |
case [13,14,15,16,18,19,20,21]: | |
positionTemp = "heat ${ctemp}C ${ftempLow}-${ftempHigh}F" | |
break | |
case [12,17]: | |
positionTemp = "heat ${ctemp}C ${ftempLow}F" | |
break | |
case 22: | |
positionTemp = 'Dry mode' | |
break | |
default: | |
positionTemp = 'Invalid' | |
break | |
} | |
sendEvent("name":"learningPositionTemp", "value":positionTemp) | |
} | |
def issueLearningCommand() { | |
Integer position = device.currentValue("learningPosition").toInteger() | |
log.debug "Issue Learning Command pressed Position Currently: $position" | |
def positionConfigArray = [position] | |
log.debug "Position Config Array: ${positionConfigArray}" | |
delayBetween ([ | |
// Send the new remote code | |
zwave.configurationV1.configurationSet(configurationValue: positionConfigArray, | |
parameterNumber: commandParameters["learningMode"], size: 1).format() | |
]) | |
} | |
def setRemoteCode() { | |
Integer remoteCodeVal = remoteCode.toInteger() | |
// Divide the remote code into a 2 byte value | |
def short remoteCodeLow = remoteCodeVal & 0xFF | |
def short remoteCodeHigh = (remoteCodeVal >> 8) & 0xFF | |
def remoteBytes = [remoteCodeHigh, remoteCodeLow] | |
log.info "Setting Remote Code: ${remoteBytes}" | |
[ | |
zwave.configurationV1.configurationSet(configurationValue: remoteBytes, parameterNumber: commandParameters["remoteCode"], size: 2).format(), | |
zwave.configurationV1.configurationGet(parameterNumber: commandParameters["remoteCode"]).format() | |
] | |
/* caller will send these | |
delayBetween ([ | |
zwave.configurationV1.configurationSet(configurationValue: remoteBytes, parameterNumber: commandParameters["remoteCode"], size: 2).format(), | |
zwave.configurationV1.configurationGet(parameterNumber: commandParameters["remoteCode"]).format() | |
], standardDelay) | |
*/ | |
} | |
def setTempOffset() { | |
def tempOffsetVal = tempOffset == null ? 0 : tempOffset.toInteger() | |
if(tempOffsetVal < 0) { // Convert negative values into hex value for this param -1 = 0xFF -5 = 0xFB | |
tempOffsetVal = 256 + tempOffsetVal | |
} | |
def configArray = [tempOffsetVal] | |
log.info "Setting TempOffset: ${tempOffsetVal}" | |
[ | |
zwave.configurationV1.configurationSet(configurationValue: configArray, parameterNumber: commandParameters["tempOffsetParam"], size: 1).format(), | |
zwave.configurationV1.configurationGet(parameterNumber: commandParameters["tempOffsetParam"]).format() | |
] | |
/* caller will send these | |
delayBetween ([ | |
zwave.configurationV1.configurationSet(configurationValue: configArray, parameterNumber: commandParameters["tempOffsetParam"], size: 1).format(), | |
zwave.configurationV1.configurationGet(parameterNumber: commandParameters["tempOffsetParam"]).format() | |
], standardDelay) | |
*/ | |
} | |
def switchFanOscillate() { | |
def swingMode = (getDataByName("swingMode") == "off") ? true : false // Load the current swingmode and invert it (Off becomes true, On becomes false) | |
setFanOscillate(swingMode) | |
} | |
def swingModeOn() { | |
log.debug "Setting Swing mode AUTO" | |
setFanOscillate(true) | |
} | |
def swingModeOff() { | |
log.debug "Setting Swing mode Off" | |
setFanOscillate(false) | |
} | |
def setFanOscillate(Boolean swingMode) { | |
def swingValue = swingMode ? 1 : 0 // Convert the swing mode requested to 1 for on, 0 for off | |
def hvacMode = device.latestValue("thermostatMode") | |
if( !(hvacMode in ["heat","cool","auto","dry"]) ) { | |
log.warn "wrong mode ${hvacMode}" | |
} else { | |
delayBetween ([ | |
zwave.configurationV1.configurationSet(configurationValue: [swingValue], parameterNumber: commandParameters["oscillateSetting"], size: 1).format(), | |
zwave.configurationV1.configurationGet(parameterNumber: commandParameters["oscillateSetting"]).format() | |
], standardDelay) | |
} | |
} | |
List fanModes() { | |
["fanAuto", "fanOn", "fanLow", "fanMedium", "fanHigh"] | |
} | |
def switchFanMode() { | |
String currentMode = device.currentState("thermostatFanMode")?.value | |
if(currentMode == "auto") { currentMode = "fanAuto" } | |
else if(currentMode == "on") { currentMode = "fanLow" } | |
else { currentMode == null } | |
String lastTriedFMode = getDataByName("lastTriedFanMode") ?: currentMode.value ?: "fanAuto" | |
def supportedModes = getDataByName("supportedFanModes") ?: "fanAuto fanLow" | |
List modeOrder = fanModes() | |
//log.info modeOrder | |
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] } | |
String nextMode = next(lastTriedFMode) | |
while (!supportedModes?.contains(nextMode) && nextMode != "fanAuto") { | |
nextMode = next(nextMode) | |
} | |
switchToFanMode(nextMode) | |
} | |
def switchToFanMode(String nextMode) { | |
def supportedFanModes = getDataByName("supportedFanModes") | |
if(supportedFanModes && !supportedFanModes.tokenize()?.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported" | |
if(nextMode in fanModes()) { | |
updateState("lastTriedFanMode", nextMode) | |
return "$nextMode"() | |
} else { | |
log.warn("no fan mode method '$nextMode'") | |
return null | |
} | |
} | |
def setThermostatFanMode(String value) { | |
log.info "fan mode " + value + " ${fanModeMap[value]}" | |
delayBetween([ | |
zwave.thermostatFanModeV2.thermostatFanModeSet(fanMode: fanModeMap[value]).format(), | |
zwave.thermostatFanModeV2.thermostatFanModeGet().format() | |
], standardDelay) | |
} | |
def getFanModeMap() { [ | |
"auto": 0, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_LOW, | |
"circulate": 1, // hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_LOW, | |
"on": 1, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_LOW, | |
"fanAuto": 0, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_AUTO_LOW, | |
"fanOn": 1, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_LOW, | |
"fanLow": 1, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_LOW, | |
"fanMedium": 5, //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_MEDIUM, | |
"fanHigh": 3 //hubitat.zwave.commands.thermostatfanmodev2.ThermostatFanModeReport.FAN_MODE_HIGH | |
]} | |
def fanAuto() { | |
log.debug "${device.name} received FANAUTO request" | |
setThermostatFanMode("auto") | |
/* delayBetween([ | |
zwave.thermostatFanModeV2.thermostatFanModeSet(fanMode: 0).format(), | |
zwave.thermostatFanModeV2.thermostatFanModeGet().format() | |
], standardDelay)*/ | |
} | |
def fanCirculate() { | |
log.warn "fanCirculate() not supported" | |
return | |
/* delayBetween([ | |
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 6).format(), | |
zwave.thermostatFanModeV3.thermostatFanModeGet().format() | |
], standardDelay)*/ | |
} | |
def fanOn() { | |
log.debug "${device.name} received FANON request" | |
setThermostatFanMode("on") | |
/* delayBetween([ | |
zwave.thermostatFanModeV2.thermostatFanModeSet(fanMode: 1).format(), | |
zwave.thermostatFanModeV2.thermostatFanModeGet().format() | |
], standardDelay)*/ | |
} | |
def setSpeed(fanspeed){ | |
log.debug "${device.name} received setSpeed $fanspeed request" | |
// if off, turn on and put thermostat into fan mode | |
// ENUM ["low","medium-low","medium","medium-high","high","on","off","auto"] | |
//["fanAuto", "fanOn", "fanLow", "fanMedium", "fanHigh"] | |
switch(fanspeed) { | |
case ['low','low-medium']: | |
setThermostatFanMode("fanLow") | |
break | |
case ['medium','medium-high']: | |
setThermostatFanMode("fanMedium") | |
break | |
case 'high': | |
setThermostatFanMode("fanHigh") | |
break | |
case 'on': | |
setThermostatFanMode("fanOn") | |
break | |
case 'auto': | |
case 'off': | |
setThermostatFanMode("fanAuto") | |
break | |
default: | |
log.warn "setSpeed: unknown speed" | |
} | |
} | |
def fanLow() { | |
log.debug "setting fan mode low" | |
setThermostatFanMode("fanLow") | |
} | |
def fanMed() { | |
log.debug "setting fan mode med" | |
setThermostatFanMode("fanMedium") | |
} | |
def fanHigh() { | |
log.debug "setting fan mode high" | |
setThermostatFanMode("fanHigh") | |
} | |
private getStandardDelay() { | |
1000 | |
} | |
def updateState(String name, String value) { | |
state[name] = value | |
// sendEvent(name: name, value: value, displayed: false) | |
//device.updateDataValue(name, value) | |
} | |
def getDataByName(String name) { | |
//state[name] ?: device.getDataValue(name) | |
state[name] ?: null // device.currentState(name)?.value | |
} | |
void debug(String msg) { | |
if(debugEnable) log.debug msg | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment