Problem with Leviton dimmer DZPD3

Just switched from Wink. Their Hub 2 worked flawlessly with these zWave Plus dimmers.

These dimmers are recognized as generic zWave smart dimmers by HE. However the dashboard never updates their status when they're turned on and off. It shows an hourglass that stays there forever.

The solution is to downgrade them to generic zWave dimmers. Then they update as expected. But... when I turn on the light, the dimmer is systematically sent two commands by the hub. Here are the two log entries generated following a single click to turn the light on:
level changed to 99 on 11/5/2019 8:31
switch changed to on on 11/5/2019 8:31

I never asked for a level change. With Wink, the lights always came back on at the level at which they were last set .

This is extremely annoying. I use voice commands (using Google Home) all the time to turn certain lights ON or OFF. I'm not going to start specifying the intensity each time for certain lights that I always turn ON at the same intensity below 100%!

There's another problem with these dimmers that I haven't figured out how to reproduce yet. I've been playing a lot with the dashboard (both local and cloud) and eventually the light I play with will be stuck at approximately 10% intensity (judging by what I see, not reported by software). Everything looks fine on the screen, the intensity is reported as 100% as requested, but it actually stays at about 10% and won't change. The light can only be turned on and off. I've never seen this before. The only way to solve the problem is to exclude the dimmer from the network, and include it again. If I play for a while, it's guaranteed to end up happening. It must have happened 3 or 4 times in an evening and the next morning. I don't expect any help on this issue unless someone recognizes the problem and knows the solution. I may mention it again if I find out how to reproduce it.

The problem I'd really like to solve now is that of the two commands generated (ON + 100% level) when a light is turned ON. This is really a major annoyance.

1 Like

Hello, and welcome to Hubitat!

First of all, I have one of these devices. I'm not using it yet as the project I had it planned for got scrubbed for a different reason and I haven't found another use for it yet. But I have played around with it some. For starters, you have to use the Generic Z-wave Smart Dimmer driver. This device is equipped with Z-wave Plus not regular Z-wave which means you have to use the generic Z-wave smart Dimmer driver.

When you issue an On command to the device, via the edit device page or through an automation, it will return to the last level you had it set to. If you turn it on via the button on the device, then it returns to 100%. That is a function of the firmware, not of HE. HE has nothing to do with what the device is doing on it's own when the onboard button is pushed.

Also, button presses on the device do not seem to update correctly in HE until you do a refresh. That is not surprising as the button is really only intended to be a backup and not a primary means of control.

As for the dashboard problem, when I add mine to a dashboard using the Dimmer Tile, everything works correctly. What time for refresh do you have set for that dashboard? Is it local or is it cloud?

So, I think you need to switch it back to the Generic Z-wave Smart Dimmer driver and then deal with the dashboard issue separately. I am not seeing 2 commands being sent to my device when it turn it on or off. This is what i see on the events page for the device.

Hi,

Thanks for the welcome. Despite my problems, I'm starting to see an interesting potential here!

Ok, so you suggest to deal with the dashboard issue separately. Why not.

