Skip to content

Commit d2d9433

Browse files
committed
Improve how attributes are requested during discovery
Signed-off-by: Chris Jackson <[email protected]>
1 parent b9c3034 commit d2d9433

File tree

1 file changed

+54
-35
lines changed

1 file changed

+54
-35
lines changed

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/discovery/ZigBeeNodePropertyDiscoverer.java

+54-35
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
*/
1313
package org.openhab.binding.zigbee.discovery;
1414

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-
1915
import java.util.ArrayList;
2016
import java.util.Collections;
2117
import java.util.HashMap;
@@ -42,6 +38,7 @@
4238
*
4339
* @author Chris Jackson - initial contribution
4440
* @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
4542
*/
4643
public class ZigBeeNodePropertyDiscoverer {
4744

@@ -50,13 +47,13 @@ public class ZigBeeNodePropertyDiscoverer {
5047
private static final Map<String, Integer> BASIC_CLUSTER_ATTRIBUTES_FOR_THING_PROPERTY;
5148
static {
5249
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);
6057
BASIC_CLUSTER_ATTRIBUTES_FOR_THING_PROPERTY = Collections.unmodifiableMap(map);
6158
}
6259

@@ -116,21 +113,25 @@ public Map<String, String> getProperties(final ZigBeeNode node) {
116113

117114
private void addPropertiesFromNodeDescriptors(ZigBeeNode node) {
118115
if (node.getLogicalType() != null) {
119-
properties.put(THING_PROPERTY_LOGICALTYPE, node.getLogicalType().toString());
116+
properties.put(ZigBeeBindingConstants.THING_PROPERTY_LOGICALTYPE, node.getLogicalType().toString());
120117
}
121118

122-
properties.put(THING_PROPERTY_NETWORKADDRESS, node.getNetworkAddress().toString());
119+
properties.put(ZigBeeBindingConstants.THING_PROPERTY_NETWORKADDRESS, node.getNetworkAddress().toString());
123120

124121
PowerDescriptor powerDescriptor = node.getPowerDescriptor();
125122
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());
130131
}
131132

132133
if (node.getNodeDescriptor() != null) {
133-
properties.put(THING_PROPERTY_MANUFACTURERCODE,
134+
properties.put(ZigBeeBindingConstants.THING_PROPERTY_MANUFACTURERCODE,
134135
String.format("0x%04x", node.getNodeDescriptor().getManufacturerCode()));
135136
}
136137
}
@@ -151,6 +152,9 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
151152
// Attempt to read all properties with a single command.
152153
// If successful, this updates the cache with the property values.
153154
try {
155+
// Try to get the supported attributes so we can reduce the number of attribute read requests
156+
basicCluster.discoverAttributes(false).get();
157+
154158
Map<String, Integer> propertiesToRead = getPropertiesToRead(basicCluster);
155159
List<Integer> attributes = new ArrayList<>(propertiesToRead.values());
156160
if (!attributes.isEmpty()) {
@@ -164,62 +168,76 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
164168
// Now, get each single property via the basic cluster. If the above multi-attribute read was successful,
165169
// this will get each property from the cache. Otherwise, it will try to get the property from the device again.
166170

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);
169175
if (manufacturer != null) {
170176
properties.put(Thing.PROPERTY_VENDOR, manufacturer.trim());
171177
} else {
172178
logger.debug("{}: Manufacturer request failed", node.getIeeeAddress());
173179
}
174180
}
175181

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);
178186
if (model != null) {
179187
properties.put(Thing.PROPERTY_MODEL_ID, model.trim());
180188
} else {
181189
logger.debug("{}: Model request failed", node.getIeeeAddress());
182190
}
183191
}
184192

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);
187197
if (hwVersion != null) {
188198
properties.put(Thing.PROPERTY_HARDWARE_VERSION, hwVersion.toString());
189199
} else {
190200
logger.debug("{}: Hardware version failed", node.getIeeeAddress());
191201
}
192202
}
193203

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);
196208
if (appVersion != null) {
197209
properties.put(ZigBeeBindingConstants.THING_PROPERTY_APPLICATIONVERSION, appVersion.toString());
198210
} else {
199211
logger.debug("{}: Application version failed", node.getIeeeAddress());
200212
}
201213
}
202214

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);
205219
if (stkVersion != null) {
206220
properties.put(ZigBeeBindingConstants.THING_PROPERTY_STKVERSION, stkVersion.toString());
207221
} else {
208222
logger.debug("{}: Stack version failed", node.getIeeeAddress());
209223
}
210224
}
211225

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);
214230
if (zclVersion != null) {
215231
properties.put(ZigBeeBindingConstants.THING_PROPERTY_ZCLVERSION, zclVersion.toString());
216232
} else {
217233
logger.debug("{}: ZCL version failed", node.getIeeeAddress());
218234
}
219235
}
220236

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);
223241
if (dateCode != null) {
224242
properties.put(ZigBeeBindingConstants.THING_PROPERTY_DATECODE, dateCode);
225243
} else {
@@ -232,8 +250,9 @@ private void addPropertiesFromBasicCluster(ZigBeeNode node) {
232250
private Map<String, Integer> getPropertiesToRead(ZclBasicCluster basicCluster) {
233251
Map<String, Integer> result = new HashMap<>();
234252
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()) {
237256
result.put(entry.getKey(), entry.getValue());
238257
}
239258
}
@@ -252,7 +271,7 @@ private void addPropertiesFromOtaCluster(ZigBeeNode node) {
252271
ZclAttribute attribute = otaCluster.getAttribute(ZclOtaUpgradeCluster.ATTR_CURRENTFILEVERSION);
253272
Object fileVersion = attribute.readValue(Long.MAX_VALUE);
254273
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));
256275
} else {
257276
logger.debug("{}: Could not get OTA firmware version from device", node.getIeeeAddress());
258277
}

0 commit comments

Comments
 (0)