Fixed zigbee on off events

This commit is contained in:
Ziver Koc 2021-07-19 23:51:29 +02:00
parent 203bb67f7f
commit 68054ebf4f
12 changed files with 114 additions and 39 deletions

View file

@ -27,13 +27,13 @@ import se.hal.plugin.zigbee.device.*;
import zutil.Timer;
import zutil.log.LogUtil;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.zsmartsystems.zigbee.zcl.clusters.ZclBasicCluster.*;
/**
* Controller that will connect to a Zigbee USB coordinator.
*/
@ -289,15 +289,30 @@ public class ZigbeeController implements HalSensorController,
ZclCluster cluster = endpoint.getInputCluster(inputClusterId);
ZigbeeHalDeviceConfig config = createDeviceConfig(inputClusterId);
if (cluster != null && config != null) {
// Read basic attributes
if (cluster instanceof ZclBasicCluster) {
try {
cluster.readAttributes(Arrays.asList(
ZclBasicCluster.ATTR_MANUFACTURERNAME,
ZclBasicCluster.ATTR_MODELIDENTIFIER,
ZclBasicCluster.ATTR_HWVERSION,
ZclBasicCluster.ATTR_APPLICATIONVERSION,
ZclBasicCluster.ATTR_STACKVERSION,
ZclBasicCluster.ATTR_ZCLVERSION,
ZclBasicCluster.ATTR_DATECODE
)).get();
} catch (Exception e) {
logger.log(Level.WARNING, "Was unable to read basic device information.", e);
}
}
// Handle specific node attributes
else if (cluster != null && config != null) {
config.setZigbeeNodeAddress(endpoint.getIeeeAddress());
config.initialize(cluster);
cluster.addAttributeListener(new ZclAttributeListener() {
@Override
public void attributeUpdated(ZclAttribute attribute, Object value) {
if (attribute.getId() != 0) // Only report on Measured Value attribute updates
return;
logger.finer("[Node: " + endpoint.getIeeeAddress() + ", Endpoint: " + endpoint.getEndpointId() + ", Cluster: " + attribute.getCluster().getId() + "] Attribute " + config.getClass().getSimpleName() + " updated: id=" + attribute.getId() + ", attribute_name=" + attribute.getName() + ", value=" + attribute.getLastValue());
for (HalDeviceReportListener deviceListener : deviceListeners) {
deviceListener.reportReceived(config, config.getDeviceData(attribute));

View file

@ -2,6 +2,7 @@ package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.IeeeAddress;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.ZclCluster;
import se.hal.intf.HalAbstractController;
import se.hal.intf.HalDeviceConfig;
import se.hal.intf.HalDeviceData;
@ -30,6 +31,14 @@ public abstract class ZigbeeHalDeviceConfig implements HalDeviceConfig {
// Abstract Methods
// --------------------------
/**
* Method will configured a newly discovered or updated cluster. Method by default
* does nothing and will need to be extended by subclasses to add specific initialization logic.
*
* @param cluster is the cluster to be initialized.
*/
public void initialize(ZclCluster cluster) {}
/**
* @param zclAttribute
* @return a HalDeviceData object containing the same value representation as the endpoint.

View file

@ -9,6 +9,9 @@ import com.zsmartsystems.zigbee.zcl.ZclCommand;
import se.hal.intf.HalEventData;
import zutil.log.LogUtil;
import java.lang.reflect.Method;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
@ -31,15 +34,19 @@ public abstract class ZigbeeHalEventDeviceConfig extends ZigbeeHalDeviceConfig {
return null;
}
@SuppressWarnings("unchecked")
public void sendZigbeeCommand(ZigBeeNetworkManager networkManager, HalEventData data) {
ZclCluster cluster = getZigbeeCluster(networkManager);
if (cluster != null) {
try {
ZclCommand command = getZigbeeCommandObject(data);
// Need to do reflection as the generic method has visibility protected.
CommandResult result =
(CommandResult) ZclCluster.class.getMethod("sendCommand", ZclCommand.class).invoke(command);
Method method = ZclCluster.class.getDeclaredMethod("sendCommand", ZclCommand.class);
method.setAccessible(true);
CommandResult result = ((Future<CommandResult>) method.invoke(cluster, command)).get();
if (result.isError() || result.isTimeout()) {
logger.warning("[Node: " + getZigbeeNodeAddress() + ", Endpoint: " + cluster.getZigBeeAddress() + "] Command failed with error: " + result.isError() + " (timeout=" + result.isTimeout() + ")");
@ -47,7 +54,7 @@ public abstract class ZigbeeHalEventDeviceConfig extends ZigbeeHalDeviceConfig {
logger.info("[Node: " + getZigbeeNodeAddress() + ", Endpoint: " + cluster.getZigBeeAddress() + "] Command has been successfully sent.");
}
} catch (Exception e) {
logger.warning("[Node: " + getZigbeeNodeAddress() + ", Endpoint: " + cluster.getZigBeeAddress() + "] Failed to send command: " + e.getMessage());
logger.log(Level.WARNING, "[Node: " + getZigbeeNodeAddress() + ", Endpoint: " + cluster.getZigBeeAddress() + "] Failed to send command.", e);
}
} else {
logger.warning("[Node: " + getZigbeeNodeAddress() + "] Unable to find cluster: " + getZigbeeClusterId());

View file

@ -18,7 +18,11 @@ public class ZigbeeHumidityConfig extends ZigbeeHalDeviceConfig implements HalSe
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
return new HumiditySensorData(((int) zclAttribute.getLastValue()) / 100.0, zclAttribute.getLastReportTime().getTimeInMillis());
if (zclAttribute.getId() == ZclRelativeHumidityMeasurementCluster.ATTR_MEASUREDVALUE)
return new HumiditySensorData(
((int) zclAttribute.getLastValue()) / 100.0,
zclAttribute.getLastReportTime().getTimeInMillis());
return null;
}
@Override

View file

@ -1,6 +1,5 @@
package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.ZclCluster;
import com.zsmartsystems.zigbee.zcl.ZclCommand;
@ -11,18 +10,41 @@ import se.hal.intf.HalDeviceData;
import se.hal.intf.HalEventConfig;
import se.hal.intf.HalEventData;
import se.hal.struct.devicedata.OnOffEventData;
import zutil.log.LogUtil;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A device configuration for a specific endpoint on a Zigbee device.
*/
public class ZigbeeOnOffConfig extends ZigbeeHalEventDeviceConfig implements HalEventConfig {
private static final Logger logger = LogUtil.getLogger();
// --------------------------
// Zigbee Methods
// --------------------------
@Override
public void initialize(ZclCluster cluster) {
if (! (cluster instanceof ZclOnOffCluster))
return;
try {
ZclAttribute attribute = cluster.getAttribute(ZclOnOffCluster.ATTR_ONOFF);
attribute.setReporting(1, 900).get();
attribute.readValue(60);
} catch (Exception e) {
logger.log(Level.WARNING, "Was unable to initialize cluster reporting rate.", e);
}
}
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getId() == ZclOnOffCluster.ATTR_ONOFF)
return new OnOffEventData(
(boolean) zclAttribute.getLastValue(),
zclAttribute.getLastReportTime().getTimeInMillis());
return null;
}

View file

@ -19,7 +19,11 @@ public class ZigbeePressureConfig extends ZigbeeHalDeviceConfig implements HalSe
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
return new PressureSensorData(((int) zclAttribute.getLastValue()), zclAttribute.getLastReportTime().getTimeInMillis());
if (zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MAXMEASUREDVALUE)
return new PressureSensorData(
(int) zclAttribute.getLastValue(),
zclAttribute.getLastReportTime().getTimeInMillis());
return null;
}
@Override

View file

@ -18,7 +18,11 @@ public class ZigbeeTemperatureConfig extends ZigbeeHalDeviceConfig implements Ha
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
return new TemperatureSensorData(((int) zclAttribute.getLastValue()) / 100.0, zclAttribute.getLastReportTime().getTimeInMillis());
if (zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
return new TemperatureSensorData(
((int) zclAttribute.getLastValue()) / 100.0,
zclAttribute.getLastReportTime().getTimeInMillis());
return null;
}
@Override

View file

@ -27,16 +27,17 @@ public class ZigbeeNodeOverviewPage extends HalWebPage {
Map<String, String> request)
throws Exception {
Set<ZigBeeNode> nodes = null;
for (HalAbstractController controller : HalAbstractControllerManager.getControllers()) {
if (controller instanceof ZigbeeController) {
nodes = ((ZigbeeController) controller).getNodes();
ZigbeeController controller = null;
for (HalAbstractController cont : HalAbstractControllerManager.getControllers()) {
if (cont instanceof ZigbeeController) {
controller = ((ZigbeeController) cont);
break;
}
}
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
tmpl.set("nodes", nodes);
tmpl.set("controller", controller);
tmpl.set("nodes", controller.getNodes());
return tmpl;
}
}