I then stayed on the devices page. I switched the device to a smart dimmer. I can control the light with the device page buttons. And when I display the events on the same page, it no longer logs any events after the device type switch. I went to the dashboard (couldn't resist...) and had the same problem: screen no longer updating, and history (events accessible from that page) no longer updated. I surmise that the unit is receiving commands but no longer reports its status. That would explain everything.

To answer your comment on commands issued using the button on the unit, I didn't mention anything about it but here's what happens when I use the hardware button:
device configured as a smart dimmer:
starting conditions: off using button; intensity 100%;
I do the following:
1 turn bulb on, then off using 'edit device' screen;
... no logging
2 turn bulb on, then off using hardware button;
|switch|off||escalier was turned off [physical]|DEVICE|physical|2019-05-11 22:36:43.829 EDT|
|switch|on||escalier was turned on [physical]|DEVICE|physical|2019-05-11 22:34:52.123 EDT|

3 set intensity to 50% using device screen;

4 turn off through device screen;
... no logging

5 turn on using button; (indicator on button goes off, light turns ON)
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 22:36:43.829 EDT

6 **press button again (indicator on button comes on, light turns OFF) **
....... no logging,

7 ** press button again (indicator on button toggles off; light turns ON at 50%)**
|level|50|%|escalier was set to 50% [physical]|DEVICE|physical|2019-05-11 22:42:50.524 EDT|
|switch|on||escalier was turned on [physical]|DEVICE|physical|2019-05-11 22:42:50.522 EDT|

8 ** press button (indicator toggles ON; lights turns OFF) **
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 22:44:31.719 EDT

9 ** turn light ON using device list (indicator toggles off; light turns ON at 100%) **
...... no logging

10- ** turn light OFF using device list (indicator toggles ON; light turns OFF) **
... no logging

11- ** turn light ON using hardware button (indicator toggles OFF; light turns ON at 100%) **
...... no logging

12- ** turn light OFF via button (indicator toggles ON; light turns OFF) **
...... no logging

13- ** turn light ON via button (indicator toggles OFF; light turns ON at 100%) **
|level|99|%|escalier was set to 99% [physical]|DEVICE|physical|2019-05-11 22:50:19.936 EDT|
|switch|on||escalier was turned on [physical]|DEVICE|physical|2019-05-11 22:50:19.932 EDT|

14- ** turn light OFF via button (indicator toggles ON; light turns OFF) **
|switch|off||escalier was turned off [physical]|DEVICE|physical|2019-05-11 22:51:51.226 EDT|

Conclusion:

  • the hardware button always turns the light ON at the level at which it was set when it was turned OFF.
  • turning ON the light using the software systematically sets the intensity at 100%.
  • the 'smart' dimmer returns nothing when issued commands by the software. It returns status info only when executing commands via the button.

Here's the same test with the non-smart (dumb?) dimmer:
1 turn bulb on, then off using 'edit device' screen;
switch off escalier was turned off [digital] DEVICE digital 2019-05-11 23:02:30.962 EDT
switch on escalier was turned on [digital] DEVICE digital 2019-05-11 23:02:00.761 EDT

turn bulb on, then off using hardware button;
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 23:04:50.245 EDT
switch on escalier was turned on [physical] DEVICE physical 2019-05-11 23:04:22.463 EDT

3 set intensity to 50% using device screen;
|level|50||escalier was set to 50% [digital]|DEVICE|digital|2019-05-11 23:05:29.606 EDT|
|switch|on||escalier was turned on [digital]|DEVICE|digital|2019-05-11 23:05:29.602 EDT|

4 turn off through device screen;
switch|off||escalier was turned off [digital]|DEVICE|digital|2019-05-11 23:06:08.405 EDT|

5 turn on using button; (indicator on button goes off, light turns ON)
switch on escalier was turned on [physical] DEVICE physical 2019-05-11 23:07:08.324 EDT

6 **press button again (indicator on button comes on, light turns OFF) **
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 23:08:42.828 EDT

7 ** press button again (indicator on button toggles off; light turns ON at 50%)**
switch on escalier was turned on [physical] DEVICE physical 2019-05-11 23:09:29.657 EDT

8 ** press button (indicator toggles ON; lights turns OFF) **
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 23:09:59.673 EDT

9 ** turn light ON using device list (indicator toggles off; light turns ON at 100%) **
level|99||escalier was set to 99% [digital]|DEVICE|digital|2019-05-11 23:10:33.609 EDT|
switch|on||escalier was turned on [digital]|DEVICE|digital|2019-05-11 23:10:33.606 EDT|

10- ** turn light OFF using device list (indicator toggles ON; light turns OFF) **
switch off escalier was turned off [digital] DEVICE digital 2019-05-11 23:11:14.111 EDT

11- ** turn light ON using hardware button (indicator toggles OFF; light turns ON at 100%) **
switch on escalier was turned on [physical] DEVICE physical 2019-05-11 23:12:04.564 EDT

12- ** turn light OFF via button (indicator toggles ON; light turns OFF) **
switch|off||escalier was turned off [physical]|DEVICE|physical|2019-05-11 23:12:30.095 EDT|

13- ** turn light ON via button (indicator toggles OFF; light turns ON at 100%) **
switch on escalier was turned on [physical] DEVICE physical 2019-05-11 23:12:56.849 EDT

14- ** turn light OFF via button (indicator toggles ON; light turns OFF) **
switch off escalier was turned off [physical] DEVICE physical 2019-05-11 23:13:23.726 EDT

Conclusion:

  • all interactions logged properly;
  • hardware button not interfering with previously set level value;
  • turning light ON via device page systematically sets intensity at 100%.

This seems consistent with my observations regarding the dashboard. The absence of logging with the smart dimmer configuration explains the dashboard failing to update.

If only the 100% level command wasn't sent by the hub (apparently...) when the light is turned ON, there would be no problem.

My dimmers were purchased in 2017 (they're z-wave Plus compatible). I know that there's been a firmware upgrade for some dimmer models (to 1.2... but I have no way of knowing 1) what my current firmware is 2) if this would solve the problem).

