/**
* Candeo C-ZB-RD1P Zigbee Rotary Dimmer Pro (Dual Purpose Mode)
* Supports on / off / setLevel / startLevelChange / stopLevelChange / flash
* Reports switch / level / power / energy / current / voltage events
* Reports button 1 pushed & double tapped events for press / double press on knob
* Reports button 2 pushed events for clockwise step rotation of the knob
* Reports button 2 held events for starting clockwise rotation of the knob
* Reports button 2 released events for stopping clockwise rotation of the knob
* Reports button 3 pushed events for counter-clockwise step rotation of the knob
* Reports button 3 held events for starting counter-clockwise rotation of the knob
* Reports button 3 released events for stopping counter-clockwise rotation of the knob
* Has Setting For Level Transition Time (use device setting, as fast as possible or set an explicit time)
* Has Setting For Level Change Rate (use device setting, as fast as possible or set an explicit rate)
* Has Setting For Flash Time
* Has Setting For Flash Timeout
* Has Settings For Power Reporting
* Has Settings For Voltage Reporting
* Has Settings For Current Reporting
* Has Settings For Energy Reporting
* Has Setting For Power On Default
* Has Setting For Power On Default Level
* Has Setting For Default On Level
* Has Setting For On Transition Time
* Has Setting For Off Transition Time
* Has Setting For Default Move Rate
* Has Setting For Explicit State After Hub Startup
*/
metadata {
definition(name: 'Candeo C-ZB-RD1P Zigbee Rotary Dimmer Pro (Dual Purpose Mode)', namespace: 'Candeo', author: 'Candeo', importUrl: 'https://raw.githubusercontent.com/candeosmart/hubitat-zigbee/refs/heads/main/Candeo%20C-ZB-RD1P%20Zigbee%20Rotary%20Dimmer%20Pro%20(Dual%20Purpose%20Mode).groovy', singleThreaded: true) {
capability 'Switch'
capability 'SwitchLevel'
capability 'ChangeLevel'
capability 'Flash'
capability 'PowerMeter'
capability 'EnergyMeter'
capability 'VoltageMeasurement'
capability 'CurrentMeter'
capability 'PushableButton'
capability 'DoubleTapableButton'
capability 'ReleasableButton'
capability 'HoldableButton'
capability 'Sensor'
capability 'Actuator'
capability 'Initialize'
capability 'Refresh'
capability 'Configuration'
command 'resetPreferencesToDefault'
fingerprint profileId: '0104', endpointId: '01', inClusters: '0000,0003,0004,0005,0006,0008,0702,0B04,1000', outClusters: '0003,0019', manufacturer: 'Candeo', model: 'C-ZB-RD1P-DPM', deviceJoinName: 'Candeo C-ZB-RD1P Zigbee Rotary Dimmer Pro (Dual Purpose Mode)'
}
preferences {
input name: 'deviceDriverOptions', type: 'hidden', title: 'Device Driver Options', description: 'The following options change the behaviour of the device driver, they take effect after hitting "Save Preferences below."'
input name: 'levelTransitionTime', type: 'enum', title: 'Transition Time (s)', description: 'When setting the device to a specific level, use this as the default transition time if one is not specified explicitly.
', options: PREFLEVELTRANSITIONTIME, defaultValue: 'device'
input name: 'levelChangeRate', type: 'enum', title: 'Level Change Rate (%)', description: 'When carrying out a start level change command, move at this percentage per second.
', options: PREFLEVELCHANGERATE, defaultValue: 'device'
input name: 'flashTime', type: 'enum', title: 'Flash Time (ms)', description: 'When carrying out a flash command, use this as the on and off time.
', options: PREFFLASHTIME, defaultValue: '750'
input name: 'flashTimeout', type: 'enum', title: 'Flash Timeout (m)', description: 'When carrying out a flash command, automatically cancel after this amount of time.
', options: PREFFLASHTIMEOUT, defaultValue: '10'
input name: 'hubStartupDefaultCommand', type: 'enum', title: 'Explicit Command After Hub Has Restarted', description: 'After the hub restarts, carry out this command on the device.
', options: PREFHUBRESTART, defaultValue: 'refresh'
input name: 'loggingOption', type: 'enum', title: 'Logging Option', description: 'Sets the logging level cumulatively, for example "Driver Trace Logging" will include all logging levels below it.
', options: PREFLOGGING, defaultValue: '5'
input name: 'deviceConfigurationOptions', type: 'hidden', title: 'Device Configuration Options', description: 'The following options change the behaviour of the device itself, they take effect after hitting "Save Preferences below", followed by "Configure" above.
For a battery powered device, you may also need to wake it up manually!'
input name: 'deviceConfigPowerReportEnable', type: 'bool', title: 'Enable Power Reporting', description: 'Enable the device to report instantaneous power readings.
', defaultValue: false
input name: 'deviceConfigPowerReportChange', type: 'enum', title: 'Power Change (W)', description: 'Report instantaneous power readings that change by at least this value.
', options: PREFPOWERCHANGE, defaultValue: '10'
input name: 'deviceConfigPowerReportTime', type: 'enum', title: 'Power Time (s)', description: 'Periodically report instantaneous power reading according to this timing.
', options: PREFREPORTTIME, defaultValue: '300'
input name: 'deviceConfigVoltageReportEnable', type: 'bool', title: 'Enable Voltage Reporting', description: 'Enable the device to report voltage readings.
', defaultValue: false
input name: 'deviceConfigVoltageReportChange', type: 'enum', title: 'Voltage Change (V)', description: 'Report voltage readings that change by at least this value.
', options: PREFVOLTAGECHANGE, defaultValue: '5'
input name: 'deviceConfigVoltageReportTime', type: 'enum', title: 'Voltage Time (s)', description: 'Periodically report voltage reading according to this timing.
', options: PREFREPORTTIME, defaultValue: '600'
input name: 'deviceConfigCurrentReportEnable', type: 'bool', title: 'Enable Current Reporting', description: 'Enable the device to report current readings.
', defaultValue: false
input name: 'deviceConfigCurrentReportChange', type: 'enum', title: 'Current Change (A)', description: 'Report current readings that change by at least this value.
', options: PREFCURRENTCHANGE, defaultValue: '0.1'
input name: 'deviceConfigCurrentReportTime', type: 'enum', title: 'Current Time (s)', description: 'Periodically report current reading according to this timing.
', options: PREFREPORTTIME, defaultValue: '900'
input name: 'deviceConfigEnergyReportEnable', type: 'bool', title: 'Enable Energy Reporting', description: 'Enable the device to report eneergy readings.
', defaultValue: false
input name: 'deviceConfigEnergyReportChange', type: 'enum', title: 'Energy Change (kWh)', description: 'Report energy readings that change by at least this value.
', options: PREFENERGYCHANGE, defaultValue: '0.5'
input name: 'deviceConfigEnergyReportTime', type: 'enum', title: 'Energy Time (s)', description: 'Periodically report energy reading according to this timing.
', options: PREFREPORTTIME, defaultValue: '3600'
input name: 'deviceConfigDefaultPowerOnBehaviour', type: 'enum', title: 'Default State After Return From Power Failure', description: 'After a power failure, set the device to this state when the power is restored.
', options: PREFPOWERON, defaultValue: 'previous'
input name: 'deviceConfigDefaultPowerOnLevel', type: 'enum', title: 'Default Level After Return From Power Failure', description: 'After a power failure, set the device to this level when the power is restored.
', options: PREFLEVEL, defaultValue: 'previous'
input name: 'deviceConfigDefaultOnLevel', type: 'enum', title: 'Default Level When Turned On', description: 'When turned on, go immediately to this level.
', options: PREFLEVEL, defaultValue: 'previous'
input name: 'deviceConfigDefaultOnTransitionTime', type: 'enum', title: 'On Transition Time (s) When Turned On', description: 'When turned on, use this as the transition time to fade up.
', options: PREFTRANSITIONTIME, defaultValue: '1000' //10ths of a second default 10
input name: 'deviceConfigDefaultOffTransitionTime', type: 'enum', title: 'Off Transition Time (s) When Turned Off', description: 'When turned off, use this as the transition time to fade down.
', options: PREFTRANSITIONTIME, defaultValue: '1000' //10ths of a second default 10
input name: 'deviceConfigDefaultMoveRate', type: 'enum', title: 'Move Rate Per Second (%)', description: 'When changing level, move at this percentage per second.
', options: PREFMOVERATE, defaultValue: '35' //level units per second default 85, approximately 35%
input name: 'platformOptions', type: 'hidden', title: 'Platform Options', description: 'The following options are relevant to the Hubitat platform and UI itself.'
}
}
import groovy.transform.Field
private @Field final String CANDEO = 'Candeo C-ZB-RD1P Device Driver'
private @Field final Boolean DEBUG = false
private @Field final Integer LOGSOFF = 1800
private @Field final Integer ZIGBEEDELAY = 1000
private @Field final Integer DEVICEMINLEVEL = 1
private @Field final Integer DEVICEMAXLEVEL = 254
private @Field final Map PREFFALSE = [value: 'false', type: 'bool']
private @Field final Map PREFTRUE = [value: 'true', type: 'bool']
private @Field final Map PREFPREVIOUS = [value: 'previous', type: 'enum']
private @Field final Map PREFDEVICE = [value: 'device', type: 'enum']
private @Field final Map PREFNONE = [value: 'none', type: 'enum']
private @Field final Map PREF1000 = [value: '1000', type: 'enum']
private @Field final Map PREF10 = [value: '10', type: 'enum']
private @Field final Map PREF5 = [value: '5', type: 'enum']
private @Field final Map PREFPOWERON = [ 'off': 'Off', 'on': 'On', 'opposite': 'Opposite', 'previous': 'Previous' ]
private @Field final Map PREFLEVEL = ['5': '5%', '10': '10%', '15': '15%', '20': '20%', '25': '25%', '30': '30%', '35': '35%', '40': '40%', '45': '45%', '50': '50%', '55': '55%', '65': '65%', '70': '70%', '75': '75%', '80': '85%', '90': '95%', '100': '100%', 'previous': 'Previous']
private @Field final Map PREFHUBRESTART = [ 'off': 'Off', 'on': 'On', 'refresh': 'Refresh State Only', 'nothing': 'Do Nothing' ]
private @Field final Map PREFLEVELTRANSITIONTIME = ['device': 'use device setting', 'none': 'as fast as possible', '500': '0.5s', '1000': '1s', '1500': '1.5s', '2000': '2s', '2500': '2.5s', '3000': '3s', '3500': '3.5s', '4000': '4s', '4500': '4.5s', '5000': '5s']
private @Field final Map PREFLEVELCHANGERATE = ['device': 'use device setting', 'none': 'as fast as possible', '1': '1%', '2': '2%', '3': '3%', '4': '4%', '5': '5%', '6': '6%', '7': '6%', '8': '8%', '9': '9%', '10': '10%', '15': '15%', '20': '20%', '25': '25%', '30': '30%', '35': '35%', '40': '40%', '45': '45%', '50': '50%']
private @Field final Map PREFTRANSITIONTIME = ['none': 'as fast as possible', '1000': '1s', '1500': '1.5s', '2000': '2s', '2500': '2.5s', '3000': '3s', '3500': '3.5s', '4000': '4s', '4500': '4.5s', '5000': '5s', '5500': '5.5s', '6000': '6s', '6500': '6.5s', '7000': '7s', '7500': '7.5s', '8000': '8s', '8500': '8.5s', '9000': '9s', '9500': '9.5s', '10000': '10s']
private @Field final Map PREFMOVERATE = ['1': '1%', '2': '2%', '3': '3%', '4': '4%', '5': '5%', '6': '6%', '7': '6%', '8': '8%', '9': '9%', '10': '10%', '15': '15%', '20': '20%', '25': '25%', '30': '30%', '35': '35%', '40': '40%', '45': '45%', '50': '50%']
private @Field final Map PREFREPORTTIME = ['10': '10s', '20': '20s', '30': '30s', '40': '40s', '50': '50s', '60': '60s', '90': '90s', '120': '120s', '240': '240s', '300': '300s', '600': '600s', '900': '900s', '1800': '1800s', '3600': '3600s']
private @Field final Map PREFPOWERCHANGE = ['1': '1W', '2': '2W', '3': '3W', '4': '4W', '5': '5W', '6': '6W', '7': '7W', '8': '8W', '9': '9W', '10': '10W', '15': '15W', '20': '20W']
private @Field final Map PREFVOLTAGECHANGE = ['1': '1V', '2': '2V', '3': '3V', '4': '4V', '5': '5V', '6': '6V', '7': '7V', '8': '8V', '9': '9V', '10': '10V', '15': '15V', '20': '20V']
private @Field final Map PREFCURRENTCHANGE = ['0.1': '0.1A', '0.2': '0.2A', '0.3': '0.3A', '0.4': '0.4A', '0.5': '0.5A', '0.6': '0.6A', '0.7': '0.7A', '0.8': '0.8A', '0.9': '0.9A', '1': '1A', '1.5': '1.5A', '2': '2A']
private @Field final Map PREFENERGYCHANGE = ['0.1': '0.1kWh', '0.2': '0.2kWh', '0.3': '0.3kWh', '0.4': '0.4kWh', '0.5': '0.5kWh', '0.6': '0.6kWh', '0.7': '0.7kWh', '0.8': '0.8kWh', '0.9': '0.9kWh', '1': '1kWh']
private @Field final Map PREFFLASHTIME = ['500': '500ms', '750': '750ms', '1000': '1000ms', '1500': '1500ms', '2000': '2000ms', '2500': '2500ms', '3000': '3000ms', '4000': '4000ms', '5000': '5000ms']
private @Field final Map PREFFLASHTIMEOUT = ['0': 'never', '1': '1m', '2': '2m', '3': '3m', '4': '4m', '5': '5m', '10': '10m', '15': '15m', '30': '30m', '60': '60m', '90': '90m', '120': '120m', '180': '180m']
private @Field final Map PREFLOGGING = ['0': 'Device Event Logging', '1': 'Driver Informational Logging', '2': 'Driver Warning Logging', '3': 'Driver Error Logging', '4': 'Driver Debug Logging', '5': 'Driver Trace Logging' ]
void installed() {
logTrace('installed called', true)
setPreferencesToDefault()
logDebug("modelNumberOfButtons: ${modelNumberOfButtons}")
sendEvent(processEvent(name: 'numberOfButtons', value: 3, displayed: false))
for (Integer buttonNumber : 1..3) {
sendEvent(buttonAction('pushed', buttonNumber, 'digital'))
}
}
void uninstalled() {
logTrace('uninstalled called')
clearAll()
}
void initialize() {
logTrace('initialize called')
String startupDefaultCommand = hubStartupDefaultCommand ?: 'refresh'
switch (startupDefaultCommand) {
case 'off':
doZigBeeCommand(off())
break
case 'on':
doZigBeeCommand(on())
break
case 'refresh':
doZigBeeCommand(refresh())
break
default:
break
}
}
List updated() {
logTrace('updated called')
logTrace("settings: ${settings}")
logInfo("deviceConfigDefaultPowerOnBehaviour setting is: ${PREFPOWERON[deviceConfigDefaultPowerOnBehaviour ?: 'previous']}", true)
logInfo("deviceConfigDefaultPowerOnLevel setting is: ${PREFLEVEL[deviceConfigDefaultPowerOnLevel ?: 'previous']}", true)
logInfo("deviceConfigDefaultOnLevel setting is: ${PREFLEVEL[deviceConfigDefaultOnLevel ?: 'previous']}", true)
logInfo("deviceConfigDefaultOnTransitionTime setting is: ${PREFTRANSITIONTIME[deviceConfigDefaultOnTransitionTime ?: '1000']}", true)
logInfo("deviceConfigDefaultOffTransitionTime setting is: ${PREFTRANSITIONTIME[deviceConfigDefaultOffTransitionTime ?: '1000']}", true)
logInfo("deviceConfigDefaultMoveRate setting is: ${PREFMOVERATE[deviceConfigDefaultMoveRate ?: '1']}", true)
logInfo("hubStartupDefaultCommand setting is: ${PREFHUBRESTART[hubStartupDefaultCommand ?: 'refresh']}", true)
logInfo("levelTransitionTime setting is: ${PREFLEVELTRANSITIONTIME[levelTransitionTime ?: 'device']}", true)
logInfo("levelChangeRate setting is: ${PREFLEVELCHANGERATE[levelChangeRate ?: 'device']}", true)
logInfo("flashTime setting is: ${PREFFLASHTIME[flashTime ?: '750']}", true)
logInfo("flashTimeout setting is: ${PREFFLASHTIMEOUT[flashTimeout ?: '10']}", true)
logInfo("deviceConfigPowerReportEnable setting is: ${deviceConfigPowerReportEnable == true}", true)
if (deviceConfigPowerReportEnable) {
logInfo("deviceConfigPowerReportChange setting is: ${PREFPOWERCHANGE[deviceConfigPowerReportChange ?: '10']}", true)
logInfo("deviceConfigPowerReportTime setting is: ${PREFREPORTTIME[deviceConfigPowerReportTime ?: '300']}", true)
}
logInfo("deviceConfigVoltageReportEnable setting is: ${deviceConfigVoltageReportEnable == true}", true)
if (deviceConfigVoltageReportEnable) {
logInfo("deviceConfigVoltageReportChange setting is: ${PREFVOLTAGECHANGE[deviceConfigVoltageReportChange ?: '5']}", true)
logInfo("deviceConfigVoltageReportTime setting is: ${PREFREPORTTIME[deviceConfigVoltageReportTime ?: '600']}", true)
}
logInfo("deviceConfigCurrentReportEnable setting is: ${deviceConfigCurrentReportEnable == true}", true)
if (deviceConfigCurrentReportEnable) {
logInfo("deviceConfigCurrentReportChange setting is: ${PREFCURRENTCHANGE[deviceConfigCurrentReportChange ?: '0.1']}", true)
logInfo("deviceConfigCurrentReportTime setting is: ${PREFREPORTTIME[deviceConfigCurrentReportTime ?: '900']}", true)
}
logInfo("deviceConfigEnergyReportEnable setting is: ${deviceConfigEnergyReportEnable == true}", true)
if (deviceConfigEnergyReportEnable) {
logInfo("deviceConfigEnergyReportChange setting is: ${PREFENERGYCHANGE[deviceConfigEnergyReportChange ?: '0.5']}", true)
logInfo("deviceConfigEnergyReportTime setting is: ${PREFREPORTTIME[deviceConfigEnergyReportTime ?: '3600']}", true)
}
logInfo("logging level is: ${PREFLOGGING[loggingOption]}", true)
clearAll()
if (logMatch('debug')) {
logInfo("logging level will reduce to Driver Error Logging after ${LOGSOFF} seconds", true)
runIn(LOGSOFF, logsOff)
}
if (checkPreferences()) {
logInfo('Device Configuration Options have been changed, will now configure the device!', true)
return configure()
}
}
void logsOff() {
logTrace('logsOff called')
if (DEBUG) {
logDebug('DEBUG field variable is set, not disabling logging automatically!', true)
}
else {
logInfo('automatically reducing logging level to Driver Error Logging', true)
device.updateSetting('loggingOption', [value: '3', type: 'enum'])
}
}
List configure() {
logTrace('configure called')
logDebug("startup on off is ${deviceConfigDefaultPowerOnBehaviour ?: 'previous'}")
Map startUpOnOff = ['on': 1, 'off': 0, 'opposite': 2, 'previous': 255]
logDebug("startUpOnOff: ${startUpOnOff[deviceConfigDefaultPowerOnBehaviour ?: 'previous']}")
logDebug("startup current level is: ${deviceConfigDefaultPowerOnLevel ?: 'previous'}")
Integer startUpLevel = deviceConfigDefaultPowerOnLevel ? deviceConfigDefaultPowerOnLevel == 'previous' ? 255 : percentageValueToLevel(deviceConfigDefaultPowerOnLevel) : 255
logDebug("startUpLevel: ${startUpLevel}")
logDebug("on level is: ${deviceConfigDefaultOnLevel ?: 'previous'}")
Integer onLevel = deviceConfigDefaultOnLevel ? deviceConfigDefaultOnLevel == 'previous' ? 255 : percentageValueToLevel(deviceConfigDefaultOnLevel) : 255
logDebug("onLevel: ${onLevel}")
logDebug("on transition time is: ${deviceConfigDefaultOnTransitionTime ?: '1000'}")
Integer onTransitionTime = deviceConfigDefaultOnTransitionTime ? deviceConfigDefaultOnTransitionTime == 'none' ? 65535 : (deviceConfigDefaultOnTransitionTime.toInteger() / 100).toInteger() : 10
logDebug("onTransitionTime: ${onTransitionTime}")
logDebug("off transition time is: ${deviceConfigDefaultOffTransitionTime ?: '1000'}")
Integer offTransitionTime = deviceConfigDefaultOffTransitionTime ? deviceConfigDefaultOffTransitionTime == 'none' ? 65535 : (deviceConfigDefaultOffTransitionTime.toInteger() / 100).toInteger() : 10
logDebug("offTransitionTime: ${offTransitionTime}")
logDebug("default move rate is: ${deviceConfigDefaultMoveRate ?: '1'}")
Integer moveRate = deviceConfigDefaultMoveRate ? percentageValueToLevel(deviceConfigDefaultMoveRate) : 3
logDebug("moveRate: ${moveRate}")
List cmds = [ //onoff
"zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0006 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}",
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x0000 ${DataType.BOOLEAN} 0 3600 {}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0006 {10 00 08 00 00 00}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x0000 {}", "delay ${ZIGBEEDELAY}",
//level
"zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0008 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}",
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0000 ${DataType.UINT8} 1 3600 {01}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0008 {10 00 08 00 00 00}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0000 {}", "delay ${ZIGBEEDELAY}",
//startupbehaviour
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x4003 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x4003 ${convertToHexString(DataType.ENUM8)} {${convertToHexString(startUpOnOff[deviceConfigDefaultPowerOnBehaviour ?: 'previous'])}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x4003 {}", "delay ${ZIGBEEDELAY}",
//minlevel
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0002 {}", "delay ${ZIGBEEDELAY}",
//maxlevel
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0003 {}", "delay ${ZIGBEEDELAY}",
//onofftransitiontime
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0010 {}", "delay ${ZIGBEEDELAY}",
//onlevel
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0011 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0011 ${convertToHexString(DataType.UINT8)} {${convertToHexString(onLevel)}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0011 {}", "delay ${ZIGBEEDELAY}",
//ontransitiontime
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0012 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0012 ${convertToHexString(DataType.UINT16)} {${convertToHexString(onTransitionTime, 2)}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0012 {}", "delay ${ZIGBEEDELAY}",
//offtransitiontime
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0013 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0013 ${convertToHexString(DataType.UINT16)} {${convertToHexString(offTransitionTime, 2)}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0013 {}", "delay ${ZIGBEEDELAY}",
//defaultmoverate
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0014 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0014 ${convertToHexString(DataType.UINT8)} {${convertToHexString(moveRate)}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0014 {}", "delay ${ZIGBEEDELAY}",
//startupcurrentlevel
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x4000 {}", "delay ${ZIGBEEDELAY}",
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x4000 ${convertToHexString(DataType.UINT8)} {${convertToHexString(startUpLevel)}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x4000 {}", "delay ${ZIGBEEDELAY}",
//onoff endpoint 2
"zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0006 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}",
//level endpoint 2
"zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0008 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}"]
if (deviceConfigPowerReportEnable || deviceConfigVoltageReportEnable || deviceConfigCurrentReportEnable) {
cmds += ["zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0B04 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}"]
}
else {
cmds += ["zdo unbind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0B04 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigPowerReportEnable) {
logDebug("power change is: ${deviceConfigPowerReportChange ?: '10'}W") //1 = 1W
logDebug("power time is: ${deviceConfigPowerReportTime ?: '300'}s")
Integer powerChange = ((deviceConfigPowerReportChange ?: 10).toBigDecimal() / 1 * 1).toInteger()
logDebug("powerChange: ${powerChange}")
if (powerChange == 0) {
logDebug('powerChange is ZERO, protecting against report flooding!')
powerChange = 10
}
Integer powerTime = deviceConfigPowerReportTime ? deviceConfigPowerReportTime.toInteger() : 300
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0604 {}", "delay ${ZIGBEEDELAY}", // responds 1 for multiplier
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0605 {}", "delay ${ZIGBEEDELAY}", // responds 1 for divisor
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x050B ${DataType.INT16} 5 ${powerTime} {${convertToHexString(powerChange, 2, true)}}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 0B 05}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x050B {}", "delay ${ZIGBEEDELAY}"]
}
else {
cmds += ["he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x050B ${DataType.INT16} 0 65535 {0} {}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 0B 05}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigVoltageReportEnable) {
logDebug("voltage change is: ${deviceConfigVoltageReportChange ?: '5'}V") //100 = 1V
logDebug("voltage time is: ${deviceConfigVoltageReportTime ?: '600'}s")
Integer voltageChange = ((deviceConfigVoltageReportChange ?: 5).toBigDecimal() / 1 * 100).toInteger()
logDebug("voltageChange: ${voltageChange}")
if (voltageChange == 0) {
logDebug('voltageChange is ZERO, protecting against report flooding!')
voltageChange = 500
}
Integer voltageTime = deviceConfigVoltageReportTime ? deviceConfigVoltageReportTime.toInteger() : 600
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0600 {}", "delay ${ZIGBEEDELAY}", // responds 1 for multiplier
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0601 {}", "delay ${ZIGBEEDELAY}", // responds 100 for divisor
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0505 ${DataType.UINT16} 5 ${voltageTime} {${convertToHexString(voltageChange, 2, true)}}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 05 05}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0505 {}", "delay ${ZIGBEEDELAY}"]
}
else {
cmds += ["he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0505 ${DataType.UINT16} 0 65535 {0} {}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 05 05}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigCurrentReportEnable) {
logDebug("current change is: ${deviceConfigCurrentReportChange ?: '0.1'}A") //100 = 1A
logDebug("current time is: ${deviceConfigCurrentReportTime ?: '900'}s")
Integer currentChange = ((deviceConfigCurrentReportChange ?: 0.1).toBigDecimal() / 1 * 100).toInteger()
logDebug("currentChange: ${currentChange}")
if (currentChange == 0) {
logDebug('currentChange is ZERO, protecting against report flooding!')
currentChange = 10
}
Integer currentTime = deviceConfigCurrentReportTime ? deviceConfigCurrentReportTime.toInteger() : 900
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0602 {}", "delay ${ZIGBEEDELAY}", // responds 1 for multiplier
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0603 {}", "delay ${ZIGBEEDELAY}", // responds 100 for divisor
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0508 ${DataType.UINT16} 5 ${currentTime} {${convertToHexString(currentChange, 2, true)}}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 08 05}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0508 {}", "delay ${ZIGBEEDELAY}"]
}
else {
cmds += ["he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0508 ${DataType.UINT16} 0 65535 {0} {}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0B04 {10 00 08 00 08 05}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigEnergyReportEnable) {
logDebug("energy change is: ${deviceConfigEnergyReportChange ?: '0.5'}kWh") //100 = 1kWh
logDebug("energy time is: ${deviceConfigEnergyReportTime ?: '3600'}s")
Integer energyChange = ((deviceConfigEnergyReportChange ?: 0.5).toBigDecimal() / 1 * 100).toInteger()
logDebug("energyChange: ${energyChange}")
if (energyChange == 0) {
logDebug('energyChange is ZERO, protecting against report flooding!')
energyChange = 50
}
Integer energyTime = deviceConfigEnergyReportTime ? deviceConfigEnergyReportTime.toInteger() : 3600
cmds += ["zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0702 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0300 {}", "delay ${ZIGBEEDELAY}", // responds 0 for unit of measure - kWh
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0301 {}", "delay ${ZIGBEEDELAY}", // responds 1 for multiplier
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0302 {}", "delay ${ZIGBEEDELAY}", // responds 100 for divisor
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0303 {}", "delay ${ZIGBEEDELAY}", // responds 0 for summation formatting
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0304 {}", "delay ${ZIGBEEDELAY}", // responds unsupported for demand formatting
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0000 ${DataType.UINT48} 5 ${energyTime} {${convertToHexString(energyChange, 4, true)}}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0702 {10 00 08 00 00 00}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0000 {}", "delay ${ZIGBEEDELAY}"]
}
else {
cmds += ["zdo unbind 0x${device.deviceNetworkId} 0x${device.endpointId} 0x01 0x0702 {${device.zigbeeId}} {}", "delay ${ZIGBEEDELAY}",
"he cr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0000 ${DataType.UINT48} 0 65535 {0} {}", "delay ${ZIGBEEDELAY}",
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0702 {10 00 08 00 00 00}", "delay ${ZIGBEEDELAY}"]
}
logDebug("returning ${cmds}")
return cmds
}
List refresh() {
logTrace('refresh called')
List cmds = ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x0000 {}", "delay ${ZIGBEEDELAY}",
"he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 0x0000 {}", "delay ${ZIGBEEDELAY}"]
if (deviceConfigPowerReportEnable) {
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x050B {}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigVoltageReportEnable) {
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0505 {}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigCurrentReportEnable) {
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0B04 0x0508 {}", "delay ${ZIGBEEDELAY}"]
}
if (deviceConfigEnergyReportEnable) {
cmds += ["he rattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0702 0x0000 {}", "delay ${ZIGBEEDELAY}"]
}
logDebug("returning ${cmds}")
return cmds
}
void resetPreferencesToDefault() {
logTrace('resetPreferencesToDefault called')
setPreferencesToDefault()
if (checkPreferences()) {
logInfo('Device Configuration Options have been changed, will now configure the device!', true)
doZigBeeCommand(configure())
}
}
void push(BigDecimal button) {
logTrace('push called')
buttonCommand('pushed', button.intValue())
}
void doubleTap(BigDecimal button) {
logTrace('doubleTap called')
buttonCommand('doubleTapped', button.intValue())
}
void hold(BigDecimal button) {
logTrace('hold called')
buttonCommand('held', button.intValue())
}
void release(BigDecimal button) {
logTrace('release called')
buttonCommand('released', button.intValue())
}
List on() {
logTrace('on called')
flashStop(false)
List cmds = ["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 1 {}"]
logDebug("returning ${cmds}")
state['action'] = 'digitalon'
return cmds
}
List off() {
logTrace('off called')
flashStop(false)
List cmds = ["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0 {}"]
logDebug("returning ${cmds}")
state['action'] = 'digitaloff'
return cmds
}
void flash(BigDecimal rate = null) {
logTrace("flash called rate: ${rate ?: 'no rate specified'}")
if (state['flashing']) {
logDebug('state["flashing"] is true, stopping flasher')
state['flashing'] = false
flashStop()
}
else {
logDebug('state["flashing"] is false, starting flasher')
state['flashing'] = true
String currentState = device.currentValue('switch')
logDebug("device state is currently: ${currentState}")
state['flashPrevious'] = currentState == 'on' ?: false
Integer flashRate = rate
if (!flashRate) {
logDebug("no rate specified, using flashTime: ${flashTime ?: '750'}")
flashRate = flashTime ? flashTime.toInteger() : 750
}
logDebug("flashRate: ${flashRate}")
if (flashRate > 5000 || flashRate < 500) {
flashRate = flashRate > 5000 ? 5000 : flashRate < 500 ? 500 : flashRate
logWarn('flashRate outside safe range (500 - 5000), resetting to safe value!')
}
runInMillis(flashRate, flasher, [data: ['on': !(state['flashPrevious']), 'rate': flashRate]])
logDebug("flashTimeout: ${flashTimeout ?: '10'}")
Integer flashEnd = (flashTimeout ? flashTimeout.toInteger() : 10) * 60 * 1000
logDebug("flashEnd: ${flashEnd}")
if (flashEnd > 0) {
logDebug('setting flashing timeout')
runInMillis(flashEnd, flashStop)
}
else {
logDebug('no timeout requested')
}
}
}
void flasher(Map data) {
logTrace("flasher called data: ${data}")
if (state['flashing']) {
String cmd = '1'
String action = 'digitalon'
if (data.on) {
logDebug('turning on')
}
else {
logDebug('turning off')
cmd = '0'
action = 'digitaloff'
}
state['action'] = action
doZigBeeCommand(["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 ${cmd} {}"])
runInMillis(data.rate, flasher, [data: ['on': !(data.on), 'rate': data.rate]])
}
else {
logDebug('state["flashing"] is false, skipping!')
}
}
void flashStop(Boolean reinstate = true) {
logTrace('flashStop called')
state['flashing'] = false
unschedule('flasher')
unschedule('flashStop')
if (reinstate) {
logDebug("reinstate is true, reinstating device previous state: ${state['flashPrevious'] ? 'on' : 'off'}")
String cmd = '1'
String action = 'digitalon'
if (state['flashPrevious']) {
logDebug('reinstate device to on')
}
else {
logDebug('reinstate device to off')
cmd = '0'
action = 'digitaloff'
}
state['action'] = action
doZigBeeCommand(["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 ${cmd} {}"])
}
}
List setLevel(BigDecimal level) {
logTrace("setLevel called level: ${level}")
logDebug("levelTransitionTime: ${levelTransitionTime ?: 'device'}")
BigDecimal levelTime = levelTransitionTime ? levelTransitionTime == 'none' ? 0 : levelTransitionTime == 'device' ? 65535 : levelTransitionTime.toBigDecimal() / 1000 : 65535
return setLevel(level, levelTime)
}
List setLevel(BigDecimal level, BigDecimal transition) {
logTrace("setLevel called level: ${level} rate: ${transition}")
Integer scaledTransition = transition == 0 ? 0 : transition == 65535 ? 65535 : (transition * 10).toInteger()
logDebug("scaledTransition: ${scaledTransition}")
Integer scaledLevel = percentageValueToLevel(level)
logDebug("scaledLevel: ${scaledLevel}")
List cmds = ["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 4 {0x${intTo8bitUnsignedHex(scaledLevel)} 0x${intTo16bitUnsignedHex(scaledTransition)}}"]
logDebug("returning ${cmds}")
state['action'] = 'digitalsetlevel'
return cmds
}
List startLevelChange(String direction) {
logTrace("startLevelChange called direction: ${direction}")
Integer upDown = direction == 'down' ? 1 : 0
logDebug("upDown: ${upDown} levelChangeRate: ${levelChangeRate ?: 'device'}")
Integer scaledRate = levelChangeRate ? levelChangeRate == 'none' ? 254 : levelChangeRate == 'device' ? 255 : percentageValueToLevel(levelChangeRate.toBigDecimal()) : 255
logDebug("scaledRate: ${scaledRate}")
List cmds = ["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 5 {0x${intTo8bitUnsignedHex(upDown)} 0x${intTo16bitUnsignedHex(scaledRate)}}"]
logDebug("returning ${cmds}")
state['action'] = 'digitalsetlevel'
return cmds
}
List stopLevelChange() {
logTrace('stopLevelChange called')
List cmds = ["he cmd 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0008 3 {}"]
logDebug("returning ${cmds}")
return cmds
}
List