Homeseer 300 Dimmers Broke with JS Upgrade?

I've been fighting a ton of other issues lately but this is certainly part of the problem. It probably would have been more obvious if I didn't usually force on/off regardless of on/off state with Room Lighting.

The non-Hubitat 300 dimmer driver that gives you far more control over the device's features no long returns on/off state.

This was working...now they all fail. If I flip to the Hubitat driver they work.

Can you be more specific about what drivers you are using and what specific problems you have, or is it just the "switch" state? (And that by "driver" you mean driver in the Hubitat sense and not Z-Wave JS as a "driver" which is what it calls itself in another sense?)

Debug logging would also be good to see for the "missed" events, or the lack thereof if that is the case (Z-Wave logs might have more in that case on JS, or staff may need to dig deeper.)

So that is a custom driver that you got from this community? You should find the release post for that driver and post your question there for the developer to see it.

Thanks...

So here are some screenshots


The switch status never update. PS - A switch can only have two states...on/off...this NEVER updates.

Debug is enabled

BUT NOTHING EVEN SHOWS IN THE LOG - I turned it on/off 6 times and this is the log output...

So now the funny/irritating thing?

The light is actually turning on/off each time I send the command

From the device detail page, I assume? Is it different if you do it physically?

And what driver are you using? (I think I recognize it -- just want to be sure. :wink: )

It logs from the switch physically
dev:312025-05-09 10:15:09.374 AM

info

Bath switch is off

dev:312025-05-09 10:15:09.150 AM

info

Bath button 2 was pushed

dev:312025-05-09 10:15:08.622 AM

info

Bath switch is on

dev:312025-05-09 10:15:08.393 AM

info

Bath button 1 was pushed

dev:312025-05-09 10:15:07.857 AM

info

Bath switch is off

dev:312025-05-09 10:15:07.677 AM

info

Bath button 2 was pushed

dev:312025-05-09 10:15:07.081 AM

info

Bath level is 99%

dev:312025-05-09 10:15:07.079 AM
info


Bath switch is on
dev:312025-05-09 10:15:06.853 AM
info Bath button 1 was pushed
dev:312025-05-09 10:15:06.008 AM
info Bath switch is off
dev:312025-05-09 10:15:05.786 AM
info Bath button 2 was pushed

Apparently I suck at ever finding those as they NEVER come up on a search...where are they? How do I get there?

So...you're physically turning the switch on or off, i.e., using the paddle?

Turning the device on or off from the wall does not depend in the driver, unless you have smart bulb mode enabled (in which case it would depend on some hub automation to do something, perhaps this, perhaps something else entirely). So the fact that it turns on or off from that is not surprising, assuming this is indeed what you meant when you answered the question.

If it's a custom driver, you installed the code. How did you do that? You likely found a forum topic (thread) with a link. If it was this one, it is mine, and there is no need to post there, as I am already here: [RELEASE] HomeSeer HS-WX300 Driver (dimmer and switch) (however, the information above would still be good to know).

If it was HPM, there is normally a link to this from inside the HPM app when you install or go to "View Apps and Drivers" in HPM, assuming the developer provided such links. HPM itself is not a place you can install something from but rather a place that points to other, existing places, so you can almost always find something like the above with a manual search, too.

2 Likes

It been long enough I don't know if I used HPM or Github. (I don't find it under HPM modify so must be Github...) Thanks for the info.

Turning it on/off locally does log. I thought that text came from driver...but no idea really. From the driver interface it does not log. But the light does turn on and off. That seems really strange to me.

I'm not sure what specific text you are talking about, but you can tell where a log entry comes from by looking at the source in Logs. Something like "dev:xxx" means it was the device with the hub-assigned ID "xxx", and clicking it will filter to just that device and also highlight its name at the top. Other entries may be generated by apps or, less commonly, the hub itself (sys:1).