What makes me think that the hub may be to blame is that the Wink hub 2 doesn't have this problem.

After you change the driver, you have to hit "configure" on the device edit page. Did you do that when you changed drivers?

All I know is that mine is working fine and I have the same model number. When I turn the device on via the On command (on button on the edit device page) it returns to the previous set level. If yours is not doing that and you have it set to the Generic Z-wave Smart Dimmer driver and you have hit the configure button, you can try to remove/exclude the device and add it again. If that doesn't fix it then I would contact support at support@hubitat.com. But the problem is definitely not the hub software in general.

This does not happen. I don't know why you insist on thinking it does. When you say "turn device on via device list, what are you talking about? There is no control available in the device list.

I'm having a lot of trouble following your big long list of activities because a lot of them don't make sense.

This is because the last time you turned it on was with the physical button which always turns it on to 100%, no matter what is displayed in HE.

If you use the physical button, you have to hit Refersh to get the right value to display.

This is not true.

After you change the driver, you have to hit "configure" on the device edit page. Did you do that when you changed drivers?

No. But just did. No change. Same behavior. Excluded and added again. No change.

hmm... I don't get what it is that makes no sense. If it's the mention of the 'device list', just replace all instances with 'device page accessed from the device list'.

Concerning "this does not happen. I don't know why you insist on thinking it does", well... I can turn the light ON and OFF repeatedly using the physical button, and the intensity value remains unchanged (contrary to your assertion that it should go to 100%), and a series of [physical] 'turn off' and 'turn on' commands are logged. As soon as I turn the light ON through the device page, the log includes an unwanted [digital] level setting command (at 99%). See step 9 for both drivers. In other words, what I see is the exact opposite of the behavior you describe.

I have no problem with displayed values. I see the light: it's on my desk.

...
Thank you for your time.

Can you show a screenshot of the edit device page?

Many Leviton users have to update the firmware on these devices to get them to report their status correctly.

See the following and other posts like it...

1 Like

Yeah... I had read this but I'd like to know how to determine if a firmware to 1.2 would change anything. I'd feel pretty stupid if I purchased the thing and was told that I already have the latest firmware version when trying to perform the update. My questions would be:

  1. is there any way to know the current firmware version?
  2. if I buy this thing (HomeSeer Z-Flash Z-Wave Firmware Update Kit – HomeSeer Store) am I good to go or will I find out later that I need something else to communicate with the devices?

Finally, I find this problem a bit perplexing. If the firmware is to blame, how does this explain that the log shows a command issued by the hub setting the level to 100% whenever the light is turned ON (with digital command) if the level is not already 100%?? If this level change command comes from the hub, how would a firmware update in the device change what the hub does?

As I have said, the hub doesn't do that. Your device data doesn't look the same as mine. Are you on the latest firmware?

Do this. Exclude the device from Hubitat and re-add it. After you do, set the light to 50% via the edit device page by entering 50 under setLevel and then clicking set level. What level does it display on the edit device page? What level is the lamp?
Then, turn the device off, then on via the edit device page. What level is displayed on the edit device page? What level is the lamp in reality?

Did all that... same result as before.

  • set level to 50% -> light comes on at 50%, 50 shown on screen;
  • turn light off then on -> light comes on at 100%, 99 shown on screen. (same result as step 9 in earlier post)

I think I'm going to order the HomeSeer Z-Flash Z-Wave Firmware Update Kit. It's much cheaper than changing my dimmers.

