Skip to content

Commit

Permalink
Add configuration handler for OnOffSwitch
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Jackson <[email protected]>
  • Loading branch information
cdjackson committed Oct 6, 2019
1 parent f802171 commit 94c11c4
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
package org.openhab.binding.zigbee.internal.converter;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.thing.Channel;
Expand All @@ -28,6 +31,7 @@
import org.eclipse.smarthome.core.types.Command;
import org.openhab.binding.zigbee.ZigBeeBindingConstants;
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
import org.openhab.binding.zigbee.internal.converter.config.ZclOnOffSwitchConfig;
import org.openhab.binding.zigbee.internal.converter.config.ZclReportingConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -64,6 +68,7 @@ public class ZigBeeConverterSwitchOnoff extends ZigBeeBaseChannelConverter
private ZclAttribute attributeClient;
private ZclAttribute attributeServer;

private ZclOnOffSwitchConfig configOnOff;
private ZclReportingConfig configReporting;

private final AtomicBoolean currentOnOffState = new AtomicBoolean(true);
Expand Down Expand Up @@ -127,6 +132,13 @@ public boolean initializeConverter() {
return false;
}

if (clusterOnOffServer != null) {
// Add the listener
clusterOnOffServer.addAttributeListener(this);
configOnOff = new ZclOnOffSwitchConfig();
configOnOff.initialize(clusterOnOffServer);
}