You still have not answered what driver you are using, which is a very important question for further troubleshooting. If it is mine, please enable debug logging and run the On or Off commands and see what gets written out to there. It won't be nothing at all unless you didn't run the command or don't have debug logging enabled, so I'm suspicious from the above where it seems there is the closest thing to to this I can find (but, again, maybe it's not this driver).

I’m sorry I thought I had posted screenshots of the driver. When I get home, I’ll do the rest of it. I think further up in the email chain and I may be confused, but I’ve already turned on debug and I get no output at all. That’s the reason Walding came up. The only time it logs a message when I turn it on and off from the wall.

I don’t have the exact name in front of me, but it’s the one that ends with advanced that parentheses I’m pretty sure it’s yours.

A screenshot of the driver name or UI doesn't really tell where it came from (or what the code is, which is ultimately the issue). My best guess is that is mine since everything I recognize should match. But:

This would not be the case with my driver if you have debug logging enabled as above.

So, without that, either you're using a different driver, don't have this enabled, or something else is wrong; without knowing more, particularly the first point, little useful troubleshooting can be done.

This is the driver I am using

/*

  • =============== HomeSeer HS-WX300 (Z-Wave Dimmer/Switch - Dimmer) Driver ===============
  • Copyright 2021 Robert Morris
  • 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.
  • =======================================================================================
  • Changelog:
  • v1.1 (2022-10-06) - Add "smart bulb mode" parameter, default level parameter, LED level command (requires firmware 1.13+)
  • v1.0 (2021-11-06) - Initial release
    */

import groovy.transform.Field
import java.util.concurrent.ConcurrentHashMap

@Field static final Map<Short,Short> commandClassVersions = [
0x20: 1, // Basic (2)
//0x25: 1, // Switch Binary (2) - Switch Mode Only
0x27: 1, // Switch All
0x26: 3, // Switch Multilevel (4) - Dimmer Mode Only
0x5B: 1, // CentralScene (3)
0x55: 1, // Transport Service (2))
0x59: 1, // AssociationGrpInfo
0x5A: 1, // DeviceResetLocally
0x5E: 2, // ZwaveplusInfo
0x6C: 1, // Supervision
0x70: 1, // Configuration (4)
0x7A: 2, // FirmwareUpdateMd
0x72: 2, // ManufacturerSpecific
0x85: 2, // Association
0x86: 2, // Version
0x98: 1, // Security
0x9F: 1 // Security S2
]

@Field static final Map<String,Short> normalColorNameMap = [
"white": 0,
"red": 1,
"green": 2,
"blue": 3,
"magenta": 4,
"yellow": 5,
"cyan": 6
]

@Field static final Map<String,Short> statusColorNameMap = [
"off": 0,
"red": 1,
"green": 2,
"blue": 3,
"magenta": 4,
"yellow": 5,
"cyan": 6,
"white": 7
]

@Field static final Map<Short,Map> zwaveParameters = [
3: [size: 1, input: [name: "param.3", title: "Bottom LED operation (in normal mode); manual may have these reversed",
type: "enum", options: [[0: "LED on when load off"],[1:"LED off when load off (DEFAULT)"]]]],
4: [size: 1, input: [name: "param.4", title: "Paddle orientation",
type: "enum", options: [[0: "Top of paddle turns load on (DEFAULT)"],[1:"Bottom of paddle turns load on"]]]],
5: [size: 1, input: [name: "param.5", title: "Lowest dimming threshold",
type: "enum", options: [[1: "1: 16% (3-wire mode)/25% (2-wire mode) (DEFAULT)"],[2:"2"],[3:"3"],[4:"4"],[5:"5"],
[6:"6"],[7:"7"],[8:"8"],[9:"9"],[10:"10"],[11:"11"],[12:"12"],[13:"13"],[14:"14 - 25% (3-wire mode)/30% (2-wire mode)"]]]],
6: [size: 1, input: [name: "param.6", title: "Multi-tap/Central Scene (button events)",
type: "enum", options: [[0: "Enabled (DEFAULT)"],[1:"Disabled (controls load without delay; eliminates held, released, and mulit-taps)"]]]],
11: [size: 1, input: [name: "param.11", title: "Default level transition time/ramp rate for Z-Wave", type: "enum",
options: [[0:"ASAP"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds (DEFAULT)"],[4:"4 seconds"],[5:"5 seconds"],[6:"6 seconds"],[7:"7 seconds"],[8:"8 seconds"],
[9:"9 seconds"],[10:"10 seconds"],[15:"15 seconds"],[30:"30 seconds"],[45:"45 seconds"],[60:"60 seconds"],[90:"90 seconds"]]]],
12: [size: 1, input: [name: "param.12", title: "Default level transition time/ramp rate for physical paddle", type: "enum",
options: [[0:"ASAP"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds (DEFAULT)"],[4:"4 seconds"],[5:"5 seconds"],[6:"6 seconds"],[7:"7 seconds"],[8:"8 seconds"],
[9:"9 seconds"],[10:"10 seconds"],[15:"15 seconds"],[30:"30 seconds"],[45:"45 seconds"],[60:"60 seconds"],[90:"90 seconds"]]]],
// This is exposed as a command instead but can be uncommented if desired:
/13: [size: 1, input: [name: "param.13", title: "LED disply mode", type: "enum",
options: [[0:"Normal (LEDs show load status)"],[1:"Status (custom LED status)"]]]],
/
30: [size: 1, input: [name: "param.30", title: "Blink frequency (when in status mode and blinking)", type: "enum",
options: [[0: "No blink"], [1: "100 ms on, 100 ms off"], [2: "200 ms on, 200 ms off"], [3: "300 ms on, 300 ms off"],
[4: "500 ms on, 400 ms off"], [5: "600 ms on, 500 ms off"], [6: "600 ms on, 600 ms off"], [7: "700 ms on, 700 ms off"],
[8: "800 ms on, 800 ms off"], [10: "1 s on, 1 s off"], [15: "1.5 s on, 1 s off"], [20: "2 s on, 2 s off"],
[25: "2.5 s on, 2.5 s off"], [30: "3 s on, 3 s off"], [50: "5 s on, 5 s off"], [100: "10 s on, 10 s off"],
[150: "15 s on, 15 s off"], [200: "20 s on, 20 s off"], [250: "25 s on, 25 s off" ]]]],
// This is exposed as a command instead but can be uncommented if desired:
/14: [size: 1, input: [name: "param.14", title: "Normal mode LED color", type: "enum",
options: [[0:"off"],[1:"red"],[2:"green"],[3:"blue"],[4:"magenta"],[5:"yellow"],[6:"cyan"],[7:"white"]]]],
/
32: [size: 1, input: [name: "param.32", title: "Wire mode (neutral/non-neutral)", type: "enum",
options: [[0:"3-wire mode (neutral, line, load) (DEFAULT)"],[1:"2-wire mode (line, load)"]]]],
36: [size: 1, input: [name: "param.36", title: "Default level when turned on from paddle (1-99, or 0 for last [DEFAULT]) (firmware 1.13+)", type: "number",
range: "0..99" ]],
37: [size: 1, input: [name: "param.37", title: "Smart bulb mode? (firmware 1.13+)", type: "enum",
options: [[0:"No, load controlled with paddle (DEFAULT)"],[1:"Yes, load not controlled with paddle"]]]]
]

@Field static ConcurrentHashMap<Long, ConcurrentHashMap<Short, String>> supervisedPackets = new ConcurrentHashMap()
@Field static ConcurrentHashMap<Long, Short> sessionIDs = [:]
@Field static final Integer supervisionCheckDelay = 5
@Field static final Integer debugAutoDisableMinutes = 30

metadata {
definition (name: "HomeSeer HS-WX300 Advanced (Dimmer)", namespace: "RMoRobert", author: "Robert Morris", importUrl: "https://raw.githubusercontent.com/RMoRobert/Hubitat/master/drivers/homeseer/homeseer-hs-wx300-advanced-dimmer.groovy") {
capability "Actuator"
capability "Switch"
capability "SwitchLevel"
capability "ChangeLevel"
capability "Flash"
capability "Configuration"
capability "PushableButton"
capability "HoldableButton"
capability "ReleasableButton"
capability "Refresh"

  command "setStatusLED", [[name:"ledNumber*", type: "ENUM", description: "LED number, 1 (bottom) to 7 (top)", constraints: [1,2,3,4,5,6,7]],
                           [name:"colorName*", type: "ENUM", description: "LED color", constraints: statusColorNameMap.collect { e -> e.key } ],
                           [name:"blink", type: "ENUM", description: "Blinking (on) or solid (off)", constraints: ["on", "off"]]]

  command "setNormalLEDColor", [[name: "color*", type: "ENUM", description: "Normal mode LED color", constraints: normalColorNameMap.collect { e -> e.key }],
                                [name: "setModeToNormal", type: "ENUM", description: "Also set LED to normal mode if currently in status mode?", constraints: ["false", "true"]]]

  command "setLEDMode", [[name:"mode*", type: "ENUM", description: "Normal mode (LEDs show load status) or status mode (custom LED statuses)",
                          constraints: ["normal", "status"]]]

  command "setConfigParameter", [[name:"Parameter Number*", type: "NUMBER"], [name:"Value*", type: "NUMBER"], [name:"Size*", type: "NUMBER"]]

  command "setLEDLevel", [[name:"level*", type: "ENUM", description: "LED brightness level, 0 (lowest) to 6 (highest) -- firmware 1.13+ only", constraints: [0,1,2,3,4,5,6]]]

  //fingerprint mfr: "000C", prod: "4447", deviceId: "3036" // WD200 -- would probably work, but commented out just in case
  fingerprint mfr: "000C", prod: "4447", deviceId: "4036", inClusters: "0x5E,0x55,0x9F,0x6C"  // WX300 (dimmer mode, S2)
  fingerprint mfr: "000C", prod: "4447", deviceId: "4036", inClusters: "0x5E,0x85,0x59,0x5A,0x7A,0x87,0x72,0x8E,0x73,0x9F,0x6C,0x55,0x86,0x26,0x70,0x5B"  // WX300 (dimmer mode)

}

preferences {
input name: "showParamNumbers", type: "bool", title: "Show parameter number in preference description", defaultValue: true
Map zwaveParams = zwaveParameters
if (showParamNumbers) {
zwaveParams.each {
if (!(it.value.input.title.startsWith("[${it.key}]"))) {
it.value.input.title = "[${it.key}] " + it.value.input.title
}
}
}
zwaveParams.each {
input it.value.input
}
input name: "flashRate", type: "enum", title: "Flash rate", options: [[500: "500 ms"], [750: "750 ms"], [1000: "1 second"], [2000: "2 seconds"], [5000: "5 seconds"]], defaultValue: 750
input name: "enableDebug", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "enableDesc", type: "bool", title: "Enable descriptionText logging", defaultValue: true
}
}

void installed(){
log.debug "installed()"
sendEvent(name: "level", value: 1)
state.blinkval = 0b0000000
(1..7).each {
state."statusled${it}" = 0
}
}

// Apply preferences changes, including updating parameters
List updated() {
log.debug "updated()"
log.warn "Debug logging is: ${enableDebug == true ? 'enabled' : 'disabled'}"
log.warn "Description logging is: ${enableDesc == true ? 'enabled' : 'disabled'}"
if (enableDebug) {
log.debug "Debug logging will be automatically disabled in ${debugAutoDisableMinutes} minutes..."
runIn(debugAutoDisableMinutes*60, "logsOff")
}

List cmds =

zwaveParameters.each { param, data ->
if (settings[data.input.name] != null) {
if (enableDebug) log.debug "Setting parameter $param (size: ${data.size}) to ${settings[data.input.name]}"
cmds.add(zwaveSecureEncap(zwave.configurationV1.configurationSet(
scaledConfigurationValue: settings[data.input.name] as BigInteger, parameterNumber: param, size: data.size
)))
}
}

cmds.add(zwaveSecureEncap(zwave.versionV2.versionGet()))
cmds.add(zwaveSecureEncap(zwave.manufacturerSpecificV2.deviceSpecificGet(deviceIdType: 1)))
return delayBetween(cmds, 200)
}

void logsOff() {
log.warn "Disabling debug logging"
device.updateSetting("enableDebug", [value:"false", type:"bool"])
}

void parse(String description) {
if (enableDebug) log.debug "parse description: ${description}"
hubitat.zwave.Command cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
zwaveEvent(cmd)
}
}

void supervisionCheck() {
// re-attempt once
if (!supervisedPackets[device.idAsLong]) { supervisedPackets[device.idAsLong] = new ConcurrentHashMap() }
supervisedPackets[device.idAsLong].each { k, v ->
if (enableDebug) log.debug "re-sending supervised session: ${k}"
sendHubCommand(new hubitat.device.HubAction(zwaveSecureEncap(v), hubitat.device.Protocol.ZWAVE))
supervisedPackets[device.idAsLong].remove(k)
}
}

Short getSessionId() {
Short sessId = 1
if (!sessionIDs[device.idAsLong]) {
sessionIDs[device.idAsLong] = sessId
return sessId
} else {
sessId = sessId + sessionIDs[device.idAsLong]
if (sessId > 63) sessId = 1
sessionIDs[device.idAsLong] = sessId
return sessId
}
}

void zwaveEvent(hubitat.zwave.commands.supervisionv1.SupervisionGet cmd) {
hubitat.zwave.Command encapCmd = cmd.encapsulatedCommand(commandClassVersions)
if (encapCmd) {
zwaveEvent(encapCmd)
}
sendHubCommand(new hubitat.device.HubAction(
zwaveSecureEncap(zwave.supervisionV1.supervisionReport(sessionID: cmd.sessionID,
reserved: 0, moreStatusUpdates: false, status: 0xFF, duration: 0)),
hubitat.device.Protocol.ZWAVE)
)
}

void zwaveEvent(hubitat.zwave.commands.supervisionv1.SupervisionReport cmd) {
if (enableDebug) log.debug "supervision report for session: ${cmd.sessionID}"
if (!supervisedPackets[device.idAsLong]) { supervisedPackets[device.idAsLong] = [:] }
if (supervisedPackets[device.idAsLong][cmd.sessionID] != null) { supervisedPackets[device.idAsLong].remove(cmd.sessionID) }
unschedule(supervisionCheck)
}

hubitat.zwave.Command supervisedEncap(hubitat.zwave.Command cmd) {
if (getDataValue("S2")?.toInteger() != null) {
hubitat.zwave.commands.supervisionv1.SupervisionGet supervised = new hubitat.zwave.commands.supervisionv1.SupervisionGet()
supervised.sessionID = getSessionId()
if (enableDebug) log.debug "new supervised packet for session: ${supervised.sessionID}"
supervised.encapsulate(cmd)
if (!supervisedPackets[device.idAsLong]) { supervisedPackets[device.idAsLong] = [:] }
supervisedPackets[device.idAsLong][supervised.sessionID] = supervised.format()
runIn(supervisionCheckDelay, supervisionCheck)
return supervised
} else {
return cmd
}
}

void zwaveEvent(hubitat.zwave.commands.versionv2.VersionReport cmd) {
if (enableDebug) log.debug "VersionReport: ${cmd}"
if (cmd.firmware0Version != null && cmd.firmware0SubVersion != null) {
device.updateDataValue("firmwareVersion", "${cmd.firmware0Version}.${cmd.firmware0SubVersion.toString().padLeft(2,'0')}")
if (enableDebug) log.debug "${device.displayName} firmware0Version and subversion is ${cmd.firmware0Version}.${cmd.firmware0SubVersion.toString().padLeft(2,'0')}"
}
else if (cmd.applicationVersion != null && cmd.applicationSubVersion != null) {
device.updateDataValue("applicationVersion", "${cmd.applicationVersion}.${cmd.applicationSubVersion.toString().padLeft(2,'0')}")
if (enableDebug) log.debug "${device.displayName} applicationVersion amd subversion is ${cmd.applicationVersion}.${cmd.applicationSubVersion.toString().padLeft(2,'0')}"
}
if (cmd.zWaveProtocolVersion != null && cmd.zWaveProtocolSubVersion != null) {
device.updateDataValue("protocolVersion", "${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion.toString().padLeft(2,'0')}")
if (enableDebug) log.debug "${device.displayName} zWaveProtocolVersion and subversion is ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion.toString().padLeft(2,'0')}"
}
if (cmd.hardwareVersion != null) {
device.updateDataValue("hardwareVersion", "${cmd.hardwareVersion}")
if (enableDebug) log.debug "${device.displayName} hardwareVersion is ${cmd.hardwareVersion}"
}
cmd.targetVersions.each { tgt ->
String tgtFW = "${tgt.version}.${tgt.subVersion.toString().padLeft(2,'0')}"
device.updateDataValue("firmwareTarget${tgt.version}" as String, tgtFW)
if (enableDebug) log.debug "Target ${tgt.version} firwmare is $tgtFW"
}
}

void zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
if (enableDebug) log.debug "DeviceSpecificReport v2: ${cmd}"
switch (cmd.deviceIdType) {
case 1:
// serial number
String serialNumber = ""
if (cmd.deviceIdDataFormat==1) {
cmd.deviceIdData.each { serialNumber += hubitat.helper.HexUtils.integerToHexString(it & 0xff, 1).padLeft(2, '0')}
} else {
cmd.deviceIdData.each { serialNumber += (char)it }
}
if (enableDebug) log.debug "Device serial number is $serialNumber"
device.updateDataValue("serialNumber", serialNumber)
break
}
}

void zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (enableDebug) log.debug "ConfigurationReport: ${cmd}"
if (enableDesc) log.info "${device.displayName} parameter '${cmd.parameterNumber}', size '${cmd.size}', is set to '${cmd.scaledConfigurationValue}'"
if (cmd.parameterNumber == 31) {
// Status LED blink bitmask parameter
state.blinkval = cmd.scaledConfigurationValue
}
else if (cmd.parameterNumber >= 21 && cmd.parameterNumber <= 27) {
// Status LED color parameters
Integer ledNum = cmd.parameterNumber - 20
state."statusled${ledNum}" = cmd.scaledConfigurationValue
}
}