I’ve got one of these (all of my dimmers are z-wave Leviton).

In earlier versions of the Hubitat software, there was a different Leviton Fan controller driver that worked as expected with this.

You can try the newest version of that for instant on/off status with this device, but I don’t think Level works anymore since it’s an actual fan device type, now.

I’ve got a box with a ton of Leviton dimmers and switches I’ll be shipping to @mike.maxwell this week for him to hopefully re-release that driver, or add functionality to the smart dimmer driver.

can you show the edit device page again? You are on the latest firmware, correct?

I don't understand how I can show the edit device page "again"... If I showed it once, isn't it still up there? ah... if for some reason you get these posts by email and deleted the previous one, here you go again:

Concerning the firmware version, it's something I've been wondering since the beginning. I have no idea how I can tell which version I have from the device details on the edit device page...

If you did what I suggested and excluded the device and re-joined it to the hub, the device details could have changed. Did you do that? When I compare yours to mine, they don't match.

And that is suspect to me.

There is no way to tell the firmware version from Hubitat. What i meant was are you at the latest HUBITAT firmware?

You can tell the firmware version by using the basic z-wave tool.

no updates available..(currently running version 2.0.9.133)

By the firmware version, you mean that of the dimmer, I assume. I installed the basic z-wave tool as device driver for the dimmer. All tiles are unresponsive (getVersionReport, getAssociationReport, etc).

I think I know the problem. When you have a fade time set in the device, it actually is fading down to zero. So, when you turn it back on, there is no setting for it to use other than 100 because that's it's default setting. I had my fade times at zero and didn't see the behavior you saw. I swapped my fade times to 5 and bingo, that's when the device set itself to 100% when the on-command was sent.

Use the following driver ported over from ST and you will be all set.

/**
 *
 *  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.
 *
 * Adapted for Hubitat based on the Leviton Decora Z-Wave Plus Dimmer DTH developed by Jason Xia (jasonxh) for SmartThings
 */
metadata {
    definition (name: "Leviton Z-Wave Plus Dimmer", namespace: "ryan780", author: "Ryan C.") {
        capability "Actuator"
        capability "Configuration"
        capability "Health Check"
        capability "Indicator"
        capability "Light"
        capability "Polling"
        capability "Refresh"
        capability "Sensor"
        capability "Switch"
        capability "Switch Level"

        attribute "loadType", "enum", ["incandescent", "led", "cfl"]
        attribute "presetLevel", "number"
        attribute "minLevel", "number"
        attribute "maxLevel", "number"
        attribute "fadeOnTime", "number"
        attribute "fadeOffTime", "number"
        attribute "levelIndicatorTimeout", "number"
        attribute "firmwareVersion", "string"

        command "low"
        command "medium"
        command "high"
        command "levelUp"
        command "levelDown"
    }


    preferences {
        input name: "levelIncrement", type: "number", title: "In-App Level Increment",
                description: "1 - 100 (default $defaultLevelIncrement)", range: "1..100", defaultValue: defaultLevelIncrement,
                displayDuringSetup: false, required: false

        input type: "paragraph", element: "paragraph", title: "Device Preferences",
                description: "The following preferences are configuring the device behaviors. " +
                        "All of them are optional. Leave a preference empty to skip configuring it."

        input name: "loadType", type: "enum", title: "Load type",
                options: ["Incandescent (default)", "LED", "CFL"],
                displayDuringSetup: false, required: false
        input name: "indicatorStatus", type: "enum", title: "Indicator LED is lit",
                options: ["When switch is off (default)", "When switch is on", "Never"],
                displayDuringSetup: false, required: false
        input name: "presetLevel", type: "number", title: "Light turns on to level",
                description: "0 to 100 (default 0)", range: "0..100",
                displayDuringSetup: false, required: false
        input type: "paragraph", element: "paragraph", title: "",
                description: "0 = last dim level (default)\n1 - 100 = fixed level"
        input name: "minLevel", type: "number", title: "Minimum light level",
                description: "0 to 100 (default 10)", range: "0..100",
                displayDuringSetup: false, required: false
        input name: "maxLevel", type: "number", title: "Maximum light level",
                description: "0 to 100 (default 100)", range: "0..100",
                displayDuringSetup: false, required: false
        input name: "fadeOnTime", type: "number", title: "Fade-on time",
                description: "0 to 253 (default 2)", range: "0..253",
                displayDuringSetup: false, required: false
        input type: "paragraph", element: "paragraph", title: "",
                description: "0 = instant on\n1 - 127 = 1 - 127 seconds (default 2)\n128 - 253 = 1 - 126 minutes"
        input name: "fadeOffTime", type: "number", title: "Fade-off time",
                description: "0 to 253 (default 2)", range: "0..253",
                displayDuringSetup: false, required: false
        input type: "paragraph", element: "paragraph", title: "",
                description: "0 = instant off\n1 - 127 = 1 - 127 seconds (default 2)\n128 - 253 = 1 - 126 minutes"
        input name: "levelIndicatorTimeout", type: "number", title: "Dim level indicator timeout",
                description: "0 to 255 (default 3)", range: "0..255",
                displayDuringSetup: false, required: false
        input type: "paragraph", element: "paragraph", title: "",
                description: "0 = dim level indicator off\n1 - 254 = timeout in seconds (default 3)\n255 = dim level indicator always on"
    }
}

