Adding support for Tuya ZS3L / TZ3000 / TS0043 / TS0042 / TS0041 to Zigbee Bindings

Hi all,

I am a relatively new user of OpenHab2, but so far, I’ve set up a network of Xiaomi Aqara wall switches (powered), Xiaomi Aqara door and temperature sensors (battery), and a couple of IKEA Tradri repeaters (powered), and 3A NUE LED Controllers (powered).
All connected to an Ember Zigbee coordinator on a Raspi.
This setup works well without issues.

I recently bought battery-powered Zemismart Tuya wireless switches on Aliexpress [1], and I have paired them successfully with OpenHab [5].
Please note these are Zigbee-only devices, not the Wifi buttons that can be coupled with the smart things app (at least I think they are zigbee only, the spec sheet does not mention wifi [4]).

I can’t get the buttons on update their status in OH2, all I get when pressing the buttons are errors that command 253 on channel <device_id>/<button_id> is unknown [2].

The devices report themselves as _TZ3000_<random characters>, TS0043 (the 3 button version), and the chip has “ZS3L” printed on it.
The two button version reports itself as TS0042, and one button likewise as TS0041.

I would like to add support for these switches, and I can certainly help implement.
As a C/C++ software dev who is unfamiliar with the code base, I would appreciate a little help to get started.
After looking through the code base a bit, I am guessing that all it takes is adding support for that ominous command 253 in a custom discovery/thing rule [3], but I am at a loss how to achieve that.

(On a side note, the devices incorrectly report themselves as MAINS powered. Fixing that is not the top priority, but if it can be done, even better.)

Hope this post contains enough data to get started understanding the problem.
I can certainly supply more details.

Thanks,
Daniel

[1] https://www.aliexpress.com/item/4001227549409.html?spm=a2g0s.9042311.0.0.64184c4d22z8k1

[2]

2020-11-24 21:38:14.530 [DEBUG] [zigbee.dongle.ember.ZigBeeDongleEzsp] - RX EZSP: EzspIncomingMessageHandler [networkId=0, type=EMBER_INCOMING_UNICAST, apsFrame=EmberApsFrame [profileId=0104, clusterId=0006, sourceEndpoint=1, destinationEndpoint=1, options=[EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY], groupId=0, sequence=AC], lastHopLqi=208, lastHopRssi=-48, sender=B883, bindingIndex=255, addressIndex=255, messageContents=01 01 FD 00]
2020-11-24 21:38:14.531 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - RX APS: ZigBeeApsFrame [sourceAddress=B883/1, destinationAddress=0000/1, profile=0104, cluster=0006, addressMode=DEVICE, radius=0, apsSecurity=false, ackRequest=false, apsCounter=AC, rssi=-48, lqi=D0, payload=01 01 FD 00]
2020-11-24 21:38:14.531 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - RX ZCL: ZclHeader [frameType=CLUSTER_SPECIFIC_COMMAND, manufacturerSpecific=false, direction=CLIENT_TO_SERVER, disableDefaultResponse=false, manufacturerCode=0, sequenceNumber=1, commandId=253]
2020-11-24 21:38:14.531 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - BC33ACFFFEEF6F95: Unknown command 253
2020-11-24 21:38:14.532 [DEBUG] [e.transaction.ZigBeeTransactionQueue] - BC33ACFFFEEF6F95: Added transaction to queue, len=1, transaction=ZigBeeTransaction [ieeeAddress=BC33ACFFFEEF6F95 queueTime=0, state=WAITING, sendCnt=0, command=DefaultResponse [On/Off: 0000/0 -> B883/1, cluster=0006, TID=01, commandIdentifier=253, statusCode=FAILURE]]
2020-11-24 21:38:14.532 [DEBUG] [transaction.ZigBeeTransactionManager] - Transaction Manager: Send Next transaction. outstandingTransactions=0, outstandingQueues=1, sleepy=0/3
2020-11-24 21:38:14.533 [DEBUG] [transaction.ZigBeeTransactionManager] - B883/1: Sending ZigBeeTransaction [ieeeAddress=BC33ACFFFEEF6F95 queueTime=1, state=WAITING, sendCnt=0, command=DefaultResponse [On/Off: 0000/0 -> B883/1, cluster=0006, TID=01, commandIdentifier=253, statusCode=FAILURE]]
2020-11-24 21:38:14.533 [DEBUG] [transaction.ZigBeeTransactionManager] - transactionListenerAdded: 1 outstanding
2020-11-24 21:38:14.533 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - TX CMD: DefaultResponse [On/Off: 0000/0 -> B883/1, cluster=0006, TID=01, commandIdentifier=253, statusCode=FAILURE]
2020-11-24 21:38:14.534 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - TX ZCL: ZclHeader [frameType=ENTIRE_PROFILE_COMMAND, manufacturerSpecific=false, direction=SERVER_TO_CLIENT, disableDefaultResponse=true, manufacturerCode=0, sequenceNumber=1, commandId=11]
2020-11-24 21:38:14.534 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - TX APS: ZigBeeApsFrame [sourceAddress=0000/1, destinationAddress=B883/1, profile=0104, cluster=0006, addressMode=DEVICE, radius=8, apsSecurity=false, ackRequest=true, apsCounter=FB, rssi=–, lqi=–, payload=18 01 0B FD 01]
2020-11-24 21:38:14.534 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - Incoming message from node B883 did not translate to command