// Might be needed for switch mode? Dimmer does not use
/*
void zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
if (enableDebug) log.warn "BasicReport: ${cmd}"
String value = (cmd.value ? "on" : "off")
if (enableDesc && device.currentValue("switch") != value) log.info "${device.displayName} switch is ${value}"
sendEvent(name: "switch", value: value)
}

void zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd) {
if (enableDebug) log.warn "BasicSet: ${cmd}"
String value = (cmd.value ? "on" : "off")
if (enableDesc && device.currentValue("switch") != value) log.info "${device.displayName} switch is ${value}"
sendEvent(name: "switch", value: value)
}
*/

void zwaveEvent(hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
if (enableDebug) log.debug "SwitchMultilevelReport: ${cmd}"
String value = (cmd.value ? "on" : "off")
if (enableDesc && device.currentValue("switch") != value) log.info "${device.displayName} switch is ${value}"
sendEvent(name: "switch", value: value)
if (cmd.value) {
if (enableDesc && device.currentValue("level") != cmd.value) log.info "${device.displayName} level is ${cmd.value}%"
sendEvent(name: "level", value: cmd.value, unit: "%")
}
}

void zwaveEvent(hubitat.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
if (enableDebug) log.debug "CentralSceneNotification: ${cmd}"
Integer btnNum = 0
String btnAction = "pushed"
if (cmd.sceneNumber == 1) { // Up paddle
switch(cmd.keyAttributes as int) {
case 0:
btnNum = 1
break
case 1:
btnNum = 1
btnAction = "released"
break
case 2:
btnNum = 1
btnAction = "held"
break
case 3:
btnNum = 3
break
case 4:
btnNum = 5
break
case 5:
btnNum = 7
break
case 6:
btnNum = 9
break
}
}
else if (cmd.sceneNumber == 2) { // Down paddle
switch(cmd.keyAttributes as int) {
case 0:
btnNum = 2
break
case 1:
btnNum = 2
btnAction = "released"
break
case 2:
btnNum = 2
btnAction = "held"
break
case 3:
btnNum = 4
break
case 4:
btnNum = 6
break
case 5:
btnNum = 8
break
case 6:
btnNum = 10
break
}
}
else {
log.debug "Unable to parse: ${cmd}"
}
if (btnNum) {
String descriptionText = "${device.displayName} button ${btnNum} was ${btnAction}"
if (enableDesc) log.info "${descriptionText}"
sendEvent(name: "${btnAction}", value: btnNum, descriptionText: descriptionText, isStateChange: true, type: "physical")
}
}

