12
12
*/
13
13
package org .openhab .binding .zigbee .discovery ;
14
14
15
- import static com .zsmartsystems .zigbee .zcl .clusters .ZclBasicCluster .*;
16
- import static org .eclipse .smarthome .core .thing .Thing .*;
17
- import static org .openhab .binding .zigbee .ZigBeeBindingConstants .*;
18
-
19
15
import java .util .ArrayList ;
20
16
import java .util .Collections ;
21
17
import java .util .HashMap ;
42
38
*
43
39
* @author Chris Jackson - initial contribution
44
40
* @author Henning Sudbrock - read multiple attributes from basic cluster with a single command to speedup discovery
41
+ * @author Chris Jackson - fix issue with reading multiple attributes that are unsupported
45
42
*/
46
43
public class ZigBeeNodePropertyDiscoverer {
47
44
@@ -50,13 +47,13 @@ public class ZigBeeNodePropertyDiscoverer {
50
47
private static final Map <String , Integer > BASIC_CLUSTER_ATTRIBUTES_FOR_THING_PROPERTY ;
51
48
static {
52
49
Map <String , Integer > map = new HashMap <String , Integer >();
53
- map .put (PROPERTY_VENDOR , ATTR_MANUFACTURERNAME );
54
- map .put (PROPERTY_MODEL_ID , ATTR_MODELIDENTIFIER );
55
- map .put (PROPERTY_HARDWARE_VERSION , ATTR_HWVERSION );
56
- map .put (THING_PROPERTY_APPLICATIONVERSION , ATTR_APPLICATIONVERSION );
57
- map .put (THING_PROPERTY_STKVERSION , ATTR_STACKVERSION );
58
- map .put (THING_PROPERTY_ZCLVERSION , ATTR_ZCLVERSION );
59
- map .put (THING_PROPERTY_DATECODE , ATTR_DATECODE );
50
+ map .put (Thing . PROPERTY_VENDOR , ZclBasicCluster . ATTR_MANUFACTURERNAME );
51
+ map .put (Thing . PROPERTY_MODEL_ID , ZclBasicCluster . ATTR_MODELIDENTIFIER );
52
+ map .put (Thing . PROPERTY_HARDWARE_VERSION , ZclBasicCluster . ATTR_HWVERSION );
53
+ map .put (ZigBeeBindingConstants . THING_PROPERTY_APPLICATIONVERSION , ZclBasicCluster . ATTR_APPLICATIONVERSION );
54
+ map .put (ZigBeeBindingConstants . THING_PROPERTY_STKVERSION , ZclBasicCluster . ATTR_STACKVERSION );
55
+ map .put (ZigBeeBindingConstants . THING_PROPERTY_ZCLVERSION , ZclBasicCluster . ATTR_ZCLVERSION );
56
+ map .put (ZigBeeBindingConstants . THING_PROPERTY_DATECODE , ZclBasicCluster . ATTR_DATECODE );
60
57
BASIC_CLUSTER_ATTRIBUTES_FOR_THING_PROPERTY = Collections .unmodifiableMap (map );
61
58
}
62
59
@@ -116,21 +113,25 @@ public Map<String, String> getProperties(final ZigBeeNode node) {
116
113
117
114
private void addPropertiesFromNodeDescriptors (ZigBeeNode node ) {
118
115
if (node .getLogicalType () != null ) {
119
- properties .put (THING_PROPERTY_LOGICALTYPE , node .getLogicalType ().toString ());
116
+ properties .put (ZigBeeBindingConstants . THING_PROPERTY_LOGICALTYPE , node .getLogicalType ().toString ());
120
117
}
121
118
122
- properties .put (THING_PROPERTY_NETWORKADDRESS , node .getNetworkAddress ().toString ());
119
+ properties .put (ZigBeeBindingConstants . THING_PROPERTY_NETWORKADDRESS , node .getNetworkAddress ().toString ());
123
120
124
121
PowerDescriptor powerDescriptor = node .getPowerDescriptor ();
125
122
if (powerDescriptor != null ) {
126
- properties .put (THING_PROPERTY_AVAILABLEPOWERSOURCES , powerDescriptor .getAvailablePowerSources ().toString ());
127
- properties .put (THING_PROPERTY_POWERSOURCE , powerDescriptor .getCurrentPowerSource ().toString ());
128
- properties .put (THING_PROPERTY_POWERMODE , powerDescriptor .getCurrentPowerMode ().toString ());
129
- properties .put (THING_PROPERTY_POWERLEVEL , powerDescriptor .getPowerLevel ().toString ());
123
+ properties .put (ZigBeeBindingConstants .THING_PROPERTY_AVAILABLEPOWERSOURCES ,
124
+ powerDescriptor .getAvailablePowerSources ().toString ());
125
+ properties .put (ZigBeeBindingConstants .THING_PROPERTY_POWERSOURCE ,
126
+ powerDescriptor .getCurrentPowerSource ().toString ());
127
+ properties .put (ZigBeeBindingConstants .THING_PROPERTY_POWERMODE ,
128
+ powerDescriptor .getCurrentPowerMode ().toString ());
129
+ properties .put (ZigBeeBindingConstants .THING_PROPERTY_POWERLEVEL ,
130
+ powerDescriptor .getPowerLevel ().toString ());
130
131
}
131
132
132
133
if (node .getNodeDescriptor () != null ) {
133
- properties .put (THING_PROPERTY_MANUFACTURERCODE ,
134
+ properties .put (ZigBeeBindingConstants . THING_PROPERTY_MANUFACTURERCODE ,
134
135
String .format ("0x%04x" , node .getNodeDescriptor ().getManufacturerCode ()));
135
136
}
136
137
}
@@ -151,6 +152,9 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
151
152
// Attempt to read all properties with a single command.
152
153
// If successful, this updates the cache with the property values.
153
154
try {
155
+ // Try to get the supported attributes so we can reduce the number of attribute read requests
156
+ basicCluster .discoverAttributes (false ).get ();
157
+
154
158
Map <String , Integer > propertiesToRead = getPropertiesToRead (basicCluster );
155
159
List <Integer > attributes = new ArrayList <>(propertiesToRead .values ());
156
160
if (!attributes .isEmpty ()) {
@@ -164,62 +168,76 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
164
168
// Now, get each single property via the basic cluster. If the above multi-attribute read was successful,
165
169
// this will get each property from the cache. Otherwise, it will try to get the property from the device again.
166
170
167
- if (alwaysUpdate || properties .get (Thing .PROPERTY_VENDOR ) == null ) {
168
- String manufacturer = basicCluster .getManufacturerName (Long .MAX_VALUE );
171
+ if ((alwaysUpdate || properties .get (Thing .PROPERTY_VENDOR ) == null )
172
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_MANUFACTURERNAME )) {
173
+ String manufacturer = (String ) basicCluster .getAttribute (ZclBasicCluster .ATTR_MANUFACTURERNAME )
174
+ .readValue (Long .MAX_VALUE );
169
175
if (manufacturer != null ) {
170
176
properties .put (Thing .PROPERTY_VENDOR , manufacturer .trim ());
171
177
} else {
172
178
logger .debug ("{}: Manufacturer request failed" , node .getIeeeAddress ());
173
179
}
174
180
}
175
181
176
- if (alwaysUpdate || properties .get (Thing .PROPERTY_MODEL_ID ) == null ) {
177
- String model = basicCluster .getModelIdentifier (Long .MAX_VALUE );
182
+ if ((alwaysUpdate || properties .get (Thing .PROPERTY_MODEL_ID ) == null )
183
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_MODELIDENTIFIER )) {
184
+ String model = (String ) basicCluster .getAttribute (ZclBasicCluster .ATTR_MODELIDENTIFIER )
185
+ .readValue (Long .MAX_VALUE );
178
186
if (model != null ) {
179
187
properties .put (Thing .PROPERTY_MODEL_ID , model .trim ());
180
188
} else {
181
189
logger .debug ("{}: Model request failed" , node .getIeeeAddress ());
182
190
}
183
191
}
184
192
185
- if (alwaysUpdate || properties .get (Thing .PROPERTY_HARDWARE_VERSION ) == null ) {
186
- Integer hwVersion = basicCluster .getHwVersion (Long .MAX_VALUE );
193
+ if ((alwaysUpdate || properties .get (Thing .PROPERTY_HARDWARE_VERSION ) == null )
194
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_MODELIDENTIFIER )) {
195
+ Integer hwVersion = (Integer ) basicCluster .getAttribute (ZclBasicCluster .ATTR_HWVERSION )
196
+ .readValue (Long .MAX_VALUE );
187
197
if (hwVersion != null ) {
188
198
properties .put (Thing .PROPERTY_HARDWARE_VERSION , hwVersion .toString ());
189
199
} else {
190
200
logger .debug ("{}: Hardware version failed" , node .getIeeeAddress ());
191
201
}
192
202
}
193
203
194
- if (alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_APPLICATIONVERSION ) == null ) {
195
- Integer appVersion = basicCluster .getApplicationVersion (Long .MAX_VALUE );
204
+ if ((alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_APPLICATIONVERSION ) == null )
205
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_MODELIDENTIFIER )) {
206
+ Integer appVersion = (Integer ) basicCluster .getAttribute (ZclBasicCluster .ATTR_APPLICATIONVERSION )
207
+ .readValue (Long .MAX_VALUE );
196
208
if (appVersion != null ) {
197
209
properties .put (ZigBeeBindingConstants .THING_PROPERTY_APPLICATIONVERSION , appVersion .toString ());
198
210
} else {
199
211
logger .debug ("{}: Application version failed" , node .getIeeeAddress ());
200
212
}
201
213
}
202
214
203
- if (alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_STKVERSION ) == null ) {
204
- Integer stkVersion = basicCluster .getStackVersion (Long .MAX_VALUE );
215
+ if ((alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_STKVERSION ) == null )
216
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_STACKVERSION )) {
217
+ Integer stkVersion = (Integer ) basicCluster .getAttribute (ZclBasicCluster .ATTR_STACKVERSION )
218
+ .readValue (Long .MAX_VALUE );
205
219
if (stkVersion != null ) {
206
220
properties .put (ZigBeeBindingConstants .THING_PROPERTY_STKVERSION , stkVersion .toString ());
207
221
} else {
208
222
logger .debug ("{}: Stack version failed" , node .getIeeeAddress ());
209
223
}
210
224
}
211
225
212
- if (alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_ZCLVERSION ) == null ) {
213
- Integer zclVersion = basicCluster .getZclVersion (Long .MAX_VALUE );
226
+ if ((alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_ZCLVERSION ) == null )
227
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_ZCLVERSION )) {
228
+ Integer zclVersion = (Integer ) basicCluster .getAttribute (ZclBasicCluster .ATTR_ZCLVERSION )
229
+ .readValue (Long .MAX_VALUE );
214
230
if (zclVersion != null ) {
215
231
properties .put (ZigBeeBindingConstants .THING_PROPERTY_ZCLVERSION , zclVersion .toString ());
216
232
} else {
217
233
logger .debug ("{}: ZCL version failed" , node .getIeeeAddress ());
218
234
}
219
235
}
220
236
221
- if (alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_DATECODE ) == null ) {
222
- String dateCode = basicCluster .getDateCode (Long .MAX_VALUE );
237
+ if ((alwaysUpdate || properties .get (ZigBeeBindingConstants .THING_PROPERTY_DATECODE ) == null )
238
+ && basicCluster .isAttributeSupported (ZclBasicCluster .ATTR_ZCLVERSION )) {
239
+ String dateCode = (String ) basicCluster .getAttribute (ZclBasicCluster .ATTR_DATECODE )
240
+ .readValue (Long .MAX_VALUE );
223
241
if (dateCode != null ) {
224
242
properties .put (ZigBeeBindingConstants .THING_PROPERTY_DATECODE , dateCode );
225
243
} else {
@@ -232,8 +250,9 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
232
250
private Map <String , Integer > getPropertiesToRead (ZclBasicCluster basicCluster ) {
233
251
Map <String , Integer > result = new HashMap <>();
234
252
for (Map .Entry <String , Integer > entry : BASIC_CLUSTER_ATTRIBUTES_FOR_THING_PROPERTY .entrySet ()) {
235
- if (alwaysUpdate || properties .get (entry .getKey ()) == null
236
- || !basicCluster .getAttribute (entry .getValue ()).isLastValueCurrent (Long .MAX_VALUE )) {
253
+ ZclAttribute attribute = basicCluster .getAttribute (entry .getValue ());
254
+ if ((alwaysUpdate || properties .get (entry .getKey ()) == null
255
+ || !attribute .isLastValueCurrent (Long .MAX_VALUE )) && attribute .isImplemented ()) {
237
256
result .put (entry .getKey (), entry .getValue ());
238
257
}
239
258
}
@@ -252,7 +271,7 @@ private void addPropertiesFromOtaCluster(ZigBeeNode node) {
252
271
ZclAttribute attribute = otaCluster .getAttribute (ZclOtaUpgradeCluster .ATTR_CURRENTFILEVERSION );
253
272
Object fileVersion = attribute .readValue (Long .MAX_VALUE );
254
273
if (fileVersion != null ) {
255
- properties .put (PROPERTY_FIRMWARE_VERSION , String .format ("0x%08X" , fileVersion ));
274
+ properties .put (Thing . PROPERTY_FIRMWARE_VERSION , String .format ("0x%08X" , fileVersion ));
256
275
} else {
257
276
logger .debug ("{}: Could not get OTA firmware version from device" , node .getIeeeAddress ());
258
277
}
0 commit comments