def installed() {
    log.debug "installed..."
    initialize()
    response(refresh())
}

def updated() {
    if (state.lastUpdatedAt != null && state.lastUpdatedAt >= now() - 1000) {
        log.debug "ignoring double updated"
        return
    }
    log.debug "updated..."
    state.lastUpdatedAt = now()

    initialize()
    response(configure())
}

def configure() {
    def commands = []
    if (loadType != null) {
        commands.addAll(setLoadType(loadType))
    }
    if (indicatorStatus != null) {
        commands.addAll(setIndicatorStatus(indicatorStatus))
    }
    if (presetLevel != null) {
        commands.addAll(setPresetLevel(presetLevel as short))
    }
    if (minLevel != null) {
        commands.addAll(setMinLevel(minLevel as short))
    }
    if (maxLevel != null) {
        commands.addAll(setMaxLevel(maxLevel as short))
    }
    if (fadeOnTime != null) {
        commands.addAll(setFadeOnTime(fadeOnTime as short))
    }
    if (fadeOffTime != null) {
        commands.addAll(setFadeOffTime(fadeOffTime as short))
    }
    if (levelIndicatorTimeout != null) {
        commands.addAll(setLevelIndicatorTimeout(levelIndicatorTimeout as short))
    }
    log.debug "Configuring with commands $commands"
    commands
}

def parse(String description) {
    def result = null
    def cmd = zwave.parse(description, [0x20: 1, 0x25:1, 0x26: 1, 0x70: 1, 0x72: 2])
    if (cmd) {
        result = zwaveEvent(cmd)
        log.debug "Parsed $cmd to $result"
    } else {
        log.debug "Non-parsed event: $description"
    }
    result
}

def on() {
    def fadeOnTime = device.currentValue("fadeOnTime")
    def presetLevel = device.currentValue("presetLevel")

    short duration = fadeOnTime == null ? 255 : fadeOnTime
    short level = presetLevel == null || presetLevel == 0 ? 0xFF : toZwaveLevel(presetLevel as short)
    delayBetween([
            zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: duration).format(),
            zwave.switchMultilevelV1.switchMultilevelGet().format()
    ], durationToSeconds(duration) * 1000 + commandDelayMs)
}

def off() {
    def fadeOffTime = device.currentValue("fadeOffTime")

    short duration = fadeOffTime == null ? 255 : fadeOffTime
    delayBetween([
            zwave.switchMultilevelV2.switchMultilevelSet(value: 0x00, dimmingDuration: duration).format(),
            zwave.switchMultilevelV1.switchMultilevelGet().format()
    ], durationToSeconds(duration) * 1000 + commandDelayMs)
}

def setLevel(value, durationSeconds = null) {
    log.debug "setLevel >> value: $value, durationSeconds: $durationSeconds"
    short level = toDisplayLevel(value as short)
    short dimmingDuration = durationSeconds == null ? 255 : secondsToDuration(durationSeconds as int)

    sendEvent(name: "level", value: level, unit: "%")
    sendEvent(name: "switch", value: level > 0 ? "on" : "off")
    delayBetween([
            zwave.switchMultilevelV2.switchMultilevelSet(value: toZwaveLevel(level), dimmingDuration: dimmingDuration).format(),
            zwave.switchMultilevelV1.switchMultilevelGet().format()
    ], durationToSeconds(dimmingDuration) * 1000 + commandDelayMs)
}