void zwaveEvent(hubitat.zwave.Command cmd){
if (enableDebug) log.debug "skip: ${cmd}"
}

String flash() {
if (enableDesc) log.info "${device.getDisplayName()} was set to flash with a rate of ${flashRate ?: 750} milliseconds"
state.flashing = true
return flashOn()
}

String flashOn() {
if (!state.flashing) return
runInMillis((flashRate ?: 750).toInteger(), flashOff)
return zwaveSecureEncap(zwave.switchMultilevelV2.switchMultilevelSet(value: 0xFF, dimmingDuration: 0))
}

String flashOff() {
if (!state.flashing) return
runInMillis((flashRate ?: 750).toInteger(), flashOn)
return zwaveSecureEncap(zwave.switchMultilevelV2.switchMultilevelSet(value: 0x00, dimmingDuration: 0))
}

List refresh() {
if (enableDebug) log.debug "refresh"
return delayBetween([
zwaveSecureEncap(zwave.switchMultilevelV1.switchMultilevelGet()),
zwaveSecureEncap(zwave.configurationV1.configurationGet()),
zwaveSecureEncap(zwave.versionV2.versionGet())
], 150)
}

List configure() {
log.debug "configure()"
runIn(debugAutoDisableMinutes*60, logsOff)
sendEvent(name: "numberOfButtons", value: 10)
updated()
}

