Implementation of level and color data types

This commit is contained in:
Ziver Koc 2023-05-06 01:11:10 +02:00
parent a89b418350
commit 234125bc35
30 changed files with 664 additions and 113 deletions

View file

@ -1,5 +1,5 @@
dependencies {
def ZIGBEE_LIB_VERSION = "1.3.8"
def ZIGBEE_LIB_VERSION = "1.4.11"
implementation project(':hal-core')

View file

@ -35,10 +35,19 @@
<div class="panel panel-default drop-shadow">
<!-- NODE -->
<div class="panel-heading">
<a href="#a" data-toggle="collapse" data-target="#node-{{.getIeeeAddress()}}">
Node: {{.getIeeeAddress()}}
</a>
<div class="panel-heading clearfix">
<a href="#a" class="pull-left" data-toggle="collapse" data-target="#node-{{.getIeeeAddress()}}">
Node: {{.getIeeeAddress()}}
</a>
<div class="btn-toolbar pull-right">
<form method="POST">
<input type="hidden" name="nodeAddress" value="{{.getIeeeAddress()}}">
<button type="submit" class="btn btn-danger btn-xs" name="action" value="node_remove">
<small class="glyphicon glyphicon-trash"></small>
</button>
</form>
</div>
</div>
<div id="node-{{.getIeeeAddress()}}" class="panel-body collapse">
<div class="col-md-6">
@ -122,6 +131,7 @@
<thead>
<th>ID</th>
<th>Name</th>
<th>Type</th>
<th>Last Value</th>
<th>Last Report Time</th>
<th></th>
@ -130,6 +140,7 @@
<tr>
<td>{{.getId()}}</td>
<td>{{.getName()}}</td>
<td>{{.getDataType()}}</td>
<td>{{.getLastValue()}}</td>
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
<td>
@ -168,6 +179,7 @@
<thead>
<th>ID</th>
<th>Name</th>
<th>Type</th>
<th>Last Value</th>
<th>Last Report Time</th>
<th></th>
@ -176,6 +188,7 @@
<tr>
<td>{{.getId()}}</td>
<td>{{.getName()}}</td>
<td>{{.getDataType()}}</td>
<td>{{.getLastValue()}}</td>
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
<td></td>

View file

@ -231,6 +231,10 @@ public class ZigbeeController implements HalSensorController,
// Zigbee Node Methods
// ------------------------------------------
public void unPairNode(ZigBeeNode node) {
networkManager.leave(node.getNetworkAddress(), node.getIeeeAddress(), true);
}
@Override
public void deviceStatusUpdate(ZigBeeNodeStatus deviceStatus, Integer networkAddress, IeeeAddress ieeeAddress) {
logger.fine("New device connected to network: " + ieeeAddress + "(" + deviceStatus + ")");
@ -402,7 +406,7 @@ public class ZigbeeController implements HalSensorController,
public void attributeUpdated(ZclAttribute attribute, Object value) {
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());
HalDeviceData data = config.getDeviceData(attribute);
HalDeviceData data = config.getDeviceData(endpoint, attribute);
if (data != null) {
for (HalDeviceReportListener deviceListener : deviceListeners) {
deviceListener.reportReceived(config, data);

View file

@ -0,0 +1,84 @@
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;
import com.zsmartsystems.zigbee.zcl.clusters.ZclColorControlCluster;
import com.zsmartsystems.zigbee.zcl.clusters.colorcontrol.MoveToColorCommand;
import se.hal.intf.HalDeviceData;
import se.hal.intf.HalEventConfig;
import se.hal.intf.HalEventData;
import se.hal.struct.devicedata.ColorEventData;
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 ZigbeeColorConfig extends ZigbeeHalEventDeviceConfig implements HalEventConfig {
private static final Logger logger = LogUtil.getLogger();
// --------------------------
// Zigbee Methods
// --------------------------
@Override
public void initialize(ZclCluster cluster) {
if (! (cluster instanceof ZclColorControlCluster))
return;
try {
ZclAttribute attribute = cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTHUE);
attribute.setReporting(1, 900).get();
attribute.readValue(60);
attribute = cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTSATURATION);
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(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
(zclAttribute.getId() == ZclColorControlCluster.ATTR_CURRENTHUE ||
zclAttribute.getId() == ZclColorControlCluster.ATTR_CURRENTSATURATION)) {
ZclCluster cluster = endpoint.getInputCluster(zclAttribute.getClusterType().getId());
float hue = (Integer) cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTHUE).getLastValue();
float saturation = (Integer) cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTSATURATION).getLastValue();
return ColorEventData.createFromHLS(
hue, 0.5f, saturation,
zclAttribute.getLastReportTime().getTimeInMillis());
}
return null;
}
@Override
public int getZigbeeClusterId() {
return ZclColorControlCluster.CLUSTER_ID;
}
@Override
protected ZclCommand getZigbeeCommandObject(HalEventData data) {
if (! (data instanceof ColorEventData))
return null;
float[] cieXYZ = ((ColorEventData) data).getCieXYZ();
return new MoveToColorCommand((int) cieXYZ[0], (int) cieXYZ[1], 1);
}
// --------------------------
// Hal Methods
// --------------------------
@Override
public Class<? extends HalDeviceData> getDeviceDataClass() {
return ColorEventData.class;
}
}

View file

@ -66,10 +66,11 @@ public abstract class ZigbeeHalDeviceConfig implements HalDeviceConfig {
public void initialize(ZclCluster cluster) {}
/**
* @param endpoint
* @param zclAttribute is the object that should be mapped to a HalDeviceFata object.
* @return a HalDeviceData object containing the same value representation as the endpoint or null if this attribute is not translatable.
*/
public abstract HalDeviceData getDeviceData(ZclAttribute zclAttribute);
public abstract HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute);
/**
* @return the cluster ID that is supported by this device config class

View file

@ -15,8 +15,10 @@ public class ZigbeeHalDeviceFactory {
private static final HashMap<Integer, Class<? extends ZigbeeHalDeviceConfig>> clusterDeviceMap = new HashMap<>();
static {
clusterDeviceMap.put(new ZigbeeColorConfig().getZigbeeClusterId(), ZigbeeColorConfig.class);
clusterDeviceMap.put(new ZigbeeHumidityConfig().getZigbeeClusterId(), ZigbeeHumidityConfig.class);
clusterDeviceMap.put(new ZigbeeIlluminanceConfig().getZigbeeClusterId(), ZigbeeIlluminanceConfig.class);
clusterDeviceMap.put(new ZigbeeLevelConfig().getZigbeeClusterId(), ZigbeeLevelConfig.class);
clusterDeviceMap.put(new ZigbeeOccupancyConfig().getZigbeeClusterId(), ZigbeeOccupancyConfig.class);
clusterDeviceMap.put(new ZigbeeOnOffConfig().getZigbeeClusterId(), ZigbeeOnOffConfig.class);
clusterDeviceMap.put(new ZigbeePressureConfig().getZigbeeClusterId(), ZigbeePressureConfig.class);

View file

@ -1,11 +1,11 @@
package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.clusters.ZclRelativeHumidityMeasurementCluster;
import se.hal.intf.HalDeviceData;
import se.hal.intf.HalSensorConfig;
import se.hal.struct.devicedata.HumiditySensorData;
import se.hal.struct.devicedata.TemperatureSensorData;
/**
* A device configuration for a specific endpoint on a Zigbee device.
@ -17,8 +17,8 @@ public class ZigbeeHumidityConfig extends ZigbeeHalDeviceConfig implements HalSe
// --------------------------
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclRelativeHumidityMeasurementCluster.ATTR_MEASUREDVALUE)
return new HumiditySensorData(
((int) zclAttribute.getLastValue()) / 100.0,

View file

@ -1,5 +1,6 @@
package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.clusters.ZclIlluminanceMeasurementCluster;
import se.hal.intf.HalDeviceData;
@ -16,8 +17,8 @@ public class ZigbeeIlluminanceConfig extends ZigbeeHalDeviceConfig implements Ha
// --------------------------
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclIlluminanceMeasurementCluster.ATTR_MEASUREDVALUE)
return new IlluminanceSensorData(
(int) zclAttribute.getLastValue(),

View file

@ -0,0 +1,73 @@
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;
import com.zsmartsystems.zigbee.zcl.clusters.ZclLevelControlCluster;
import com.zsmartsystems.zigbee.zcl.clusters.levelcontrol.MoveToLevelCommand;
import se.hal.intf.HalDeviceData;
import se.hal.intf.HalEventConfig;
import se.hal.intf.HalEventData;
import se.hal.struct.devicedata.LevelEventData;
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 ZigbeeLevelConfig extends ZigbeeHalEventDeviceConfig implements HalEventConfig {
private static final Logger logger = LogUtil.getLogger();
// --------------------------
// Zigbee Methods
// --------------------------
@Override
public void initialize(ZclCluster cluster) {
if (! (cluster instanceof ZclLevelControlCluster))
return;
try {
ZclAttribute attribute = cluster.getAttribute(ZclLevelControlCluster.ATTR_CURRENTLEVEL);
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(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclLevelControlCluster.ATTR_CURRENTLEVEL)
return new LevelEventData(
(Integer) zclAttribute.getLastValue(),
zclAttribute.getLastReportTime().getTimeInMillis());
return null;
}
@Override
public int getZigbeeClusterId() {
return ZclLevelControlCluster.CLUSTER_ID;
}
@Override
protected ZclCommand getZigbeeCommandObject(HalEventData data) {
if (! (data instanceof LevelEventData))
return null;
return new MoveToLevelCommand((int) (data.getData() * 255), 1);
}
// --------------------------
// Hal Methods
// --------------------------
@Override
public Class<? extends HalDeviceData> getDeviceDataClass() {
return LevelEventData.class;
}
}

View file

@ -1,5 +1,6 @@
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.clusters.ZclOccupancySensingCluster;
@ -37,8 +38,8 @@ public class ZigbeeOccupancyConfig extends ZigbeeHalEventDeviceConfig implements
}
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclOccupancySensingCluster.ATTR_OCCUPANCY)
return new OccupancyEventData(
(boolean) zclAttribute.getLastValue(),

View file

@ -1,5 +1,6 @@
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;
@ -40,8 +41,8 @@ public class ZigbeeOnOffConfig extends ZigbeeHalEventDeviceConfig implements Hal
}
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclOnOffCluster.ATTR_ONOFF)
return new OnOffEventData(
(boolean) zclAttribute.getLastValue(),

View file

@ -1,5 +1,6 @@
package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
import se.hal.intf.HalDeviceData;
@ -16,8 +17,8 @@ public class ZigbeePressureConfig extends ZigbeeHalDeviceConfig implements HalSe
// --------------------------
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
return new PressureSensorData(
(int) zclAttribute.getLastValue(),

View file

@ -1,5 +1,6 @@
package se.hal.plugin.zigbee.device;
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
import se.hal.intf.HalDeviceData;
@ -17,8 +18,8 @@ public class ZigbeeTemperatureConfig extends ZigbeeHalDeviceConfig implements Ha
// --------------------------
@Override
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
return new TemperatureSensorData(
((int) zclAttribute.getLastValue()) / 100.0,

View file

@ -62,6 +62,11 @@ public class ZigbeeNetworkPage extends HalWebPage {
}
switch (request.get("action")) {
case "node_remove":
if (node != null)
controller.unPairNode(node);
break;
case "refresh":
if (attribute != null)
attribute.readValue(0);

View file

@ -5,9 +5,11 @@
"interfaces": [
{"se.hal.intf.HalDatabaseUpgrader": "se.hal.plugin.zigbee.db.ZigbeeHalDatabaseUpgrader"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeColorConfig"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOnOffConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeHumidityConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeIlluminanceConfig"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeLevelConfig"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOccupancyConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeePressureConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeTemperatureConfig"},