@aruffell Here is my handler:
/**
* Copyright 2018 SmartThings
*
* 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: "Z-Wave Fan Controller 4-Level", namespace: "darthdurden", author: "geoffrey.j.brown@gmail.com", ocfDeviceType: "oic.d.fan", genericHandler: "Z-Wave") {
capability "Switch"
capability "Fan Speed"
capability "Health Check"
command "low"
command "medium"
command "high"
command "max"
command "raiseFanSpeed"
command "lowerFanSpeed"
command "setFanSpeed"
command "setSwitchModeNormal"
command "setSwitchModeStatus"
command "setSwitchModeNormalTemp"
fingerprint mfr: "000C", prod: "0203", model: "0001", deviceJoinName: "HomeSeer 4 Speed Fan Control"
}
simulator {
status "00%": "command: 2003, payload: 00"
status "24%": "command: 2003, payload: 18"
status "49%": "command: 2003, payload: 31"
status "74%": "command: 2003, payload: 4A"
status "99%": "command: 2003, payload: 63"
}
tiles(scale: 2) {
multiAttributeTile(name: "fanSpeed", type: "generic", width: 6, height: 4, canChangeIcon: true) {
tileAttribute("device.fanSpeed", key: "PRIMARY_CONTROL") {
attributeState "0", label: "off", action: "switch.on", icon: "st.thermostat.fan-off", backgroundColor: "#ffffff"
attributeState "1", label: "low", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
attributeState "2", label: "medium", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
attributeState "3", label: "high", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
attributeState "4", label: "max", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc"
}
tileAttribute("device.fanSpeed", key: "VALUE_CONTROL") {
attributeState "VALUE_UP", action: "raiseFanSpeed"
attributeState "VALUE_DOWN", action: "lowerFanSpeed"
}
}
main "fanSpeed"
details(["fanSpeed"])
}
}
def installed() {
log.debug "installing ..."
sendHubCommand(zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 5, size: 1).format())
sendHubCommand(zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 13, size: 1).format())
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
response(refresh())
}
def parse(String description) {
def result = null
if (description != "updated") {
log.debug "parse() >> zwave.parse($description)"
def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) {
result = [result, response(zwave.basicV1.basicGet())]
log.debug "Was hailed: requesting state update"
} else {
log.debug "Parse returned ${result?.descriptionText}"
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
return fanEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
return fanEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
return fanEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) {
return fanEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
log.debug "received hail from device"
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
sendHubCommand(zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format())
// Handles all Z-Wave commands we aren't interested in
log.debug "Unhandled: ${cmd.toString()}"
[:]
}
def fanEvents(physicalgraph.zwave.Command cmd) {
def rawLevel = cmd.value as int
def result = []
if (0 <= rawLevel && rawLevel <= 100) {
def value = (rawLevel ? "on" : "off")
result << createEvent(name: "switch", value: value)
result << createEvent(name: "level", value: rawLevel == 99 ? 100 : rawLevel)
def fanLevel = 0
if (1 <= rawLevel && rawLevel <= 24) {
fanLevel = 1
} else if (25 <= rawLevel && rawLevel <= 49) {
fanLevel = 2
} else if (50 <= rawLevel && rawLevel <= 74) {
fanLevel = 3
} else if (75 <= rawLevel && rawLevel <= 100) {
fanLevel = 4
}
result << createEvent(name: "fanSpeed", value: fanLevel)
}
return result
}
def on() {
def cmds = []
cmds << zwave.switchMultilevelV3.switchMultilevelSet(value: 0xFF).format()
cmds << zwave.switchMultilevelV1.switchMultilevelGet().format()
return cmds
}
def off() {
def cmds = []
cmds << zwave.switchMultilevelV3.switchMultilevelSet(value: 0x00).format()
cmds << zwave.switchMultilevelV1.switchMultilevelGet().format()
return cmds
}
def setLevel(value, rate = null) {
def cmds = []
def level = value as Integer
level = level == 255 ? level : Math.max(Math.min(level, 99), 0)
log.debug "setLevel >> value: $level"
cmds << zwave.switchMultilevelV3.switchMultilevelSet(value: level).format()
cmds << zwave.switchMultilevelV1.switchMultilevelGet().format()
cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
return cmds
}
def setFanSpeed(speed) {
log.debug "setFanSpeed >> $speed"
if (speed as Integer == 0) {
off()
} else if (speed as Integer == 1) {
low()
} else if (speed as Integer == 2) {
medium()
} else if (speed as Integer == 3) {
high()
} else if (speed as Integer == 4) {
max()
}
}
def raiseFanSpeed() {
setFanSpeed(Math.min((device.currentValue("fanSpeed") as Integer) + 1, 4))
}
def lowerFanSpeed() {
setFanSpeed(Math.max((device.currentValue("fanSpeed") as Integer) - 1, 0))
}
def low() {
setLevel(24)
}
def medium() {
setLevel(49)
}
def high() {
setLevel(74)
}
def max() {
setLevel(99)
}
/*
* Set the color of the LEDS for normal dimming mode, shows the current dim level
*/
def setSwitchModeNormal() {
log.debug "switch mode >> normal"
def cmds = []
cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
return cmds
}
def set4Speed() {
cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 5, size: 1).format()
}
/*
* Set Dimmer to Status mode (exit normal mode)
*
*/
def setSwitchModeStatus() {
log.debug "switch mode >> status"
def cmds = []
cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 13, size: 1).format()
return cmds
}
def setSwitchModeNormalTemp() {
def cmds = []
cmds << setSwitchModeNormal()
cmds << setSwitchModeStatus()
return delayBetween(cmds, 5000)
}
def refresh() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}
def ping() {
refresh()
}
I believe it should work just fine for 4 speeds out of the box. I’m having trouble with my one fan (speed 2 runs the same as speed 1), but I’m 99% sure that is a bad capacitor on the fan now. It used to work, so I think something just died on it. I hope this helps!