String on() {
if (enableDebug) log.debug "on()"
state.flashing = false
//hubitat.zwave.Command cmd = zwave.switchMultilevelV2.switchMultilevelSet(value: 0xFF)
// Using Basic instead because does not resepect Z-Wave parameter for rate with Mutlilevel:
hubitat.zwave.Command cmd = zwave.basicV1.basicSet(value: 0xFF)
return zwaveSecureEncap(supervisedEncap(cmd))
}

String off() {
if (enableDebug) log.debug "off()"
state.flashing = false
//hubitat.zwave.Command cmd = zwave.switchMultilevelV2.switchMultilevelSet(value: 0x00)
// Using Basic instead because does not resepect Z-Wave parameter for rate with Mutlilevel:
hubitat.zwave.Command cmd = zwave.basicV1.basicSet(value: 0x00)
return zwaveSecureEncap(supervisedEncap(cmd))
}

String setLevel(Number value) {
if (enableDebug) log.debug "setLevel($value)"
state.flashing = false
hubitat.zwave.Command cmd = zwave.switchMultilevelV2.switchMultilevelSet(value: value < 100 ? value : 99)
return zwaveSecureEncap(supervisedEncap(cmd))
}

String setLevel(Number value, Number duration) {
if (enableDebug) log.debug "setLevel($value, $duration)"
state.flashing = false
Integer dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
hubitat.zwave.Command cmd = zwave.switchMultilevelV2.switchMultilevelSet(value: value < 100 ? value : 99, dimmingDuration: dimmingDuration)
return zwaveSecureEncap(supervisedEncap(cmd))
}

