From ac176d7a6716069c92d630f84496ecdab3f09d10 Mon Sep 17 00:00:00 2001 From: Chris Jackson Date: Sun, 11 Feb 2018 19:55:11 +0000 Subject: [PATCH] Add humidity and pressure converters (#149) Signed-off-by: Chris Jackson --- ESH-INF/thing/_channels.xml | 10 ++ .../zigbee/ZigBeeBindingConstants.java | 2 +- .../ZigBeeChannelConverterFactory.java | 4 +- .../ZigBeeConverterAtmosphericPressure.java | 127 ++++++++++++++++++ .../ZigBeeConverterColorTemperature.java | 11 +- .../ZigBeeConverterRelativeHumidity.java | 85 ++++++++++++ 6 files changed, 232 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterAtmosphericPressure.java create mode 100644 src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterRelativeHumidity.java diff --git a/ESH-INF/thing/_channels.xml b/ESH-INF/thing/_channels.xml index ed9c206b4..bbaeeca46 100644 --- a/ESH-INF/thing/_channels.xml +++ b/ESH-INF/thing/_channels.xml @@ -91,6 +91,16 @@ + + + + Number + + Indicates the current pressure + Pressure + + + diff --git a/src/main/java/org/openhab/binding/zigbee/ZigBeeBindingConstants.java b/src/main/java/org/openhab/binding/zigbee/ZigBeeBindingConstants.java index 335fabfc1..b805690f8 100644 --- a/src/main/java/org/openhab/binding/zigbee/ZigBeeBindingConstants.java +++ b/src/main/java/org/openhab/binding/zigbee/ZigBeeBindingConstants.java @@ -53,6 +53,7 @@ public class ZigBeeBindingConstants { public static final String CHANNEL_ILLUMINANCE_VALUE = "zigbee:measurement_illuminance"; public static final String CHANNEL_TEMPERATURE_VALUE = "zigbee:measurement_temperature"; public static final String CHANNEL_HUMIDITY_VALUE = "zigbee:measurement_relativehumidity"; + public static final String CHANNEL_PRESSURE_VALUE = "zigbee:measurement_pressure"; public static final String CHANNEL_OCCUPANCY_SENSOR = "zigbee:sensor_occupancy"; @@ -86,7 +87,6 @@ public class ZigBeeBindingConstants { public static final String THING_PROPERTY_ROUTES = "zigbee_routes"; public static final String THING_PROPERTY_NEIGHBORS = "zigbee_neighbors"; public static final String THING_PROPERTY_LASTUPDATE = "zigbee_lastupdate"; - public static final String THING_PROPERTY_PERMITJOINING = "zigbee_permitjoining"; public static final String THING_PROPERTY_ASSOCIATEDDEVICES = "zigbee_devices"; // List of all configuration parameters diff --git a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeChannelConverterFactory.java b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeChannelConverterFactory.java index 6092ee3ae..fab4b32ca 100644 --- a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeChannelConverterFactory.java +++ b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeChannelConverterFactory.java @@ -57,6 +57,7 @@ public ZigBeeChannelConverterFactory() { channelMap.put(ZigBeeBindingConstants.CHANNEL_COLOR_COLOR, ZigBeeConverterColorColor.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_COLOR_TEMPERATURE, ZigBeeConverterColorTemperature.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_ELECTRICAL_ACTIVEPOWER, ZigBeeConverterMeasurementPower.class); + channelMap.put(ZigBeeBindingConstants.CHANNEL_HUMIDITY_VALUE, ZigBeeConverterRelativeHumidity.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_IAS_CONTACT_PORTAL1, ZigBeeConverterIasContactPortal1.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_IAS_MOTION_INTRUSION, ZigBeeConverterIasMotionIntrusion.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_IAS_MOTION_PRESENCE, ZigBeeConverterIasMotionPresence.class); @@ -64,6 +65,7 @@ public ZigBeeChannelConverterFactory() { channelMap.put(ZigBeeBindingConstants.CHANNEL_ILLUMINANCE_VALUE, ZigBeeConverterIlluminance.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_OCCUPANCY_SENSOR, ZigBeeConverterOccupancy.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_POWER_BATTERYPERCENT, ZigBeeConverterBatteryPercent.class); + channelMap.put(ZigBeeBindingConstants.CHANNEL_PRESSURE_VALUE, ZigBeeConverterAtmosphericPressure.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_SWITCH_ONOFF, ZigBeeConverterSwitchOnoff.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_SWITCH_LEVEL, ZigBeeConverterSwitchLevel.class); channelMap.put(ZigBeeBindingConstants.CHANNEL_TEMPERATURE_VALUE, ZigBeeConverterTemperature.class); @@ -111,7 +113,7 @@ public Collection getChannels(ThingUID thingUID, ZigBeeEndpoint endpoin // Perform a channel consolidation at endpoint level to remove unnecessary channels. // This removes channels that are covered through inheritance. - for (Map.Entry consolidationChannel : channelConsolidation.entrySet()) { + for (Map.Entry consolidationChannel : channelConsolidation.entrySet()) { if (channels.containsKey(consolidationChannel.getKey()) && channels.containsKey(consolidationChannel.getValue())) { logger.debug("{}: Removing channel {} in favor of {}", endpoint.getIeeeAddress(), diff --git a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterAtmosphericPressure.java b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterAtmosphericPressure.java new file mode 100644 index 000000000..6e5427d13 --- /dev/null +++ b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterAtmosphericPressure.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2014-2017 by the respective copyright holders. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zigbee.internal.converter; + +import java.math.BigDecimal; + +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.zigbee.ZigBeeBindingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.zsmartsystems.zigbee.ZigBeeEndpoint; +import com.zsmartsystems.zigbee.zcl.ZclAttribute; +import com.zsmartsystems.zigbee.zcl.ZclAttributeListener; +import com.zsmartsystems.zigbee.zcl.clusters.ZclPressureMeasurementCluster; +import com.zsmartsystems.zigbee.zcl.protocol.ZclClusterType; + +/** + * Converter for the atmospheric pressure channel. + * This channel will attempt to detect if the device is supporting the enhanced (scaled) value reports and use them if + * they are available. + * + * @author Chris Jackson - Initial Contribution + * + */ +public class ZigBeeConverterAtmosphericPressure extends ZigBeeBaseChannelConverter implements ZclAttributeListener { + private Logger logger = LoggerFactory.getLogger(ZigBeeConverterAtmosphericPressure.class); + + private ZclPressureMeasurementCluster cluster; + + /** + * If enhancedScale is null, then the binding will use the MeasuredValue report, + * otherwise it will use the ScaledValue report + */ + private Integer enhancedScale = null; + + @Override + public boolean initializeConverter() { + cluster = (ZclPressureMeasurementCluster) endpoint.getInputCluster(ZclPressureMeasurementCluster.CLUSTER_ID); + if (cluster == null) { + logger.error("{}: Error opening device pressure measurement cluster", endpoint.getIeeeAddress()); + return false; + } + + // Check if the enhanced attributes are supported + if (cluster.getScaledValue(Long.MAX_VALUE) != null) { + enhancedScale = cluster.getScale(Long.MAX_VALUE); + if (enhancedScale != null) { + enhancedScale *= -1; + } + } + + cluster.bind(); + + // Add a listener, then request the status + cluster.addAttributeListener(this); + + // Configure reporting - no faster than once per second - no slower than 10 minutes. + if (enhancedScale != null) { + cluster.setScaledValueReporting(1, REPORTING_PERIOD_DEFAULT_MAX, 0.1); + } else { + cluster.setMeasuredValueReporting(1, REPORTING_PERIOD_DEFAULT_MAX, 0.1); + } + return true; + } + + @Override + public void disposeConverter() { + cluster.removeAttributeListener(this); + } + + @Override + public void handleRefresh() { + if (enhancedScale != null) { + cluster.getScaledValue(0); + } else { + cluster.getMeasuredValue(0); + } + } + + @Override + public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { + if (endpoint.getInputCluster(ZclPressureMeasurementCluster.CLUSTER_ID) == null) { + return null; + } + return createChannel(thingUID, endpoint, ZigBeeBindingConstants.CHANNEL_PRESSURE_VALUE, + ZigBeeBindingConstants.ITEM_TYPE_NUMBER, "Atmospheric Pressure"); + } + + @Override + public void attributeUpdated(ZclAttribute attribute) { + logger.debug("{}: ZigBee attribute reports {}", endpoint.getIeeeAddress(), attribute); + if (attribute.getCluster() == ZclClusterType.PRESSURE_MEASUREMENT) { + // Handle automatic reporting of the enhanced attribute configuration + if (attribute.getId() == ZclPressureMeasurementCluster.ATTR_SCALE) { + enhancedScale = (Integer) attribute.getLastValue(); + if (enhancedScale != null) { + enhancedScale *= -1; + } + return; + } + + if (attribute.getId() == ZclPressureMeasurementCluster.ATTR_SCALEDVALUE && enhancedScale != null) { + Integer value = (Integer) attribute.getLastValue(); + if (value != null) { + updateChannelState(new DecimalType(BigDecimal.valueOf(value, enhancedScale))); + } + return; + } + + if (attribute.getId() == ZclPressureMeasurementCluster.ATTR_MEASUREDVALUE && enhancedScale == null) { + Integer value = (Integer) attribute.getLastValue(); + if (value != null) { + updateChannelState(new DecimalType(BigDecimal.valueOf(value, 0))); + } + return; + } + } + } +} diff --git a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorTemperature.java b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorTemperature.java index ad6adf020..72385a404 100644 --- a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorTemperature.java +++ b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorTemperature.java @@ -52,8 +52,8 @@ public boolean initializeConverter() { return false; } - Integer kMin = clusterColorControl.getColorTemperatureMin(Integer.MAX_VALUE); - Integer kMax = clusterColorControl.getColorTemperatureMax(Integer.MAX_VALUE); + Integer kMin = clusterColorControl.getColorTemperatureMin(Long.MAX_VALUE); + Integer kMax = clusterColorControl.getColorTemperatureMax(Long.MAX_VALUE); if (kMin == null) { kelvinMin = CT_DEFAULT_MIN; @@ -118,7 +118,8 @@ public void handleCommand(final Command command) { @Override public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { - clusterColorControl = (ZclColorControlCluster) endpoint.getInputCluster(ZclColorControlCluster.CLUSTER_ID); + ZclColorControlCluster clusterColorControl = (ZclColorControlCluster) endpoint + .getInputCluster(ZclColorControlCluster.CLUSTER_ID); if (clusterColorControl == null) { return null; } @@ -126,7 +127,7 @@ public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { try { if (!clusterColorControl.discoverAttributes(false).get()) { // Device is not supporting attribute reporting - instead, just read the attributes - Integer capabilities = clusterColorControl.getColorCapabilities(Integer.MAX_VALUE); + Integer capabilities = clusterColorControl.getColorCapabilities(Long.MAX_VALUE); if (capabilities != null && (capabilities & ColorCapabilitiesEnum.COLOR_TEMPERATURE.getKey()) == 0) { // No support for color temperature return null; @@ -136,7 +137,7 @@ public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { } } else if (clusterColorControl.isAttributeSupported(ZclColorControlCluster.ATTR_COLORCAPABILITIES)) { // If the device is reporting is capabilities, then use this over attribute detection - Integer capabilities = clusterColorControl.getColorCapabilities(Integer.MAX_VALUE); + Integer capabilities = clusterColorControl.getColorCapabilities(Long.MAX_VALUE); if (capabilities != null && (capabilities & ColorCapabilitiesEnum.COLOR_TEMPERATURE.getKey()) == 0) { // No support for color temperature return null; diff --git a/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterRelativeHumidity.java b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterRelativeHumidity.java new file mode 100644 index 000000000..a4014dae8 --- /dev/null +++ b/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterRelativeHumidity.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2014-2017 by the respective copyright holders. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zigbee.internal.converter; + +import java.math.BigDecimal; + +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.zigbee.ZigBeeBindingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.zsmartsystems.zigbee.ZigBeeEndpoint; +import com.zsmartsystems.zigbee.zcl.ZclAttribute; +import com.zsmartsystems.zigbee.zcl.ZclAttributeListener; +import com.zsmartsystems.zigbee.zcl.clusters.ZclRelativeHumidityMeasurementCluster; +import com.zsmartsystems.zigbee.zcl.protocol.ZclClusterType; + +/** + * Converter for the relative humidity channel + * + * @author Chris Jackson - Initial Contribution + * + */ +public class ZigBeeConverterRelativeHumidity extends ZigBeeBaseChannelConverter implements ZclAttributeListener { + private Logger logger = LoggerFactory.getLogger(ZigBeeConverterRelativeHumidity.class); + + private ZclRelativeHumidityMeasurementCluster cluster; + + @Override + public boolean initializeConverter() { + cluster = (ZclRelativeHumidityMeasurementCluster) endpoint + .getInputCluster(ZclRelativeHumidityMeasurementCluster.CLUSTER_ID); + if (cluster == null) { + logger.error("{}: Error opening device relative humidity measurement cluster", endpoint.getIeeeAddress()); + return false; + } + + cluster.bind(); + + // Add a listener, then request the status + cluster.addAttributeListener(this); + + // Configure reporting - no faster than once per second - no slower than 10 minutes. + cluster.setMeasuredValueReporting(1, REPORTING_PERIOD_DEFAULT_MAX, 0.1); + return true; + } + + @Override + public void disposeConverter() { + cluster.removeAttributeListener(this); + } + + @Override + public void handleRefresh() { + cluster.getMeasuredValue(0); + } + + @Override + public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { + if (endpoint.getInputCluster(ZclRelativeHumidityMeasurementCluster.CLUSTER_ID) == null) { + return null; + } + return createChannel(thingUID, endpoint, ZigBeeBindingConstants.CHANNEL_HUMIDITY_VALUE, + ZigBeeBindingConstants.ITEM_TYPE_NUMBER, "Relative Humidity"); + } + + @Override + public void attributeUpdated(ZclAttribute attribute) { + logger.debug("{}: ZigBee attribute reports {}", endpoint.getIeeeAddress(), attribute); + if (attribute.getCluster() == ZclClusterType.RELATIVE_HUMIDITY_MEASUREMENT + && attribute.getId() == ZclRelativeHumidityMeasurementCluster.ATTR_MEASUREDVALUE) { + Integer value = (Integer) attribute.getLastValue(); + if (value != null) { + updateChannelState(new DecimalType(BigDecimal.valueOf(value, 2))); + } + } + } +}