[3] https://github.com/openhab/org.openhab.binding.zigbee/tree/2.5.x/org.openhab.binding.zigbee/src/main/resources

[4] https://developer.tuya.com/en/docs/iot/device-development/module/zigbee-module/zs3l?id=K97r37j19f496

[5]


I have exactly the same problem running OH 2.5.10 in combination with a different coordinator (Quivicon, recognized as Telegesis (Firmware R309C))

The 4-button switches report as “TS0044”, vendor “_TZ3000_vp6clf9d”, manufacturer “0x1002”, but OH does not recognize the button press.
What I get is the battery level and the battery voltage, which gets updated whenever I press a button.
A bit strange is (as seen in the screenshot above it too reports as mains powered, where it is running on battery).
Battery levels etc. show up as channels for each button, but that is something I can live with.
The switched support short- and long press actions but the device discovered does not distinguish.
Sounds like it is discovered as a different device, correct ?
Those Switches are really nice, and perfect for locations without wiring.

Any chance we get these working with OH ?

Just found this:

Looks like Deconz implemented support for this kind of switch, after they had similar issues with the 0xFD / 253 command:

00:10:57:170 no button map for: TS0043 ep: 0x03 cl: 0x0006 cmd: 0xFD pl[0]: 000

I’ve been playing around with the buttons a bit, and looks like command 0xFD with a following message/body(?) of 0x00 means “single press”, 0x01 means “double press” and 0x02 means “long press”.
I just can’t figure out how to create an XML description for this device, could not find any documentation on that.

Maybe @chris can help you with the XML.

Take a look at the binding source - this should have a few examples of remote controls etc where you can define the commands and what they do. In addition, you need to add an entry to the discovery files which define how the devices are detected (so that they don’t use the auto channel discovery that the binding uses for most devices).

Take a look there, and if you have any questions, let me know and I’ll try and answer :slight_smile:

Thanks @chris, what exactly do you mean by “binding source”?
I looked at the source code already and found the other XML files under “org.openhab.binding.zigbee\src\main\resources\ESH-INF\thing”.
But the examples listed there don’t give me a clear understanding what to add for my thing.
Does that look right to you?

		<channel id="left" typeId="system.button">
			<label>Left Button</label>
			<properties>
				<property name="zigbee_endpoint">1</property>
				<property name="zigbee_shortpress_cluster_id">0x0006</property>
				<property name="zigbee_shortpress_attribute_id">253</property>
				<property name="zigbee_shortpress_attribute_value">1</property>
			</properties>
			[..]

I also patched ZigBeeThingTypeMatcher.java to match properties by regex, since these things have random parts in their name.

edit 11/30/2020 < incorrect code removed >

Thanks,
Daniel

I mean the binding source code for the ZigBee binding.

You can find it here -:

I’m not really sure what you are trying to do and I’d need to spend some time to work this out. I thought I’d read above that you had a cluster specific command.

I’ll need to look more at this - I’ll try and find some time later in the week.

Sounds good.
You may hav guessed, I am already looking at the source code, but I’d appreciate your expert feedback.

In the meantime, I’ll try to compile and test my changes.

Let me know whenever you need additional testing, I’m willing to support as I have a similar switch here.

I’ve got the build system working, and I added regex matching to the ZigbeeThingTypeMatcher with unittests.
That part works.

@chris:
I could use some help translating the unknown message into an XML mapping.

2020-11-24 21:38:14.531 [DEBUG] [tsystems.zigbee.ZigBeeNetworkManager] - RX APS: ZigBeeApsFrame [sourceAddress=B883/1, destinationAddress=0000/1, profile=0104, cluster=0006, addressMode=DEVICE, radius=0, apsSecurity=false, ackRequest=false, apsCounter=AC, rssi=-48, lqi=D0, payload=01 01 FD 00]

I am guessing, B883 is the device, /1 is the endpoint, cluster is 0006…?
What about the payload 01 01 FD 00…?
The last byte is 00 for short press, 01 for double press and 02 for long press.
FD seems to be the command id, but how do I map that to XML…?
And the leading 01 01?

I have deployed an XML that crashed the bindings:

2020-11-30 10:22:33.390 [ERROR] [ng.zigbee.handler.ZigBeeThingHandler] - 00158D00058034B8: Exception creating channels

And I’m a bit reluctant to blindly keep trying new code because I need my the coordinator to be up :slight_smile:

I found an XML file describing what the coordinator thinks the device looks like (without my modifications):
3gang BC33ACFFFEEF6F63.xml (86.3 KB)

