-
Notifications
You must be signed in to change notification settings - Fork 175
/
Hue Dimmer Remote as Button Controller.groovy
152 lines (121 loc) · 5.38 KB
/
Hue Dimmer Remote as Button Controller.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
*
*
* 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.
*
*/
/* Philips Hue Wireless Dimmer
Capabilities:
Actuator
Configuration
Button
Sensor
*/
metadata {
definition (name: "Hue Dimmer Button Controller", namespace: "Sticks18", author: "Scott G") {
capability "Actuator"
capability "Button"
capability "Configuration"
capability "Sensor"
// fingerprint specific to Hue remote taken from Basic Cluster.
fingerprint profileId: "C05E", inClusters: "0000", outClusters: "0000,0003,0004,0006,0008", manufacturer: "Philips", model: "RWL020"
}
// simulator metadata
simulator {
// status messages
}
// UI tile definitions
tiles {
standardTile("button", "device.button", width: 2, height: 2) {
state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
}
main "button"
details(["button"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
// next line is debugging code to see raw zigbee message. no longer needed
// log.trace description
// Create a map from the raw zigbee message to make parsing more intuitive
def msg = zigbee.parse(description)
// Check if the message comes from the on/off cluster (0x0006 in zigbee) to determine if button was On or Off
if (msg.clusterId == 6) {
// Command 1 is the zigbee 'on' command, so make that button 1. Else it must be 'off' command, make that button 4.
// Then create the button press event. All button events with be of type "pushed", not "held".
def button = (msg.command == 1 ? 1 : 4)
def result = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug "Parse returned ${result?.descriptionText}"
return result
}
// Check if message comes from the level cluster (0x0008 in zigbee) to determine if button was dim up/down
if (msg.clusterId == 8) {
// Remote sends move level and stop commands when dim up/down pushed or held
// Additional parsing and debugging created for when buttons are held, but not creating events for them
// since it is difficult to separate them from pushed events
switch (msg.command)
{
// Move level command means dim/up down was pushed or held
case 2:
// Position -6 and -5 is the two digit hex of the move step size, which is different for an initial push vs a hold
// Check it for the initial push value '1E'
def y = description[-6..-5]
if (y == "1E") {
// Determine the button push by looking at the move direction determined in position -8 and -7
// "00" means to move up in level, so dim up button was pushed. Create button event
def button = (description[-8..-7] == "00" ? 2 : 3)
def result = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug "Parse returned ${result?.descriptionText}"
return result
break
}
// If move step size is not '1E' then the button is being held. Send debug message, but take no action
log.debug "Received held message"
break
case 3:
// If level command is 3, then stop moving command was sent. Send debug message, but take no action.
// This stop command could be used to get a button 'held' event, but we would need to ignore the initial button push
log.debug "Received stop message"
break
}
}
}
// Configuration runs during device join
def configure() {
log.debug "configure"
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting and Bindings."
def configCmds = [
// Bind the outgoing on/off cluster from remote to hub, so remote sends hub messages when On/Off buttons pushed
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 1000",
// Bind the outgoing level cluster from remote to hub, so remote sends hub messages when Dim Up/Down buttons pushed
"zdo bind 0x${device.deviceNetworkId} 1 1 8 {${device.zigbeeId}} {}", "delay 500",
]
return configCmds
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
}