if (clusterOnOffClient != null) {
// Add the command listener
clusterOnOffClient.addCommandListener(this);
Expand All @@ -142,6 +154,7 @@ public boolean initializeConverter() {
configReporting = new ZclReportingConfig(channel);

configOptions = new ArrayList<>();
configOptions.addAll(configOnOff.getConfiguration());
configOptions.addAll(configReporting.getConfiguration());

return true;
Expand Down Expand Up @@ -226,6 +239,28 @@ public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) {
.build();
}

@Override
public void updateConfiguration(@NonNull Configuration currentConfiguration,
Map<String, Object> updatedParameters) {
if (configReporting.updateConfiguration(currentConfiguration, updatedParameters)) {
try {
ZclAttribute attribute;
CommandResult reportingResponse;

attribute = clusterOnOffServer.getAttribute(ZclOnOffCluster.ATTR_ONOFF);
reportingResponse = attribute
.setReporting(configReporting.getReportingTimeMin(), configReporting.getReportingTimeMax())
.get();
handleReportingResponse(reportingResponse, configReporting.getPollingPeriod(),
configReporting.getReportingTimeMax());
} catch (InterruptedException | ExecutionException e) {
logger.debug("{}: OnOff exception setting reporting", endpoint.getIeeeAddress(), e);
}
}

configOnOff.updateConfiguration(currentConfiguration, updatedParameters);
}

@Override
public void attributeUpdated(ZclAttribute attribute, Object val) {
logger.debug("{}: ZigBee attribute reports {}", endpoint.getIeeeAddress(), attribute);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* Copyright (c) 2010-2018 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.config;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.config.core.ParameterOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zsmartsystems.zigbee.zcl.ZclAttribute;
import com.zsmartsystems.zigbee.zcl.ZclCluster;
import com.zsmartsystems.zigbee.zcl.clusters.ZclOnOffCluster;

/**
* Configuration handler for the {@link ZclOnOffSwitchCluster}
*
* @author Chris Jackson
*
*/
public class ZclOnOffSwitchConfig implements ZclClusterConfigHandler {
private Logger logger = LoggerFactory.getLogger(ZclOnOffSwitchConfig.class);

private static final String CONFIG_ID = "zigbee_onoff_";
private static final String CONFIG_OFFWAITTIME = CONFIG_ID + "offwaittime";
private static final String CONFIG_ONTIME = CONFIG_ID + "ontime";
private static final String CONFIG_STARTUPONOFF = CONFIG_ID + "startuponoff";

private ZclOnOffCluster onoffCluster;

private final List<ConfigDescriptionParameter> parameters = new ArrayList<>();

@Override
public boolean initialize(ZclCluster cluster) {
onoffCluster = (ZclOnOffCluster) cluster;
try {
Boolean result = onoffCluster.discoverAttributes(false).get();
if (!result) {
logger.debug("{}: Unable to get supported attributes for {}.", onoffCluster.getZigBeeAddress(),
onoffCluster.getClusterName());
}
} catch (InterruptedException | ExecutionException e) {
logger.error("{}: Error getting supported attributes for {}. ", onoffCluster.getZigBeeAddress(),
onoffCluster.getClusterName(), e);
}

// Build a list of configuration supported by this channel based on the attributes the cluster supports
List<ParameterOption> options = new ArrayList<>();

if (onoffCluster.isAttributeSupported(ZclOnOffCluster.ATTR_OFFWAITTIME)) {
parameters.add(ConfigDescriptionParameterBuilder.create(CONFIG_OFFWAITTIME, Type.INTEGER)
.withLabel("Off Wait Time")
.withDescription("Time in 100ms steps to ignore ON commands after an OFF command").withDefault("0")
.withMinimum(new BigDecimal(0)).withMaximum(new BigDecimal(60000)).build());
}
if (onoffCluster.isAttributeSupported(ZclOnOffCluster.ATTR_ONTIME)) {
parameters.add(ConfigDescriptionParameterBuilder.create(CONFIG_ONTIME, Type.INTEGER)
.withLabel("Auto OFF Time")
.withDescription("Time in 100ms steps to automatically turn off when sent with timed command")
.withDefault("65535").withMinimum(new BigDecimal(0)).withMaximum(new BigDecimal(60000)).build());
}
if (onoffCluster.isAttributeSupported(ZclOnOffCluster.ATTR_STARTUPONOFF)) {
options = new ArrayList<ParameterOption>();
options.add(new ParameterOption("0", "OFF"));
options.add(new ParameterOption("1", "ON"));
parameters.add(ConfigDescriptionParameterBuilder.create(CONFIG_STARTUPONOFF, Type.INTEGER)
.withLabel("Power on state").withDescription("The state to set after powering on").withDefault("0")
.withMinimum(new BigDecimal(0)).withMaximum(new BigDecimal(1)).withOptions(options)
.withLimitToOptions(true).build());
}

return !parameters.isEmpty();
}

@Override
public List<ConfigDescriptionParameter> getConfiguration() {
return parameters;
}

@Override
public boolean updateConfiguration(@NonNull Configuration currentConfiguration,
Map<String, Object> configurationParameters) {

boolean updated = false;
for (Entry<String, Object> configurationParameter : configurationParameters.entrySet()) {
if (!configurationParameter.getKey().startsWith(CONFIG_ID)) {
continue;
}
// Ignore any configuration parameters that have not changed
if (Objects.equals(configurationParameter.getValue(),
currentConfiguration.get(configurationParameter.getKey()))) {
logger.debug("Configuration update: Ignored {} as no change", configurationParameter.getKey());
continue;
}

logger.debug("{}: Update LevelControl configuration property {}->{} ({})", onoffCluster.getZigBeeAddress(),
configurationParameter.getKey(), configurationParameter.getValue(),
configurationParameter.getValue().getClass().getSimpleName());
Integer response = null;
switch (configurationParameter.getKey()) {
case CONFIG_OFFWAITTIME:
response = configureAttribute(ZclOnOffCluster.ATTR_OFFWAITTIME, configurationParameter.getValue());
break;
case CONFIG_ONTIME:
response = configureAttribute(ZclOnOffCluster.ATTR_ONTIME, configurationParameter.getValue());
break;
case CONFIG_STARTUPONOFF:
response = configureAttribute(ZclOnOffCluster.ATTR_STARTUPONOFF, configurationParameter.getValue());
break;
default:
logger.warn("{}: Unhandled configuration property {}", onoffCluster.getZigBeeAddress(),
configurationParameter.getKey());
break;
}

if (response != null) {
currentConfiguration.put(configurationParameter.getKey(), BigInteger.valueOf(response));
updated = true;
}
}

return updated;
}

private Integer configureAttribute(int attributeId, Object value) {
ZclAttribute attribute = onoffCluster.getAttribute(attributeId);
attribute.writeValue(((BigDecimal) (value)).intValue());
return (Integer) attribute.readValue(0);
}
}

0 comments on commit 94c11c4

Please sign in to comment.