Some new findings:
Today German discounter LIDL startet a zigbee system branded “SilverCrest” with bulbs, plugs, stripes, panels etc.
They offer a gateway as well.
I did some testing:
With this Gateway the switch is recognized with full functionality.
Digging deeper the LIDL plug was discovered by a Hue Brige, from the ID provided and the model info I think this might be a Tuya system. Then it is clear why the switch was working without issues.

Hi Thomas,

I bought such a Gateway, a bulb and a stripe and I got it working with the Lildl App.

I tried to install the gateway to OH3, but failed, as I don’t know what Type of Thing to use, and of course which parameters to use.
So my question now: Is it possible to include the gateway to openHAB and if possible could you please help me ?
Thx Peter

@fibu-freak, let’s use this thread to discuss connecting the Tuya switches to OH2 natively (without gateway).
Please open a new topic to discuss how to connect the LIDL gateway to OH2/OH3.

@chris, I could use your help to investigate whether support for these switches can be added in the Zigbee bindings (using XML definitions for the device), or whether that has to be done on the lower level (in com.zsmartsystems.zigbee by adding support for the new command 253 as a new Tuya-specific ToggleCommand, maybe).

Thanks,
Daniel

There is no binding that supports the Lidl gateway yet, so up to now this is a closed system.

@Oggerschummer
THX Thomas for your for your hint.

@schalli
Sorry, Daniel. As I find the expression “Lidl Gateway” in your thread, I thought I could ask a short question without opening an extra thread. But Thomas just posted the answer.

Cheers - Peter

I’m happy to answer any questions - I don’t have the devices so can’t really help much.

We would not add support in the zigbee library for custom commands. Any support, if possible, must be done in the binding.

@chris, thanks for the kind offer.
As mentioned in the thread, I am at a loss how to add support.
I’ve tried adding an XML file describing the new command type:
ts0041.xml (1.4 KB)

But that resulted in various crashes of the zigbee library:

2020-12-06 22:02:59.966 [ERROR] [ng.zigbee.handler.ZigBeeThingHandler] - 00158D00054DC510: Exception creating channels
java.lang.NullPointerException: null
at com.zsmartsystems.zigbee.zcl.ZclCluster.readAttributeValue(ZclCluster.java:480) ~[bundleFile:?]
at com.zsmartsystems.zigbee.zcl.ZclAttribute.readValue(ZclAttribute.java:193) ~[bundleFile:?]
at org.openhab.binding.zigbee.internal.converter.ZigBeeConverterSwitchOnoff.handleRefresh(ZigBeeConverterSwitchOnoff.java:198) ~[bundleFile:?]
at org.openhab.binding.zigbee.handler.ZigBeeThingHandler.doNodeInitialisation(ZigBeeThingHandler.java:406) [bundleFile:?]
at org.openhab.binding.zigbee.handler.ZigBeeThingHandler.access$0(ZigBeeThingHandler.java:239) [bundleFile:?]
at org.openhab.binding.zigbee.handler.ZigBeeThingHandler$1.call(ZigBeeThingHandler.java:233) [bundleFile:?]
at org.openhab.binding.zigbee.handler.ZigBeeThingHandler$1.call(ZigBeeThingHandler.java:1) [bundleFile:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_275]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_275]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_275]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_275]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_275]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_275]

After that first crash, I added attribute 0 (which was causing the crash), to the channel properties like so:

  			<property name="zigbee_shortpress_attribute_id">0</property>
  			<property name="zigbee_shortpress_attribute_value">true</property>

But that resulted in the following crash:

2020-12-06 22:17:23.574 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception:
java.lang.NullPointerException: null
at org.openhab.binding.zigbee.discovery.ZigBeeNodePropertyDiscoverer.addPropertiesFromBasicCluster(ZigBeeNodePropertyDiscoverer.java:157) ~[?:?]
at org.openhab.binding.zigbee.discovery.ZigBeeNodePropertyDiscoverer.getProperties(ZigBeeNodePropertyDiscoverer.java:109) ~[?:?]
at org.openhab.binding.zigbee.discovery.ZigBeeDiscoveryService$2.run(ZigBeeDiscoveryService.java:207) ~[?:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_275]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_275]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_275]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_275]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_275]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_275]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_275]

Is there a simple way to make the Zigbee library understand, that command 253 (with an attribute(?) of 00) means, the swich was toggled?

If you have time, I would appreciate if you could read through the thread and help me add support for that command (using XML, I presume…).

Thanks,
Daniel

What version of the binding are you using? I can’t correlate these line numbers with the current 2.5 binding at least.

If you mean can you map the current switch command to a new command, then no, this is not possible. The switch converter is designed to use the standard ZCL commands and it will not be possible to change that.

When posting logs, please post them with code fences - it’s really very hard to read them as you’ve displayed above.

This is a problem at the moment as we’re moving house over the next couple of months so I’m very short on time. I’m not super familiar with the XML definitions as this code was added by German Telekom to support the Qivicon system and while I supported that work when it was added a few years ago, it’s not something that I’ve really used so I’ll need to work this all out myself - just like you :wink: