-
-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Chris Jackson <chris@cd-jackson.com> (+4 squashed commits) Squashed commits: [8c397c9] Add tests for ZigBeeConverterTuyaButton Signed-off-by: Daniel Schall <github.com@mon-clan.de> [d68a96a] Fix build break Signed-off-by: Daniel Schall <github.com@mon-clan.de> [9a37f0e] Add Tuya button support Signed-off-by: Daniel Schall <github.com@mon-clan.de> [af45e77] Create Tuya specific handler binding Signed-off-by: Chris Jackson <chris@cd-jackson.com>
- Loading branch information
Showing
18 changed files
with
967 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/bin/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
This content is produced and maintained by the openHAB project. | ||
|
||
* Project home: https://www.openhab.org | ||
|
||
== Declared Project Licenses | ||
|
||
This program and the accompanying materials are made available under the terms | ||
of the Eclipse Public License 2.0 which is available at | ||
https://www.eclipse.org/legal/epl-2.0/. | ||
|
||
== Source Code | ||
|
||
https://github.com/openhab/org.openhab.binding.zigbee | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
|
||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.openhab.addons.bundles</groupId> | ||
<artifactId>org.openhab.addons.zigbee.reactor</artifactId> | ||
<version>3.2.0-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>org.openhab.binding.zigbee.tuya</artifactId> | ||
|
||
<name>openHAB Add-ons :: Bundles :: ZigBee Tuya Handler</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.openhab.addons.bundles</groupId> | ||
<artifactId>org.openhab.binding.zigbee</artifactId> | ||
<version>${project.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
33 changes: 33 additions & 0 deletions
33
...nding.zigbee.tuya/src/main/java/org/openhab/binding/zigbee/tuya/TuyaBindingConstants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* Copyright (c) 2010-2021 Contributors to the openHAB project | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.openhab.binding.zigbee.tuya; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.openhab.core.thing.type.ChannelTypeUID; | ||
|
||
/** | ||
* The {@link TuyaBindingConstants} class defines common constants, which are | ||
* used across the whole binding. | ||
* | ||
* @author Chris Jackson - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
public class TuyaBindingConstants { | ||
|
||
public static final String BINDING_ID = "zigbee"; | ||
|
||
public static final String CHANNEL_NAME_TUYA_BUTTON = "tuyabutton"; | ||
public static final String CHANNEL_LABEL_TUYA_BUTTON = "Button"; | ||
public static final ChannelTypeUID CHANNEL_TUYA_BUTTON = new ChannelTypeUID("zigbee:tuya_button"); | ||
|
||
} |
216 changes: 216 additions & 0 deletions
216
...ya/src/main/java/org/openhab/binding/zigbee/tuya/converter/ZigBeeConverterTuyaButton.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/** | ||
* Copyright (c) 2010-2021 Contributors to the openHAB project | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.openhab.binding.zigbee.tuya.converter; | ||
|
||
import static java.lang.Integer.*; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Set; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
import org.openhab.core.thing.Channel; | ||
import org.openhab.core.thing.CommonTriggerEvents; | ||
import org.openhab.core.thing.ThingUID; | ||
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter; | ||
import org.openhab.binding.zigbee.handler.ZigBeeThingHandler; | ||
import org.openhab.binding.zigbee.internal.converter.config.ZclReportingConfig; | ||
import org.openhab.binding.zigbee.tuya.internal.TuyaButtonPressCommand; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.zsmartsystems.zigbee.CommandResult; | ||
import com.zsmartsystems.zigbee.ZigBeeEndpoint; | ||
import com.zsmartsystems.zigbee.zcl.ZclAttribute; | ||
import com.zsmartsystems.zigbee.zcl.ZclAttributeListener; | ||
import com.zsmartsystems.zigbee.zcl.ZclCluster; | ||
import com.zsmartsystems.zigbee.zcl.ZclCommand; | ||
import com.zsmartsystems.zigbee.zcl.ZclCommandListener; | ||
import com.zsmartsystems.zigbee.zcl.ZclStatus; | ||
import com.zsmartsystems.zigbee.zcl.clusters.ZclOnOffCluster; | ||
|
||
/** | ||
* Generic converter for Tuya buttons (e.g., Zemismart). | ||
* <p> | ||
* This converter is handling the Tuya-specific command (ID: 253) and emits button-pressed events. | ||
* <p> | ||
* As the configuration is done via channel properties, this converter is usable via static thing types only. | ||
* | ||
* @author Daniel Schall - initial contribution | ||
*/ | ||
public class ZigBeeConverterTuyaButton extends ZigBeeBaseChannelConverter | ||
implements ZclAttributeListener, ZclCommandListener { | ||
|
||
private Logger logger = LoggerFactory.getLogger(ZigBeeConverterTuyaButton.class); | ||
|
||
private ZclCluster clientCluster = null; | ||
private ZclCluster serverCluster = null; | ||
|
||
// Tuya devices sometimes send duplicate commands with the same tx id. | ||
// We keep track of the last received Tx id and ignore the duplicate. | ||
private Integer lastTxId = -1; | ||
|
||
@Override | ||
public Set<Integer> getImplementedClientClusters() { | ||
return Collections.singleton(ZclOnOffCluster.CLUSTER_ID); | ||
} | ||
|
||
@Override | ||
public Set<Integer> getImplementedServerClusters() { | ||
return Collections.singleton(ZclOnOffCluster.CLUSTER_ID); | ||
} | ||
|
||
@Override | ||
public boolean initializeDevice() { | ||
ZclCluster clientCluster = endpoint.getOutputCluster(ZclOnOffCluster.CLUSTER_ID); | ||
ZclCluster serverCluster = endpoint.getInputCluster(ZclOnOffCluster.CLUSTER_ID); | ||
|
||
if (clientCluster == null) { | ||
logger.error("{}: Error opening client cluster {} on endpoint {}", endpoint.getIeeeAddress(), | ||
ZclOnOffCluster.CLUSTER_ID, endpoint.getEndpointId()); | ||
return false; | ||
} | ||
|
||
if (serverCluster == null) { | ||
logger.error("{}: Error opening server cluster {} on endpoint {}", endpoint.getIeeeAddress(), | ||
ZclOnOffCluster.CLUSTER_ID, endpoint.getEndpointId()); | ||
return false; | ||
} | ||
|
||
ZclReportingConfig reporting = new ZclReportingConfig(channel); | ||
|
||
try { | ||
CommandResult bindResponse = bind(serverCluster).get(); | ||
if (bindResponse.isSuccess()) { | ||
// Configure reporting | ||
ZclAttribute attribute = serverCluster.getAttribute(ZclOnOffCluster.ATTR_ONOFF); | ||
CommandResult reportingResponse = attribute | ||
.setReporting(reporting.getReportingTimeMin(), reporting.getReportingTimeMax()).get(); | ||
handleReportingResponse(reportingResponse, POLLING_PERIOD_HIGH, reporting.getPollingPeriod()); | ||
} else { | ||
logger.debug("{}: Error 0x{} setting server binding", endpoint.getIeeeAddress(), | ||
Integer.toHexString(bindResponse.getStatusCode())); | ||
pollingPeriod = POLLING_PERIOD_HIGH; | ||
} | ||
|
||
} catch (InterruptedException | ExecutionException e) { | ||
logger.error("{}: Exception setting reporting ", endpoint.getIeeeAddress(), e); | ||
} | ||
|
||
try { | ||
CommandResult bindResponse = bind(clientCluster).get(); | ||
if (!bindResponse.isSuccess()) { | ||
logger.error("{}: Error 0x{} setting client binding for cluster {}", endpoint.getIeeeAddress(), | ||
toHexString(bindResponse.getStatusCode()), ZclOnOffCluster.CLUSTER_ID); | ||
} | ||
} catch (InterruptedException | ExecutionException e) { | ||
logger.error("{}: Exception setting client binding to cluster {}: {}", endpoint.getIeeeAddress(), | ||
ZclOnOffCluster.CLUSTER_ID, e); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public synchronized boolean initializeConverter(ZigBeeThingHandler thing) { | ||
super.initializeConverter(thing); | ||
|
||
clientCluster = endpoint.getOutputCluster(ZclOnOffCluster.CLUSTER_ID); | ||
serverCluster = endpoint.getInputCluster(ZclOnOffCluster.CLUSTER_ID); | ||
|
||
if (clientCluster == null) { | ||
logger.error("{}: Error opening device client controls", endpoint.getIeeeAddress()); | ||
return false; | ||
} | ||
|
||
if (serverCluster == null) { | ||
logger.error("{}: Error opening device server controls", endpoint.getIeeeAddress()); | ||
return false; | ||
} | ||
|
||
clientCluster.addCommandListener(this); | ||
serverCluster.addAttributeListener(this); | ||
|
||
// Add Tuya-specific command | ||
// | ||
HashMap<Integer, Class<? extends ZclCommand>> commandMap = new HashMap<>(); | ||
commandMap.put(TuyaButtonPressCommand.COMMAND_ID, TuyaButtonPressCommand.class); | ||
clientCluster.addClientCommands(commandMap); | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public void disposeConverter() { | ||
if(clientCluster != null) { | ||
clientCluster.removeCommandListener(this); | ||
} | ||
if (serverCluster != null) { | ||
serverCluster.removeAttributeListener(this); | ||
} | ||
} | ||
|
||
@Override | ||
public void handleRefresh() { | ||
// nothing to do, as we only listen to commands | ||
} | ||
|
||
@Override | ||
public Channel getChannel(ThingUID thingUID, ZigBeeEndpoint endpoint) { | ||
// This converter is used only for channels specified in static thing types, and cannot be used to construct | ||
// channels based on an endpoint alone. | ||
return null; | ||
} | ||
|
||
@Override | ||
public boolean commandReceived(ZclCommand command) { | ||
logger.debug("{} received command {}", endpoint.getIeeeAddress(), command); | ||
Integer thisTxId = command.getTransactionId(); | ||
if(lastTxId == thisTxId) | ||
{ | ||
logger.debug("{} ignoring duplicate command {}", endpoint.getIeeeAddress(), thisTxId); | ||
} | ||
else if (command instanceof TuyaButtonPressCommand) { | ||
TuyaButtonPressCommand tuyaButtonPressCommand = (TuyaButtonPressCommand) command; | ||
thing.triggerChannel(channel.getUID(), getEventType(tuyaButtonPressCommand.getPressType())); | ||
clientCluster.sendDefaultResponse(command, ZclStatus.SUCCESS); | ||
} | ||
else { | ||
logger.warn("{} received unknown command {}", endpoint.getIeeeAddress(), command); | ||
} | ||
|
||
lastTxId = thisTxId; | ||
return true; | ||
} | ||
|
||
@Override | ||
public void attributeUpdated(ZclAttribute attribute, Object val) { | ||
logger.debug("{}: ZigBee attribute reports {}", endpoint.getIeeeAddress(), attribute); | ||
} | ||
|
||
private String getEventType(Integer pressType) | ||
{ | ||
switch(pressType) | ||
{ | ||
case 0: | ||
return CommonTriggerEvents.SHORT_PRESSED; | ||
case 1: | ||
return CommonTriggerEvents.DOUBLE_PRESSED; | ||
case 2: | ||
return CommonTriggerEvents.LONG_PRESSED; | ||
default: | ||
logger.warn("{} received unknown pressType {}", endpoint.getIeeeAddress(), pressType); | ||
return CommonTriggerEvents.SHORT_PRESSED; | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...in/java/org/openhab/binding/zigbee/tuya/converter/ZigBeeTuyaChannelConverterProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Copyright (c) 2010-2021 Contributors to the openHAB project | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.openhab.binding.zigbee.tuya.converter; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.openhab.binding.zigbee.ZigBeeBindingConstants; | ||
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter; | ||
import org.openhab.binding.zigbee.converter.ZigBeeChannelConverterFactory; | ||
import org.openhab.binding.zigbee.converter.ZigBeeChannelConverterProvider; | ||
import org.openhab.core.thing.type.ChannelTypeUID; | ||
import org.osgi.service.component.annotations.Component; | ||
|
||
/** | ||
* The base {@link ZigBeeTuyaChannelConverterProvider} of the binding making the Tuya specific | ||
* {@link ZigBeeBaseChannelConverter}s available for the {@link ZigBeeChannelConverterFactory}. | ||
* | ||
* @author Chris Jackson - Initial contribution | ||
*/ | ||
@Component(immediate = true, service = ZigBeeChannelConverterProvider.class) | ||
public final class ZigBeeTuyaChannelConverterProvider implements ZigBeeChannelConverterProvider { | ||
|
||
private final Map<ChannelTypeUID, Class<? extends ZigBeeBaseChannelConverter>> channelMap = new HashMap<>(); | ||
|
||
public ZigBeeTuyaChannelConverterProvider() { | ||
// Add all the converters into the map... | ||
channelMap.put(ZigBeeBindingConstants.CHANNEL_COLOR_COLOR, ZigBeeConverterTuyaButton.class); | ||
} | ||
|
||
@Override | ||
public Map<ChannelTypeUID, Class<? extends ZigBeeBaseChannelConverter>> getChannelConverters() { | ||
return channelMap; | ||
} | ||
} |
Oops, something went wrong.