String startLevelChange(String direction) {
Integer upDown = direction == "down" ? 1 : 0
return zwaveSecureEncap(zwave.switchMultilevelV1.switchMultilevelStartLevelChange(upDown: upDown, ignoreStartLevel: 1, startLevel: 0))
}

String stopLevelChange() {
return zwaveSecureEncap(zwave.switchMultilevelV1.switchMultilevelStopLevelChange())
}

void push(Integer btnNum) {
sendEvent(name: "pushed", value: btnNum, isStateChange: true, type: "digital")
}

void hold(Integer btnNum) {
sendEvent(name: "held", value: btnNum, isStateChange: true, type: "digital")
}

void release(Integer btnNum) {
sendEvent(name: "released", value: btnNum, isStateChange: true, type: "digital")
}

List getStatusLEDStates() {
List states = new ArrayList(7)
(1..7).each {
states.add(state."statusled${it}" ?: 0)
}
return states
}

List setNormalLEDColor(String color, setModeToNormal=false) {
if (enableDebug) log.debug "setNormalLEDColor(String $color, $setModeToNormal)"
List cmds =
Short colorNum = normalColorNameMap[color]
if (colorNum == null) {
log.error "Invalid color name specified: $color"
}
Boolean setToNormal = (!setModeToNormal || setModeToNormal == "false" ) ? false : true
return setNormalLEDColor(colorNum, setToNormal)
}

