/**
* Candeo Modmote Zigbee Scene Switch
* Reports pushed, double tapped and held button events
* Supresses duplicate events received from device
* Has setting for debounce timer for filtering duplicate events
*/
metadata {
definition(name: 'Candeo Modmote Zigbee Scene Switch', namespace: 'Candeo', author: 'Candeo', importUrl: 'https://github.com/candeosmart/hubitat-zigbee/blob/main/Candeo%20Modmote%20Zigbee%20Scene%20Switch.groovy', singleThreaded: true) {
capability 'PushableButton'
capability 'DoubleTapableButton'
capability 'HoldableButton'
capability 'Configuration'
fingerprint profileId: '0104', endpointId: '01', inClusters: '0000,0001,0003,0004,0006,1000', outClusters: '0019,000A,0003,0004,0005,0006,0008,1000', manufacturer: '_TZ3000_czuyt8lz', model: 'TS004F', deviceJoinName: 'Candeo Modmote Zigbee Scene Switch'
fingerprint profileId: '0104', endpointId: '01', inClusters: '0001,0003,0004,0006,1000,0000', outClusters: '0003,0004,0005,0006,0008,1000,0019,000A', manufacturer: '_TZ3000_b3mgfu0d', model: 'TS004F', deviceJoinName: 'Candeo Modmote Zigbee Scene Switch'
}
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: 'debounceTimer', type: 'enum', title: 'Debounce Timer (s)', description: 'Helps to suppress duplicate events received from the device. We think that the default of 2 seconds is the best option, but you can adjust it to suit your environment.
', options: PREFDEBOUNCETIMER, defaultValue: '2000'
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: '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 Modmote Device Driver'
private @Field final Boolean DEBUG = false
private @Field final Integer LOGSOFF = 1800
private @Field final Map PREFFALSE = [value: 'false', type: 'bool']
private @Field final Map PREFTRUE = [value: 'true', type: 'bool']
private @Field final Map BUTTON_MAPPING = [ 'TS004F': ['numberOfButtons': 4,
'endpointIds': [ '01': [ 'on': ['event': 'pushed', 'button': 1], 'off': ['event': 'doubleTapped', 'button': 1], 'toggle': ['event': 'held', 'button': 1] ],
'02': [ 'on': ['event': 'pushed', 'button': 2], 'off': ['event': 'doubleTapped', 'button': 2], 'toggle': ['event': 'held', 'button': 2] ],
'03': [ 'on': ['event': 'pushed', 'button': 3], 'off': ['event': 'doubleTapped', 'button': 3], 'toggle': ['event': 'held', 'button': 3] ],
'04': [ 'on': ['event': 'pushed', 'button': 4], 'off': ['event': 'doubleTapped', 'button': 4], 'toggle': ['event': 'held', 'button': 4] ] ] ] ]
private @Field final Integer DEBOUNCETIMER = 2000
private @Field final Map PREFDEBOUNCETIMER = ['0': '0s', '500': '0.5s', '1000': '1s', '1500': '1.5s', '2000': '2s', '3000': '3s', '4000': '4s', '5000': '5s']
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() {
logsOn()
logTrace('installed called')
device.updateSetting('debounceTimer', [value: '2000', type: 'enum'])
logInfo("debounceTimer setting is: ${PREFDEBOUNCETIMER[debounceTimer]}")
logInfo('logging level is: Driver Trace Logging')
logInfo("logging level will reduce to Driver Error Logging after ${LOGSOFF} seconds")
logDebug("modelNumberOfButtons: ${modelNumberOfButtons}")
sendEvent(processEvent(name: 'numberOfButtons', value: modelNumberOfButtons, displayed: false))
for (Integer buttonNumber : 1..modelNumberOfButtons) {
sendEvent(buttonAction('pushed', buttonNumber, 'digital'))
String buttonEvent = "button${buttonNumber}Event"
state[buttonEvent] = 'standby'
String buttonTimer = "button${buttonNumber}Timer"
state[buttonTimer] = currentTimeStamp
}
}
void uninstalled() {
logTrace('uninstalled called')
clearAll()
}
void initialize() {
logTrace('initialize called')
}
void updated() {
logTrace('updated called')
logTrace("settings: ${settings}")
logInfo("debounceTimer setting is: ${PREFDEBOUNCETIMER[debounceTimer]}", true)
logInfo("logging level is: ${PREFLOGGING[loggingOption]}", true)
String deviceMode = state['currentMode'] ?: 'unknown'
clearAll()
for (Integer buttonNumber : 1..modelNumberOfButtons) {
String buttonEvent = "button${buttonNumber}Event"
state[buttonEvent] = 'standby'
String buttonTimer = "button${buttonNumber}Timer"
state[buttonTimer] = currentTimeStamp
}
state['currentMode'] = deviceMode
if (logMatch('debug')) {
logInfo("logging level will reduce to Driver Error Logging after ${LOGSOFF} seconds", true)
runIn(LOGSOFF, logsOff)
}
logInfo('if you have changed any Device Configuration Options, make sure that you hit Configure above!', true)
}
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('battery powered device requires manual wakeup to accept configuration commands')
List cmds = ["he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0000 {10 00 00 04 00 00 00 01 00 05 00 07 00 FE FF}", 'delay 200',
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} {10 00 00 04 80}", 'delay 50',
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} {10 00 00 11 D0}", 'delay 50',
"he wattr 0x${device.deviceNetworkId} 0x${device.endpointId} 0x0006 0x8004 0x30 {01} {}", 'delay 50',
"he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0006 {10 00 00 04 80}", 'delay 50']
logDebug("sending ${cmds}")
return cmds
}
void push(BigDecimal button) {
logTrace('push called')
sendEvent(buttonAction('pushed', button.intValue(), 'digital'))
}
void doubleTap(BigDecimal button) {
logTrace('doubleTap called')
sendEvent(buttonAction('doubleTapped', button.intValue(), 'digital'))
}
void hold(BigDecimal button) {
logTrace('hold called')
sendEvent(buttonAction('held', button.intValue(), 'digital'))
}
List