def poll() {
    delayBetween(statusCommands, commandDelayMs)
}

def ping() {
    poll()
}

def refresh() {
    def commands = statusCommands
    commands << zwave.versionV1.versionGet().format()

    if (getDataValue("MSR") == null) {
        commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
    }
    for (i in 1..8) {
        commands << zwave.configurationV1.configurationGet(parameterNumber: i).format()
    }
    log.debug "Refreshing with commands $commands"
    delayBetween(commands, commandDelayMs)
}

def indicatorNever() {
    sendEvent(name: "indicatorStatus", value: "never")
    configurationCommand(7, 0)
}

def indicatorWhenOff() {
    sendEvent(name: "indicatorStatus", value: "when off")
    configurationCommand(7, 255)
}

def indicatorWhenOn() {
    sendEvent(name: "indicatorStatus", value: "when on")
    configurationCommand(7, 254)
}

def low() {
    setLevel(10)
}

def medium() {
    setLevel(50)
}

def high() {
    setLevel(100)
}

def levelUp() {
    setLevel(device.currentValue("level") + (levelIncrement ?: defaultLevelIncrement))
}

def levelDown() {
    setLevel(device.currentValue("level") - (levelIncrement ?: defaultLevelIncrement))
}


private static int getCommandDelayMs() { 1000 }
private static int getDefaultLevelIncrement() { 10 }

private initialize() {
    // Device-Watch simply pings if no device events received for 32min(checkInterval)
    sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
}

private zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
    dimmerEvent(cmd.value)
}

private zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
    dimmerEvent(cmd.value)
}

private zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
    response(zwave.switchMultilevelV1.switchMultilevelGet().format())
}

private zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
    if (cmd.value == 0) {
        switchEvent(false)
    } else if (cmd.value == 255) {
        switchEvent(true)
    } else {
        log.debug "Bad switch value $cmd.value"
    }
}

private zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
    def result = null
    switch (cmd.parameterNumber) {
        case 1:
            result = createEvent(name: "fadeOnTime", value: cmd.configurationValue[0])
            break
        case 2:
            result = createEvent(name: "fadeOffTime", value: cmd.configurationValue[0])
            break
        case 3:
            result = createEvent(name: "minLevel", value: cmd.configurationValue[0])
            break
        case 4:
            result = createEvent(name: "maxLevel", value: cmd.configurationValue[0])
            break
        case 5:
            result = createEvent(name: "presetLevel", value: cmd.configurationValue[0])
            break
        case 6:
            result = createEvent(name: "levelIndicatorTimeout", value: cmd.configurationValue[0])
            break
        case 7:
            def value = null
            switch (cmd.configurationValue[0]) {
                case 0: value = "never"; break
                case 254: value = "when on"; break
                case 255: value = "when off"; break
            }
            result = createEvent(name: "indicatorStatus", value: value)
            break
        case 8:
            def value = null
            switch (cmd.configurationValue[0]) {
                case 0: value = "incandescent"; break
                case 1: value = "led"; break
                case 2: value = "cfl"; break
            }
            result = createEvent(name: "loadType", value: value)
            break
    }
    result
}

private zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
    log.debug "manufacturerId:   $cmd.manufacturerId"
    log.debug "manufacturerName: $cmd.manufacturerName"
    log.debug "productId:        $cmd.productId"
    log.debug "productTypeId:    $cmd.productTypeId"
    def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
    updateDataValue("MSR", msr)
    updateDataValue("manufacturer", cmd.manufacturerName)
    createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}

private zwaveEvent(hubitat.zwave.commands.hailv1.Hail cmd) {
    createEvent(name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false)
}

private zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
    createEvent(name: "firmwareVersion", value: "${cmd.applicationVersion}.${cmd.applicationSubVersion}", displayed: false)
}