// Not exposed as command, but could be useful as alternate form; also used internally by the custom command:
List setNormalLEDColor(Short colorNum, Boolean setModeToNormal=false) {
if (enableDebug) log.debug "setNormalLEDColor(Short $color, $setModeToNormal)"
List cmds =
if (colorNum < 0 || colorNum > 7) {
log.error "Invalid color number specified: $colorNum"
}
else {
cmds.add(
setConfigParameter(14, colorNum, 1)
)
}
if (setModeToNormal) {
cmds.add(setConfigParameter(13, 0, 1))
}
return delayBetween(cmds, 750)
}

List setStatusLED(String ledNumber, String colorName, String blink) {
if (enableDebug) log.debug "setStatusLED(Integer $ledNumber, String $colorName, String $blink)"
List cmds =
Integer ledNum = Integer.parseInt(ledNumber)
Short colorNum = statusColorNameMap[colorName]
Boolean blinkOn = blink == "on" || blink == "ON" || blink == "On" || blink == "oN"
Short blinkBit = blinkOn ? 2**(ledNum-1) : 0b11111111 - 2**(ledNum-1)
Short newBlinkVal
if (ledNum < 1 || ledNum > 7) {
log.error "Invalid LED number specified: $ledNum"
return
}
else if (colorNum < 0 || colorNum > 7) {
log.error "Invalid color number specified: $colorNum"
return
}
if (blinkOn) {
newBlinkVal = (state.blinkval ?: 0) | blinkBit
}
else {
newBlinkVal = (state.blinkval ?: 0) & blinkBit
}

String cmd = setConfigParameter(ledNum + 20, colorNum, 1)
cmds.add(cmd)
if (newBlinkVal != state.blinkval) {
String cmd2 = setConfigParameter(31, newBlinkVal,1)
cmds.add(cmd2)
state.blinkval = newBlinkVal
}
state."statusled${ledNum}" = colorNum
// Device manual makes it sound like this happens automatically, but maybe that's HomeSeer behavior?
// Set to status mode if at least one LED set to status/color, otherwise set to normal
if (getStatusLEDStates().every { Integer i -> i == 0 }) {
cmds.add(setLEDMode("normal"))
}
else {
cmds.add(setLEDMode("status"))
}
return delayBetween(cmds, 750)
}

String setLEDMode(String mode) {
if (enableDebug) log.debug "setLEDMode($mode)"
Byte val = (mode.toLowerCase() == "status") ? 1 : 0
return setConfigParameter(13, val, 1)
}

String setLEDLevel(level) {
if (enableDebug) log.debug "setLEDLevel($level)"
BigInteger intLevel = new BigInteger(level)
return setConfigParameter(34, intLevel, 1)
}

String setConfigParameter(Integer number, BigInteger value, Integer size) {
if (enableDebug) log.debug "setConfigParameter(number: $number, value: $value, size: $size)"
hubitat.zwave.Command cmd = zwave.configurationV1.configurationSet(parameterNumber: number as Short, scaledConfigurationValue: value as BigInteger, size: size as Short)
//return zwaveSecureEncap(cmd)
return zwaveSecureEncap(supervisedEncap(cmd))
}

So today I DID get out with debug on

The state of the switch never changes in the device output

Device

