/* * ================ Zooz Dimmer Scene Controller (ZEN35) Driver ================= * * Copyright 2025 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. * * ======================================================================================= * * BUTTON NUMBER/EVENT MAPPING: * * "Base" button number: * - relay/large button = button 5 * - small top left = button 1 * - small top right = button 2 * - small bottom left = button 3 * - small bottom right = button 4 * Single taps, hold, and release: * - base button number pushed, held, and released events * Multi-taps: * - mathematically, a pushed event for button number = (base button number) + (5 * (number of taps - 1)) ... or specifically: * * "button 1" taps: button 1, 6, 11, 16, or 21 pushed (taps 1-5) * * "button 2" taps: button 2, 7, 12, 17, or 22 pushed (taps 1-5) * * "button 3" taps: button 3, 8, 13, 18, or 23 pushed (taps 1-5) * * "button 4" taps: button 4, 9, 14, 19, or 24 pushed (taps 1-5) * * "button 5" taps: button 5, 10, 15, 20, or 25 pushed (taps 1-5) * * * Changelog: * v1.0.1 (2025-04-22): Change order of relay LED paramter display to make easier to see; elevate log to warning if using setLED for this button but not configured to follow * v1.0 (2025-04-18): Initial release, based on ZEN32 driver */ import groovy.transform.Field @Field static final Map commandClassVersions = [ 0x20: 1, // Basic 0x26: 3, // SwitchMultilevel 0x55: 1, // TransportService 0x59: 1, // AssociationGroupInfo 0x5B: 1, // CentralScene 0x6C: 1, // Supervision 0x70: 1, // Configuration 0x72: 2, // ManufacturerSpecific 0x85: 1, // Association 0x86: 2, // Version 0x87: 3, // Indicator 0x8E: 2, // MultichannelAssociation 0x98: 1, // Security 0x9F: 1 // Security S2 ] // color name to parameter value mapping: @Field static final TreeMap colorNameMap = [ 0:"white", 1:"blue", 2:"green", 3:"red", 4:"magenta", 5:"yellow", 6:"cyan" ] // LED/button number to parameter value mappings (for LED color parameters): @Field static final Map ledIndicatorParams = [1: 2, 2: 3, 3: 4, 4: 5, 5: 1] @Field static final Map ledColorParams = [1: 7, 2: 8, 3: 9, 4: 10, 5: 6] @Field static final Map ledBrightnessParams = [1: 12, 2: 13, 3: 14, 4: 15, 5: 11] // LED number mappings for Indicator command class: @Field static Map indicatorLEDNumberMap = [0:0x50, 5:0x43, 1:0x44, 2:0x45, 3:0x46, 4:0x47] @Field static final Map zwaveParameters = [ 16: [input: [name: "param.16", type: "number", title: "[16] Automatically turn relay off after ... minutes (0=disable auto-off; default)", range: 0..65535], size: 4], 17: [input: [name: "param.17", type: "number", title: "[17] Automatically turn relay on after ... minutes (0=disable auto-on; default)", range: 0..65535], size: 4], 18: [input: [name: "param.18", type: "enum", title: "[18] State on power restore (relay and buttons)", options: [[1: "Off"], [2: "On"], [0: "Previous state (default)"]]], size: 1], 19: [input: [name: "param.19", type: "enum", title: "[19] Local (physical) and Z-Wave control/smart bulb mode", options: [[0: "Disable local control, enable Z-Wave"], [1: "Enable local and Z-Wave control (default)"], [2: "Disable local and Z-Wave control"]]], size: 1], 20: [input: [name: "param.20", type: "enum", title: "[20] Behavior of relay reports if local and/or Z-Wave control disabled (scene/button events are always sent)", options: [[0:"Send on/off reports and change LED (default)"],[1:"Do not send on/off reports or change LED"]]], size: 1], 21: [input: [name: "param.21", type: "enum", title: "[21] Ramp rate for physical on", options: [[0:"ASAP (default)"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds"], [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], [99:"99 seconds"]]], size: 1], 21: [input: [name: "param.22", type: "enum", title: "[22] Ramp rate for physical off", options: [[0:"ASAP (default)"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds"], [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], [99:"99 seconds"]]], size: 1], 23: [input: [name: "param.23", type: "enum", title: "[23] Ramp rate for physical dimming (0-99 speed)", options: [[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds (default)"], [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], [99:"99 seconds"]]], size: 1], 24: [input: [name: "param.24", type: "enum", title: "[24] Ramp rate for Z-Wave on", options: [[0:"ASAP (default)"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds"], [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], [99:"99 seconds"]]], size: 1], 25: [input: [name: "param.25", type: "enum", title: "[25] Ramp rate for Z-Wave off", options: [[0:"ASAP (default)"],[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds"], [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], [99:"99 seconds"]]], size: 1], // 26: [input: [name: "param.26", type: "enum", title: "[26] Ramp rate for Z-Wave dimming (0-99 speed) for association groups 3 and 4", // options: [[1:"1 second"],[2:"2 seconds"],[3:"3 seconds"],[4:"4 seconds"],[5:"5 seconds (default)"], // [7:"7 seconds"],[10:"10 seconds"],[15:"15 seconds"],[20:"20 seconds"],[30:"30 seconds"], [45:"45 seconds"],[60:"60 seconds"], // [99:"99 seconds"]]], // size: 1], 27: [input: [name: "param.27", type: "number", range:"1..99", title: "[27] Minimum brightness (default: 1)"], size: 1], 28: [input: [name: "param.28", type: "number", range:"1..99", title: "[28] Maximum brightness (default: 99)"], size: 1], 29: [input: [name: "param.29", type: "enum", title: "[29] Button 5 double-tap behavior", options: [[0:"On to full brightness (default; parameter 28 will not be available)"], [1:"On to custom brightness (from parameter 31)"], [2:"On to maximum brightness (from parameter 28)"]]], size: 1], 30: [input: [name: "param.30", type: "enum", title: "[30] Button 5 single-tap behavior", options: [[0:"On to last brightness (default)"], [1:"On to custom brightness (from parameter 31)"], [2:"On to maximum brightness (from parameter 28)"], [3:"On to full brightness (may disable parameter 28?)"]]], size: 1], 31: [input: [name: "param.31", type: "number", range:"0..99", title: "[31] Button 5 brightness for phyiscal taps (1-99, or 0 for last)"], size: 1], 32: [input: [name: "param.32", type: "enum", title: "[32] 3-way switch type", options: [[0:"Toggle on/off switch (default)"],[1:"Toggle switch with dimming mode"], [2:"Momentary (connected 3-way toggles on/off)"],[3:"Momentary switch with smart sequence"]]], size: 1], 33: [input: [name: "param.33", type: "enum", title: "[33] 3-way switch type", options: [[0:"Report each level if phyiscal and Z-Wave control disabled (final level only if enabled)"], [1:"Always report final level only"], [2:"Report each level if physical and Z-Wave control disabled (final level only if enabled), use Multilevel reporr (default)"]]], size: 1], 34: [input: [name: "param.34", type: "enum", title: "[34] Disable Z-Wave programming (except reset and scenes) on button 5", options: [[0:"Enabled (default)"],[1:"Disabled (allows triple-tap w/o activating exclusion mode)"]]], size: 1], 36: [input: [name: "param.36", type: "enum", title: "[36] Enable scene control on button 5", options: [[1:"Enabled (default)"],[0:"Disabled (multi-taps no longer possible but reduces delay)"]]], size: 1], 37: [input: [name: "param.26", type: "enum", title: "[37] Enable scene control (2- and 3-tap) from momentary in 3-way", options: [[0:"Disabled (default)"],[1:"Enabled"]]], size: 1], 38: [input: [name: "param.38", type: "enum", title: "[38] Flash LED indicators when parameters adjusted", options: [[0:"Flash (default)"],[1:"Don't Flash (recommended if using setLED() command)"]]], size: 1], 39: [input: [name: "param.39", type: "enum", title: "[39] Enable LED blink when buttons pressed", options: [[0:"Enabled (default)"],[1:"Disabled"]]], size: 1], 40: [input: [name: "param.40", type: "enum", title: "[40] On/off only mode", options: [[0:"Disabled (default)"],[1:"Enabled"]]], size: 1] ] // These get set by configure(), "default" parameter values necessary to make this driver work as expected and generally not exposed in the UI: @Field static final Map defaultZwaveParameters = [ // LED indicator mode for relay and buttons 1-4: //1: [value: 3, size: 1], // leaving this one (relay LED) out since it's set by separate preference 2: [value: 3, size: 1], // these could default to 2 or 3 (always off or always on); defaulting to 3 for now, but could read/compare in future and not override if set to one... 3: [value: 3, size: 1], 4: [value: 3, size: 1], 5: [value: 3, size: 1] ] metadata { definition (name: "Zooz Dimmer Scene Controller (ZEN35)", namespace: "RMoRobert", author: "Robert Morris", importUrl: "https://raw.githubusercontent.com/RMoRobert/Hubitat/master/drivers/zooz/zooz-zen35-scene-ctlr-dimmer.groovy") { capability "Actuator" capability "Switch" capability "SwitchLevel" capability "Configuration" capability "PushableButton" capability "HoldableButton" capability "ReleasableButton" command "refresh" command "setConfigParameter", [[name:"Parameter Number*", type: "NUMBER"], [name:"Value*", type: "NUMBER"], [name:"Size*", type: "NUMBER"]] command "setLED", [[name:"ledNumber*", type: "NUMBER", description: "LED/button number: 1-5 (5=large/relay button)", constraints: 1..5], [name:"colorName", type: "ENUM", description: "Color name: white, blue, green, red (all versions); also magenta, yellow, cyan (hardare v2 or FW10.40+)", constraints: colorNameMap], [name:"brightness", type: "NUMBER", description: "Brightness level: 100, 60, or 30 (percent; will round to nearest if not one of these); or 0 for off", constraints: [100,60,30,0]], ] command "setIndicator", [[name:"ledNumber*", type: "NUMBER", description: "LED/Button number (1-5, 5=large button, 0=all)", constraints: 0..5], [name:"mode*", type: "ENUM", description: "Mode (flash, on, or off)", constraints: ["flash", "on", "off"]], [name:"lengthOfOnOffPeriods", type: "NUMBER", description: "On/off period length in tenths of seconds (0-254, e.g., 10 = 1 second)", constraints: 2..255], [name:"numberOfOnOffPeriods", type: "NUMBER", description: "Number of total on/off periods (1-254), or 255 for indefinite", constraints: 1..255], [name:"lengthOfOnPeriod", type: "NUMBER", description: "On period length in tenths of seconds (e.g., 8 = 0.8 seconds; can be used to create asymmetric on/off periods)", constraints: 1..254], ] fingerprint mfr:"027A", prod:"7000", deviceId:"A018", inClusters:"0x5E,0x9F,0x55,0x70,0x5B,0x8E,0x59,0x85,0x86,0x6C,0x73,0x26,0x72,0x87,0x7A,0x5A", controllerType: "ZWV" } preferences { zwaveParameters.each { input it.value.input } input name: "relayLEDBehavior", type: "enum", title: "Relay LED Indicator Mode", options: [[0:"On when relay off (default)"],[4:"As modified by LED commands (recommended in some uses cases)"], [1:"On when relay on"],[2:"Always off"],[3:"Always on"]] input name: "enableDebug", type: "bool", title: "Enable debug logging", defaultValue: true input name: "enableDesc", type: "bool", title: "Enable descriptionText logging", defaultValue: true } } 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 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.versionv2.VersionReport cmd) { if (enableDebug) log.debug "VersionReport: ${cmd}" device.updateDataValue("firmwareVersion", "${cmd.firmware0Version}.${String.format("%02d", cmd.firmware0SubVersion)}") device.updateDataValue("protocolVersion", "${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}") device.updateDataValue("hardwareVersion", "${cmd.hardwareVersion}") } 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}" setStoredConfigParamValue(cmd.parameterNumber, cmd.scaledConfigurationValue) } // void zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) { // if (enableDebug) log.debug "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.debug "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.switchbinaryv1.SwitchBinaryReport cmd) { // if (enableDebug) log.debug "SwitchBinaryReport: ${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}" dimmerEvents(cmd) } void dimmerEvents(hubitat.zwave.Command cmd) { if (enableDebug) log.debug "dimmerEvents value: ${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 btnBaseNum = cmd.sceneNumber ?: 0 Integer btnNum = btnBaseNum String btnAction = "pushed" if (cmd.keyAttributes as Integer == 2) btnAction = "held" else if (cmd.keyAttributes as Integer == 1) btnAction = "released" if ((cmd.keyAttributes as Integer) >= 3) { btnNum = btnBaseNum + (5 * ((cmd.keyAttributes as Integer) - 2)) } 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.commands.indicatorv3.IndicatorReport cmd) { if (enableDebug) log.debug "IndicatorReport: ${cmd}" } void zwaveEvent(hubitat.zwave.commands.indicatorv3.IndicatorSupportedReport cmd) { if (enableDebug) log.debug "IndicatorSupportedReport: ${cmd}" if (cmd.nextIndicatorId > 0) { sendHubCommand(new hubitat.device.HubAction(zwaveSecureEncap(zwave.indicatorV3.indicatorSupportedGet(indicatorId:cmd.nextIndicatorId)), hubitat.device.Protocol.ZWAVE)) } } void zwaveEvent(hubitat.zwave.Command cmd){ if (enableDebug) log.debug "skip: ${cmd}" } /* List indicatorGet() { List cmds = [] cmds << zwaveSecureEncap(zwave.indicatorV3.indicatorSupportedGet(indicatorId:0x00)) return delayBetween(cmds,300) } */ void setStoredConfigParamValue(Integer parameterNumber, BigInteger parameterValue) { state."configParam${parameterNumber}" = parameterValue } BigInteger getStoredConfigParamValue(Integer parameterNumber) { return state."configParam${parameterNumber}" } List refresh() { if (enableDebug) log.debug "refresh" return delayBetween([ zwaveSecureEncap(zwave.basicV1.basicGet()), zwaveSecureEncap(zwave.configurationV1.configurationGet()), zwaveSecureEncap(zwave.versionV2.versionGet()) ], 100) } String on() { if (enableDebug) log.debug "on()" zwaveSecureEncap(zwave.basicV1.basicSet(value: 0xFF)) } String off() { if (enableDebug) log.debug "off()" zwaveSecureEncap(zwave.basicV1.basicSet(value: 0x00)) } String setLevel(value) { if (enableDebug) log.debug "setLevel($value)" hubitat.zwave.Command cmd = zwave.switchMultilevelV2.switchMultilevelSet(value: value < 100 ? value : 99) return zwaveSecureEncap(cmd) } String setLevel(value, duration) { if (enableDebug) log.debug "setLevel($value, $duration)" 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(cmd) } void push(btnNum) { sendEvent(name: "pushed", value: btnNum, isStateChange: true, type: "digital") } void hold(btnNum) { sendEvent(name: "held", value: btnNum, isStateChange: true, type: "digital") } void release(btnNum) { sendEvent(name: "released", value: btnNum, isStateChange: true, type: "digital") } void installed(){ log.warn "Installed..." sendEvent(name: "level", value: 1) } List configure() { log.warn "configure..." List cmds = [] sendEvent(name: "numberOfButtons", value: 25) zwaveParameters.each { param, data -> if (settings[data.input.name] != null) { if (enableDebug) log.debug "Preference parameter: setting parameter $param (size: ${data.size}) to ${settings[data.input.name]}" cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: settings[data.input.name] as BigInteger, parameterNumber: param, size: data.size)) } } defaultZwaveParameters.each { param, data -> if (enableDebug) log.debug "Default parameter: setting parameter $param (size: ${data.size}) to ${data.value}" cmds < cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: pNum as Integer)) } ledColorParams.each { led, pNum -> cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: pNum as Integer)) } ledBrightnessParams.each { led, pNum -> cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: pNum as Integer)) } cmds << zwaveSecureEncap(zwave.versionV2.versionGet()) cmds << zwaveSecureEncap(zwave.versionV2.versionGet()) cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet()) cmds << zwaveSecureEncap(zwave.manufacturerSpecificV2.deviceSpecificGet(deviceIdType: 1)) return cmds ? delayBetween(cmds, 200) : [] } // Apply preferences changes, including updating parameters List updated() { log.info "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 30 minutes..." runIn(1800, logsOff) } List cmds = [] zwaveParameters.each { param, data -> if (settings[data.input.name] != null) { if (enableDebug) log.debug "Preference parameter: setting parameter $param (size: ${data.size}) to ${settings[data.input.name]}" cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: settings[data.input.name] as BigInteger, parameterNumber: param, size: data.size)) } } if (relayLEDBehavior != null) { BigInteger relayLEDParamVal = relayLEDBehavior as BigInteger if (relayLEDParamVal < 4) { cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: relayLEDParamVal, parameterNumber: 1, size: 1)) cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: 1)) } } // Had this before but really probably don't need to do it every save, only Configure? // cmds << zwaveSecureEncap(zwave.versionV2.versionGet()) // cmds << zwaveSecureEncap(zwave.manufacturerSpecificV2.deviceSpecificGet(deviceIdType: 1)) return cmds ? delayBetween(cmds, 200) : [] } List setLED(ledNumber, String colorName, brightness=null) { if (enableDebug) log.debug "setLED(Object $ledNumber, String $colorName, Object $brightness)" Integer intLedNum = ledNumber as Integer Integer intColor = colorNameMap.find{ colorName?.equalsIgnoreCase(it.value) }.key != null ? colorNameMap.find{ colorName.equalsIgnoreCase(it.value) }.key : null Integer intLevel = null switch (brightness as Integer) { case 1..44: intLevel = 2 // actual Z-Wave value (30%) break case 45..74: intLevel = 1 // actual Z-Wave value (60%) break case 75..100: intLevel = 0 // actual Z-Wave value (100%) break case 0: intLevel = -1 // using to mean "off" break default: intLevel = null // using to mean "don't set" } List cmds = [] if (intLevel == -1) { // Set LED to "always off" (may want to change in future if add association), unless #5/relay and configured not to: if (intLedNum != 5 || (relayLEDBehavior as Integer) == 4) { cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: 2, parameterNumber: ledIndicatorParams[intLedNum], size: 1)) cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: ledIndicatorParams[intLedNum])) } else { // If you are intentionally doing this for some reason and don't want to see this log entry, comment out the following line (add two slashes to the front, like this line has) if (enableDebug) log.debug "Relay LED (#5) not configured to allow turning off from setLED (no changes made)" } } else { if (intColor != null) { cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: intColor, parameterNumber: ledColorParams[intLedNum], size: 1)) } else { if (enableDebug) log.debug "Not changing color because no color found for color: $colorName" } if (intLevel != null) { } else { } if (intLevel >= 0) { cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: intLevel, parameterNumber: ledBrightnessParams[intLedNum], size: 1)) } else { if (enableDebug) log.debug "Not changing level because convertd value not >= 0" } // Set LED to "always on" (may want to change in future if add association): if (intLedNum != 5 || (relayLEDBehavior as Integer) == 4) { cmds << zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: 3, parameterNumber: ledIndicatorParams[intLedNum], size: 1)) } else if (brightness && (relayLEDBehavior as Integer) < 3) { if (enableDebug) log.debug "Relay LED (#5) not configured to allow turning on from setLED (skipping setting to always on)" } cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: ledColorParams[intLedNum])) cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: ledBrightnessParams[intLedNum])) cmds << zwaveSecureEncap(zwave.configurationV1.configurationGet(parameterNumber: ledIndicatorParams[intLedNum])) } return cmds ? delayBetween(cmds, 500) : [] } List setIndicator(Number ledNumber=0, String mode="on", Number lengthOfOnOffPeriods=null, Number numberOfOnOffPeriods=null, Number lengthOfOnPeriod=null) { if (enableDebug) log.debug "setIndicator($ledNumber, $mode, $lengthOfOnOffPeriods, $numberOfOnOffPeriods, $lengthOfOnPeriod)" Short indId = indicatorLEDNumberMap[ledNumber as Integer] ?: 0 List cmds = [] if (mode.equalsIgnoreCase("flash")) { Short lenOnOff = lengthOfOnOffPeriods != null ? lengthOfOnOffPeriods as Short : 0 Short numOnOff = numberOfOnOffPeriods != null ? numberOfOnOffPeriods as Short : 0 Short lenOn = lengthOfOnPeriod != null ? lengthOfOnPeriod as Short : 0 if (enableDebug) log.debug "lenOnOff = $lenOnOff, numOnOff=$numOnOff, lenOn=$lenOn, indId=$indId" cmds << zwaveSecureEncap(zwave.indicatorV3.indicatorSet(value: 0xFF, indicatorCount: 3, indicatorValues: [ [indicatorId: indId, propertyId: 0x03, value: lenOnOff], // This property is used to set the duration (in tenth of seconds) of an on/off period [indicatorId: indId, propertyId: 0x04, value: numOnOff], // This property is used to set the number of on/off periods to run [indicatorId: indId, propertyId: 0x05, value: lenOn] // This property is used to set the length of the on time during an on/off period; it allows asymmetric on/off periods ])) } else { Short onOff = (mode.equalsIgnoreCase("on") ? 0xFF : 0x00) cmds << zwaveSecureEncap(zwave.indicatorV3.indicatorSet(value: 0xFF, indicatorCount: 1, indicatorValues: [ [indicatorId: indId, propertyId: 0x02, value: onOff] ])) } return cmds ? delayBetween(cmds, 300) : [] } // Custom command (for apps/users) String setConfigParameter(number, value, size) { return zwaveSecureEncap(setParameter(number, value, size.toInteger())) } // For internal/driver use String setParameter(number, value, size) { if (enableDebug) log.debug "setParameter(number: $number, value: $value, size: $size)" return zwaveSecureEncap(zwave.configurationV1.configurationSet(scaledConfigurationValue: value.toInteger(), parameterNumber: number, size: size)) }