private zwaveEvent(hubitat.zwave.Command cmd) {
    log.warn "Unhandled zwave command $cmd"
}

private dimmerEvent(short level) {
    def result = null
    if (level == 0) {
        result = [createEvent(name: "level", value: 0, unit: "%"), switchEvent(false)]
    } else if (level >= 1 && level <= 100) {
        result = [createEvent(name: "level", value: toDisplayLevel(level), unit: "%")]
        if (!isNewFirmware && device.currentValue("switch") != "on") {
            // Don't blindly trust level. Explicitly request on/off status.
            result << response(zwave.switchBinaryV1.switchBinaryGet().format())
        } else {
            result << switchEvent(true)
        }
    } else {
        log.debug "Bad dimming level $level"
    }
    result
}

private switchEvent(boolean on) {
    createEvent(name: "switch", value: on ? "on" : "off")
}

private getStatusCommands() {
    def cmds = []
    if (!isNewFirmware) {
        // Even though SwitchBinary is not advertised by this device, it seems to be the only way to assess its true
        // on/off status.
        cmds << zwave.switchBinaryV1.switchBinaryGet().format()
    }
    cmds << zwave.switchMultilevelV1.switchMultilevelGet().format()
    cmds
}

private short toDisplayLevel(short level) {
    level = Math.max(0, Math.min(100, level))
    (level == (short) 99) ? 100 : level
}

private short toZwaveLevel(short level) {
    Math.max(0, Math.min(99, level))
}

private int durationToSeconds(short duration) {
    if (duration >= 0 && duration <= 127) {
        duration
    } else if (duration >= 128 && duration <= 254) {
        (duration - 127) * 60
    } else if (duration == 255) {
        2   // factory default
    } else {
        log.error "Bad duration $duration"
        0
    }
}

private short secondsToDuration(int seconds) {
    if (seconds >= 0 && seconds <= 127) {
        seconds
    } else if (seconds >= 128 && seconds <= 127 * 60) {
        127 + Math.round(seconds / 60)
    } else {
        log.error "Bad seconds $seconds"
        255
    }
}

private configurationCommand(param, value) {
    param = param as short
    value = value as short
    delayBetween([
            zwave.configurationV1.configurationSet(parameterNumber: param, configurationValue: [value]).format(),
            zwave.configurationV1.configurationGet(parameterNumber: param).format()
    ], commandDelayMs)
}

private setFadeOnTime(short time) {
    sendEvent(name: "fadeOnTime", value: time)
    configurationCommand(1, time)
}

private setFadeOffTime(short time) {
    sendEvent(name: "fadeOffTime", value: time)
    configurationCommand(2, time)
}

private setMinLevel(short level) {
    sendEvent(name: "minLevel", value: level)
    configurationCommand(3, level)
}

private setMaxLevel(short level) {
    sendEvent(name: "maxLevel", value: level)
    configurationCommand(4, level)
}

private setPresetLevel(short level) {
    sendEvent(name: "presetLevel", value: level)
    configurationCommand(5, level)
}

private setLevelIndicatorTimeout(short timeout) {
    sendEvent(name: "levelIndicatorTimeout", value: timeout)
    configurationCommand(6, timeout)
}

private setLoadType(String loadType) {
    switch (loadType) {
        case "Incandescent (default)":
            sendEvent(name: "loadType", value: "incandescent")
            return configurationCommand(8, 0)
        case "LED":
            sendEvent(name: "loadType", value: "led")
            return configurationCommand(8, 1)
        case "CFL":
            sendEvent(name: "loadType", value: "cfl")
            return configurationCommand(8, 2)
    }
}

private setIndicatorStatus(String status) {
    switch (indicatorStatus) {
        case "When switch is off (default)":    return indicatorWhenOff()
        case "When switch is on":               return indicatorWhenOn()
        case "Never":                           return indicatorNever()
    }
}

private boolean getIsNewFirmware() { device.currentValue("firmwareVersion") ==~ /1\.2\d/ }

There's more stuff in here to clean up to play nicer with Hubitat vs. ST but this should at least get you started with something that should work. I'll post an update when I've cleaned it up.

4 Likes

Use the basic z-wave tool to interrogate the device for firmware version, the result will be printed in the log.

Then change it back to its normal device driver.