Thank you for the information. (A link to the driver is generally easier than the raw code here, but a tip if you do: using the "code" formatting button on the editing toolbar, or surronding the block with three backticks, ```, generally makes it easier to read.) That looks like my driver, which I suggested as a likely possibility and provided a link to above.

The output you provided also looks consistent with the debug logging I'd expect.

This device behavior is mysterious, however. Are you using the device in switch mode or dimmer mode? The fact that there has apparently never been a meaningful "level" event or that something not apparent from this log snippet is getting parsed as 0 is odd if it's a dimmer. If it's in switch mode, there is a different driver (please see the link I provided above). I can't guarantee it won't have the same problem, as Z-Wave JS is again opinionated about what it sends to drivers in the first place, but this would be good to know before starting to look into this more.

2 Likes

I just tested my device in dimmer mode (which, upon closer inspection, you do appear to be using) and switch mode and was not able to replicate the problem. In my case, the device was newly included on Z-Wave JS, but I also tried downgrading to legacy and re-upgrading and was not able to reproduce then, either.

I'm not sure what's causing your problem. However, the first thing I'd try is a re-interview to see if it helps. Hit this endpoint (typing the address into the URL bar of your browser would work):

http://<hubIP>/home/zwave2/reinterview?node=<nodeID>

Substitute <hubIP> with your actual hub IP address, and substitute <nodeID> with the (decimal) Z-Wave node ID of this device. That is the one you can find in parentheses after the hex node ID on the Z-Wave Details page (but don't include the parentheses). Make sure the device is powered on -- able to receive Z-Wave commands -- when doing this.

If that doesn't help, an exclusion and re-inclusion might. You can swap it out with a virtual device in between (to make the process easier if you're using the device in any apps) if you want.

If the problem persists after that, I'd look at debug logs when sending the on and off commands and provide them here. Knowing your hub model, Z-Wave firmware version (output of the /hub/firmwareVersion endpoint), and exact WX-300 model (there are at least two) and firmware version (again at least two of these) may also matter, although I'm not aware of any changes that should affect this.

1 Like

Thanks for all your trouble and time! Will try some exclude/include stuff and see if it changes anything.

:grinning:Really confused

This may be a more global problem than your driver. When I did the JS upgrade...or let me at least say that "previously" since I can't swear to exactly when this changed...

Homeseer also see mys 200's a 300 now. I have no idea how...or if...this really impacts functionality.

HomeSeer or Hubitat?

If Hubitat,I don't see anything to suggest that in the screenshot above, except you're using a driver apparently written for the 200, which you would have had to have changed to (it's different from your screenshot above and the code you provided). The driver you're using is a key piece of this issue, and I wouldn't be surprised if you had problems for that reason.

The hardware type is version 1. It is a 200. That field USED to say 200. It now show it as 300. I can only "assume" that changed with the JS update...since out of all the things I looked at after the upgrade wasn't that. Maybe a version upgrade could do that too.

So a Hubitat issue ...not Homeseer. Do you have any idea if that is any more than a text field? IE - Does the hub use that in any way or depend on the driver...or both.

Between the two versions of these I have about 30 of them and are really familiar with them.

PS - Your driver is awesome and lets me control the LED's in rules with ease. Thanks!

I'm still confused what field you are talking about, as neither "300" nor "200" is anywhere outside your control in anything you've circled. A "hardware version" of "1" is also entirely plausible for this device -- that's always some integer value, normally unrelated to any marketing name the manufacturer may have for the device. (There are two generations, and it's possible the "WX300 R2" is hardware version 2, but I only have the original and don't know.) Some drivers uses this data in some way, but in most cases, it's unlikely to matter much, if it all (e.g., mine doesn't use anything here at all), but I still don't think I see anything odd.

I'm even more confused now, as you're saying you have a WD200 but put "300" in your topic title, were apparently using that driver above, but are now saying it's a "200"?

These devices are pretty similar, even their configuration parameters, to such an extent that some drivers could be interchangeable. But both the hub and my custom drivers have specific drivers for each, so it is important to be clear about what hardware you are using and what driver you're using. Unfortunately, the more answers I get to these questions, the more confusing things seem to get. :slight_smile:

EDIT: OK, nevermind, I re-read the post above and you have both but see "300" for the "200" models? That's just the "Device Name," which is set by the hub with the driver name upon inclusion. Apparently, that's what it matched with then. If you changed the driver, as you must have, the "Device Name" is just an artifact of this history. It's entirely within your control what you do with the Device Name after this, at least with Z-Wave devices, or you can set a Device Label to override the display name, as you also have.

EDIT 2: No, wait, I looked at the Device Data for the device you have using the WD200+ driver and that's definitely a WX300, as the Z-Wave device data matches. The WD200+ would have a device ID of 12342. So, back to confusion. :slight_smile: (Are you sure you didn't change a driver somewhere?)

1 Like