Skip to content

Commit

Permalink
Align GWA1501 and GWA1502 functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-danache committed Dec 23, 2024
1 parent 9d2dd00 commit b6c02ed
Show file tree
Hide file tree
Showing 41 changed files with 148 additions and 142 deletions.
8 changes: 7 additions & 1 deletion .groovylintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@
"MethodSize": {
"enabled": false
},
"NestedBlockDepth": {
"enabled": false
},
"NoJavaUtilDate": {
"enabled": false
},
"ParameterCount": {
"enabled": false
},
"PublicMethodsBeforeNonPublicMethods": {
"enabled": false
},
"TrailingWhitespace": {
"enabled": false
}
}
}
}
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Aqara_DCM-K01.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
31 changes: 17 additions & 14 deletions ikea-zigbee-drivers/Gewiss_GWA1501.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.hubitat.zigbee.DataType
import com.hubitat.app.ChildDeviceWrapper
import com.hubitat.app.DeviceWrapper

@Field static final Map<String, String> GWA1501_BUTTON_TYPE = [
@Field static final Map<String, String> BUTTON_TYPES = [
'toggle': 'Rocker / Toggle',
'push': 'Push Button',
]
Expand Down Expand Up @@ -79,10 +79,9 @@ metadata {
input(
name:'buttonType', type:'enum', title:'Button type', required:true,
description:'<small>Select wired buttons type.</small>',
options:GWA1501_BUTTON_TYPE,
options:BUTTON_TYPES,
defaultValue:'toggle'
)

input(
name:'enableContacts', type:'bool', title:'Use as Contact Sensor', required:true,
description:'<small>Track open/closed state using two Contact Sensor child devices.</small>',
Expand Down Expand Up @@ -121,7 +120,7 @@ List<String> updated(boolean auto = false) {
buttonType = 'toggle'
device.updateSetting 'buttonType', [value:buttonType, type:'enum']
}
log_info "🛠️ buttonType = ${GWA1501_BUTTON_TYPE[buttonType]}"
log_info "🛠️ buttonType = ${BUTTON_TYPES[buttonType]}"

if (enableContacts == null) {
enableContacts = false
Expand Down Expand Up @@ -198,7 +197,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand All @@ -207,6 +206,8 @@ void configureApply() {
// Configuration for devices.Gewiss_GWA1501
cmds += "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0406 {${device.zigbeeId}} {}" // Occupancy Sensing cluster (ep 0x01)
cmds += "zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0406 {${device.zigbeeId}} {}" // Occupancy Sensing cluster (ep 0x02)
cmds += "he cr 0x${device.deviceNetworkId} 0x01 0x0406 0x0000 0x18 0x0000 0x0E10 {01} {}" // Report Occupancy (map8) at least every 1 hour (ep 0x01)
cmds += "he cr 0x${device.deviceNetworkId} 0x02 0x0406 0x0000 0x18 0x0000 0x0E10 {01} {}" // Report Occupancy (map8) at least every 1 hour (ep 0x02)
cmds += "he raw 0x${device.deviceNetworkId} 0x00 0x00 0x0022 {49 ${utils_payload "${device.zigbeeId}"} ${utils_payload '0x01'} ${utils_payload '0x0020'} 03 ${utils_payload "${location.hub.zigbeeEui}"} 01} {0x0000}" // Unbind Poll Control cluster
cmds += zigbee.writeAttribute(0x0020, 0x0000, 0x23, 0x00) // Disable periodic polling by the device (to conserve battery)

Expand Down Expand Up @@ -250,8 +251,6 @@ List<String> refresh(boolean auto = false) {
// Refresh for devices.Gewiss_GWA1501
cmds += zigbee.readAttribute(0x0406, 0x0000, [destEndpoint:0x01]) // Occupancy (ep 01)
cmds += zigbee.readAttribute(0x0406, 0x0000, [destEndpoint:0x02]) // Occupancy (ep 02)
cmds += "he cr 0x${device.deviceNetworkId} 0x01 0x0406 0x0000 0x18 0x0000 0x0000 {01} {}" // Disable periodic reporting for Occupancy (map8) (ep 0x01)
cmds += "he cr 0x${device.deviceNetworkId} 0x02 0x0406 0x0000 0x18 0x0000 0x0000 {01} {}" // Disable periodic reporting for Occupancy (map8) (ep 0x02)

// Refresh for capability.Battery
cmds += zigbee.readAttribute(0x0001, 0x0021) // BatteryPercentage
Expand Down Expand Up @@ -364,21 +363,25 @@ void parse(String description) {
case { contains it, [clusterInt:0x0406, commandInt:0x01, attrInt:0x0000] }:
String newState = msg.value == '01' ? 'closed' : 'open'

// Ignore periodic reports with no state change
if (msg.commandInt == 0x0A && state["lastC${msg.endpointInt}"] == newState) {
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${msg.endpointInt}, State=${newState}"
return
}
state["lastC${msg.endpointInt}"] = newState

// Send button events only when the device reports any change, not on refresh
// Ignore open state for push buttons
// For push buttons, send events only on contact close
if (msg.commandInt == 0x0A && (buttonType == 'toggle' || newState == 'closed')) {
List<String> button = msg.endpointInt == 0x01 ? BUTTONS.ONE : BUTTONS.TWO
utils_sendEvent name:'pushed', value:button[0], type:'physical', isStateChange:true, descriptionText:"Button ${button[0]} (${button[1]}) was pushed"
}

// Send event to module child device (if contacts child devices are enabled)
if (enableContacts == true) {
Integer moduleNumber = msg.endpointInt
ChildDeviceWrapper childDevice = fetchChildDevice(moduleNumber)
if (newState != childDevice.currentValue('contact', true)) {
childDevice.parse([[name:'contact', value:newState, descriptionText:"${childDevice.displayName} is ${newState}", type:type]])
}
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${moduleNumber}, State=${newState}"
ChildDeviceWrapper childDevice = fetchChildDevice(msg.endpointInt)
childDevice.parse([[name:'contact', value:newState, descriptionText:"${childDevice.displayName} is ${newState}", type:type]])
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${msg.endpointInt}, State=${newState}"
}
return

Expand Down
75 changes: 36 additions & 39 deletions ikea-zigbee-drivers/Gewiss_GWA1502.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import com.hubitat.zigbee.DataType
import com.hubitat.app.ChildDeviceWrapper
import com.hubitat.app.DeviceWrapper

@Field static final Map<String, String> GWA1502_WORK_MODE = [
'button': 'Button - Track button events',
'sensor': 'Sensor - Track open/closed state using two Contact Sensor child devices',
]
@Field static final Map<String, String> GWA1502_BUTTON_TYPE = [
@Field static final Map<String, String> BUTTON_TYPES = [
'toggle': 'Rocker / Toggle',
'push': 'Push Button',
]
Expand Down Expand Up @@ -77,19 +73,16 @@ metadata {

// Inputs for devices.Gewiss_GWA1502
input(
name:'workMode', type:'enum', title:'Device mode', required:true,
description:'<small>Select device work mode.</small>',
options:GWA1502_WORK_MODE,
defaultValue:'button'
name:'buttonType', type:'enum', title:'Button type', required:true,
description:'<small>Select wired buttons type.</small>',
options:BUTTON_TYPES,
defaultValue:'toggle'
)
input(
name:'enableContacts', type:'bool', title:'Use as Contact Sensor', required:true,
description:'<small>Track open/closed state using two Contact Sensor child devices.</small>',
defaultValue:false
)
if (workMode != 'sensor') {
input(
name:'buttonType', type:'enum', title:'Button type', required:true,
description:'<small>Select wired buttons type.</small>',
options:GWA1502_BUTTON_TYPE,
defaultValue:'toggle'
)
}
}
}

Expand Down Expand Up @@ -119,12 +112,18 @@ List<String> updated(boolean auto = false) {
log_info "🛠️ logLevel = ${['1':'Debug', '2':'Info', '3':'Warning', '4':'Error'].get(logLevel)}"

// Preferences for devices.Gewiss_GWA1502
if (workMode == null) {
workMode = 'button'
device.updateSetting 'workMode', [value:workMode, type:'enum']
if (buttonType == null) {
buttonType = 'toggle'
device.updateSetting 'buttonType', [value:buttonType, type:'enum']
}
log_info "🛠️ buttonType = ${BUTTON_TYPES[buttonType]}"

if (enableContacts == null) {
enableContacts = false
device.updateSetting 'enableContacts', [value:false, type:'bool']
}
log_info "🛠️ workMode = ${GWA1502_WORK_MODE[workMode]}"
if (workMode == 'button') {
log_info "🛠️ enableContacts = ${enableContacts}"
if (enableContacts != true) {
ChildDeviceWrapper childDevice = getChildDevice("${device.deviceNetworkId}-1")
if (childDevice) {
log_debug "🎬 Removing child device ${childDevice} ..."
Expand All @@ -135,11 +134,6 @@ List<String> updated(boolean auto = false) {
log_debug "🎬 Removing child device ${childDevice} ..."
deleteChildDevice("${device.deviceNetworkId}-2")
}
if (buttonType == null) {
buttonType = 'toggle'
device.updateSetting 'buttonType', [value:buttonType, type:'enum']
}
log_info "🛠️ buttonType = ${GWA1502_BUTTON_TYPE[buttonType]}"
}

// Preferences for capability.HealthCheck
Expand Down Expand Up @@ -199,7 +193,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand All @@ -208,6 +202,8 @@ void configureApply() {
// Configuration for devices.Gewiss_GWA1502
cmds += "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0406 {${device.zigbeeId}} {}" // Occupancy Sensing cluster (ep 0x01)
cmds += "zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0406 {${device.zigbeeId}} {}" // Occupancy Sensing cluster (ep 0x02)
cmds += "he cr 0x${device.deviceNetworkId} 0x01 0x0406 0x0000 0x18 0x0000 0x0258 {01} {}" // Report Occupancy (map8) at least every 10 minutes (ep 0x01)
cmds += "he cr 0x${device.deviceNetworkId} 0x02 0x0406 0x0000 0x18 0x0000 0x0258 {01} {}" // Report Occupancy (map8) at least every 10 minutes (ep 0x02)

// Configuration for capability.HealthCheck
sendEvent name:'healthStatus', value:'online', descriptionText:'Health status initialized to online'
Expand Down Expand Up @@ -245,8 +241,6 @@ List<String> refresh(boolean auto = false) {
// Refresh for devices.Gewiss_GWA1502
cmds += zigbee.readAttribute(0x0406, 0x0000, [destEndpoint:0x01]) // Occupancy (ep 01)
cmds += zigbee.readAttribute(0x0406, 0x0000, [destEndpoint:0x02]) // Occupancy (ep 02)
cmds += "he cr 0x${device.deviceNetworkId} 0x01 0x0406 0x0000 0x18 0x0000 0x0258 {01} {}" // Disable periodic reporting for Occupancy (map8) at least every 10 minutes (ep 0x01)
cmds += "he cr 0x${device.deviceNetworkId} 0x02 0x0406 0x0000 0x18 0x0000 0x0258 {01} {}" // Disable periodic reporting for Occupancy (map8) at least every 10 minutes (ep 0x02)

if (auto) return cmds
utils_sendZigbeeCommands cmds
Expand Down Expand Up @@ -356,23 +350,26 @@ void parse(String description) {
case { contains it, [clusterInt:0x0406, commandInt:0x01, attrInt:0x0000] }:
String newState = msg.value == '01' ? 'closed' : 'open'

// Send event to module child device (if contacts child devices are enabled)
if (workMode == 'sensor') {
Integer moduleNumber = msg.endpointInt
ChildDeviceWrapper childDevice = fetchChildDevice(moduleNumber)
if (newState != childDevice.currentValue('contact', true)) {
childDevice.parse([[name:'contact', value:newState, descriptionText:"${childDevice.displayName} is ${newState}", type:type]])
}
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${moduleNumber}, State=${newState}"
// Ignore periodic reports with no state change
if (msg.commandInt == 0x0A && state["lastC${msg.endpointInt}"] == newState) {
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${msg.endpointInt}, State=${newState}"
return
}
state["lastC${msg.endpointInt}"] = newState

// Send button events only when the device reports any change, not on refresh
// Ignore open state for push buttons
// For push buttons, send events only on contact close
if (msg.commandInt == 0x0A && (buttonType == 'toggle' || newState == 'closed')) {
List<String> button = msg.endpointInt == 0x01 ? BUTTONS.ONE : BUTTONS.TWO
utils_sendEvent name:'pushed', value:button[0], type:'physical', isStateChange:true, descriptionText:"Button ${button[0]} (${button[1]}) was pushed"
}

// Send event to module child device (if contacts child devices are enabled)
if (enableContacts == true) {
ChildDeviceWrapper childDevice = fetchChildDevice(msg.endpointInt)
childDevice.parse([[name:'contact', value:newState, descriptionText:"${childDevice.displayName} is ${newState}", type:type]])
utils_processedZclMessage "${msg.commandInt == 0x0A ? 'Report' : 'Read'} Attributes Response", "Contact=${msg.endpointInt}, State=${newState}"
}
return

// Other events that we expect but are not usefull
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_CWS-Light.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_DIM-Light.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1603.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1743.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1745.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1746.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1766.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1810.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1812.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1836.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1841.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E1842.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E2002.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
2 changes: 1 addition & 1 deletion ikea-zigbee-drivers/Ikea_E2006.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void configure(boolean auto = false) {
runIn(cmds.findAll { !it.startsWith('delay') }.size() + 1, 'configureApply')
}
void configureApply() {
log_info "⚙️ Finishing device configuration ..."
log_info '⚙️ Finishing device configuration ...'
List<String> cmds = ["he raw 0x${device.deviceNetworkId} 0x01 0x01 0x0003 {014300 3C00}"]

// Auto-apply preferences
Expand Down
Loading

0 comments on commit b6c02ed

Please sign in to comment.