Closed BenRoe closed 3 months ago
I also have TS0021 but it's showing as "smoke". I can provide more info if needed, hope to see this included in ZHA.
I also have this device but for me it shows Opening as the Sensor
Hi, I had the same issue here. Didn't manage to write a quirk but instead wrote an automation that triggers when the error shows up in the logs. Works perfectly fine. From the "unknow cluster command " message you can determine both the button and the type of tap. See automation below. Hope it helps ;)
alias: Boton setup jaime description: "" trigger:
Well I've been making my first foray into zigpy for these switches. I've got the signature piece down, but could probably do with little hint on what I've got wrong below. Presumably it's just the clusters I'm mapping don't have the needed functionality. I've tried a number of combinations without full success on using button presses to do anything.
Currently the devce is recognized, but looks like I have not properly assigned datapoint handlers (it's clear the TuyaNewManufCluster is falling through all of the things it can handle). I'm a bit hazy on how to determine if an existing class works or what. (The zigbee2mqtt implementation didn't look complicated, but I stll haven't grasped how it works enough to translate to zigpy.)
Including log results when I press the buttons now (I could have sworn dp 10 for batteries hadn't done this before when I understood less of what I was doing, but oh well). It pretty a straightforward missing implementation, though
2024-02-11 20:23:20.264 DEBUG (MainThread) [zigpy.zcl] [0x3721:1:0xef00] No datapoint handler for TuyaDatapointData(dp=2, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))
2024-02-11 20:29:15.481 DEBUG (MainThread) [zigpy.zcl] [0x3721:1:0xef00] No datapoint handler for TuyaDatapointData(dp=1, data=TuyaData(dp_type=<TuyaDPType.ENUM: 4>, function=0, raw=b'\x00', *payload=<enum8.undefined_0x00: 0>))
2024-02-11 21:19:40.839 DEBUG (MainThread) [zigpy.zcl] [0x3721:1:0xef00] No datapoint handler for TuyaDatapointData(dp=10, data=TuyaData(dp_type=<TuyaDPType.VALUE: 2>, function=0, raw=b'\x00\x00\x00\x00', *payload=0))
My quirk:
"""Tuya 2 Button Remote."""
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, OnOff, Ota, PowerConfiguration, Time
from zigpy.zcl.clusters.security import IasZone
from zhaquirks.const import (
BUTTON_1,
BUTTON_2,
COMMAND,
DEVICE_TYPE,
DOUBLE_PRESS,
ENDPOINT_ID,
ENDPOINTS,
INPUT_CLUSTERS,
LONG_PRESS,
MODEL,
OUTPUT_CLUSTERS,
PROFILE_ID,
SHORT_PRESS,
)
from zhaquirks.tuya import TuyaNewManufCluster, TuyaNoBindPowerConfigurationCluster, TuyaSmartRemoteOnOffCluster, TuyaSwitch
class TuyaSmartRemote0021(TuyaSwitch):
"""Tuya 2-button remote device."""
signature = {
MODEL: "TS0021",
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
INPUT_CLUSTERS: [
Basic.cluster_id,
PowerConfiguration.cluster_id,
IasZone.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
INPUT_CLUSTERS: [
Basic.cluster_id,
PowerConfiguration.cluster_id,
IasZone.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [
Basic.cluster_id,
TuyaNoBindPowerConfigurationCluster,
TuyaSmartRemoteOnOffCluster,
TuyaNewManufCluster,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
INPUT_CLUSTERS: [
Basic.cluster_id,
TuyaNoBindPowerConfigurationCluster,
TuyaSmartRemoteOnOffCluster,
TuyaNewManufCluster,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
},
}
device_automation_triggers = {
(SHORT_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: SHORT_PRESS},
(LONG_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS},
(DOUBLE_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS},
(SHORT_PRESS, BUTTON_2): {ENDPOINT_ID: 2, COMMAND: SHORT_PRESS},
(LONG_PRESS, BUTTON_2): {ENDPOINT_ID: 2, COMMAND: LONG_PRESS},
(DOUBLE_PRESS, BUTTON_2): {ENDPOINT_ID: 2, COMMAND: DOUBLE_PRESS},
}
I'm moderately experienced with python and handy with grep, so I can easily troubleshoot more or provide more info, but I'm hoping someone witth more knowledge of this software can easily spot the issue!
@jaimezapa Do you mind posting your reply as code block because I cannot get it to work. Thanks
@jaimezapa Do you mind posting your reply as code block because I cannot get it to work. Thanks
Here you have it. Bare in mind that you need to add this to your config file system_log: fire_event: true
Then check the logs to get the device ID
alias: Boton setup jaime
description: ""
trigger:
- platform: event
event_type: system_log_event
event_data:
name: zigpy.zcl
id: liso
condition:
- condition: template
value_template: "{{ \"0xCECD:1:0xef00\" in trigger.event.data.message[0] }}"
enabled: true
action:
- choose:
- conditions:
- condition: template
value_template: "{{ \"\\\\x02\\\\x04\" in trigger.event.data.message[0] }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x00\" in trigger.event.data.message[0] }}"
sequence:
- service: light.toggle
target:
entity_id: light.suite_all_studio_all
data: {}
alias: single
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x01\" in trigger.event.data.message[0] }}"
sequence:
- service: switch.toggle
target:
entity_id: switch.adaptive_lighting_sleep_mode_al_studio
data: {}
alias: double
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x02\" in trigger.event.data.message[0] }}"
sequence: []
alias: long
alias: boton liso
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x04\" in trigger.event.data.message[0] }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x00\" in trigger.event.data.message[0] }}"
sequence:
- if:
- condition: device
type: is_off
device_id: 1220c3eafc6d7f8b55d55f95e5ebbfc4
entity_id: 50111a494b1a6048f7a9cbd971090e28
domain: light
then:
- service: light.turn_on
target:
device_id: []
area_id: []
entity_id: light.ewelink_ck_bl702_al_01_7009_z102lg03_1_light_8
data: {}
- service: light.turn_on
target:
device_id: []
area_id: []
entity_id: light.ewelink_ck_bl702_al_01_7009_z102lg03_1_light_8
data:
rgb_color:
- 255
- 56
- 0
- service: adaptive_lighting.set_manual_control
data:
manual_control: true
entity_id: switch.adaptive_lighting_adaptative_lights_1
else:
- service: adaptive_lighting.set_manual_control
data:
manual_control: false
entity_id: switch.adaptive_lighting_adaptative_lights_1
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- service: light.turn_off
target:
device_id: []
area_id: []
entity_id: light.all_lights_hall_lights
data: {}
alias: single
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x01\" in trigger.event.data.message[0] }}"
sequence:
- service: media_player.media_next_track
target:
entity_id: media_player.spotify_jaime
data: {}
alias: double
- conditions:
- condition: template
value_template: "{{ \"\\\\x01\\\\x02\" in trigger.event.data.message[0] }}"
sequence:
- service: switch.toggle
target:
entity_id: switch.setup_jaime_switch
data: {}
alias: long
alias: boton rugoso
default: []
- delay:
hours: 0
minutes: 0
seconds: 3
milliseconds: 0
enabled: true
mode: single
@jaimezapa I have just tried an even simpler version and it doesn't work. I managed to troubleshoot it and the automation is not triggering because ZHA is firing "DEBUG" events and the system_log_event type only accepts ERROR and WARNING...
When I manually create a notification using system_log.write, with default level, it does trigger the automation. But not when using DEBUG.
Is ZHA sending ERROR/WARNING level into your log on your end? If so, how did you manage it to do that?
I see. Yesterday I upgraded HA to 2024.2 and looks like they've changed the log type. In the 2023.10 version zigpy would throw this as a warning instead of debug. Guess we'll have to come up with a workaround...
[zigpy.zcl] [0xB9C5:1:0xef00] No explicit handler for cluster command 0x06: b'\x02r\x02\x04\x00\x01\x00'
Maybe monitor the stdout logs from outside the container and throw MQTT messages?
To be honest, I'm giving up. The effort is not worth it over just buying another €10 button on AliExpress. Thank you very much for the responses here anyway @jaimezapa
Feel free to try this code, I run it as a service and works like a charm. Note that debug should stay enabled for zigpy (tomorrow I´ll see if I can filter the with logger first)
''' import os import sys import time import re import subprocess
log_file_path = "volumes/home_assistant/home-assistant.log"
pattern_lucia = re.compile(r"[0xB9C5:1:0xef00]") pattern_jaime = re.compile(r"[0xCECD:1:0xef00] Unknown cluster command")
webhook_url_lucia = "http://your-HA:8123/api/webhook/Setup-lucia" webhook_url_jaime = "http://your-HA:8123/api/webhook/Setup-jaime"
def send_curl_command(code,webhook): curl_command = ["curl", "-X", "POST", "-d", f"code={code}", webhook] subprocess.run(curl_command)
def check_log(): with open(log_file_path, "r") as f:
f.seek(0, os.SEEK_END)
# Continuously monitor new lines added to the log file
while True:
line = f.readline()
if line:
# Check if the line contains the specified pattern_lucia
if pattern_lucia.search(line):
# Extract the code from the log entry
match = re.search(r"b'([^']+)'", line)
if match:
code = match.group(1)
# Send the curl command with the code
send_curl_command(code,webhook_url_lucia)
# Check if the line contains the specified pattern_jaime
if pattern_jaime.search(line):
# Extract the code from the log entry
match = re.search(r"b'([^']+)'", line)
if match:
code = match.group(1)
# Send the curl command with the code
send_curl_command(code,webhook_url_jaime)
else:
# Sleep for a short interval before checking again
time.sleep(0.1)
try:
check_log()
except KeyboardInterrupt:
sys.exit(0)
except Exception as e:
print("Error:", e)
'''
I have the same switch. The first time I added it, it got recognized as smoke detector (like @accik 's one) then I removed it and added a second time and it got recognized as an opening detector (like @CoarsePiglet 's one). Removing and adding it again seems to retain the opening configuration. I also tried initiating the pairing process from both buttons and tried to repeatly press 'em during pairing. No change. :(
I'm trying to write a quirk based on @hexalm 's code. But it seems ZHA does not use my quirk, just its default code:
Enabling debug log, I can see:
2024-03-17 09:40:55.501 DEBUG (MainThread) [homeassistant.components.zha.core.discovery] Discovering entities for device: a4:c1:38:a1:0b:25:6a:cf-_TZ3210_3ulg9kpo TS0021
2024-03-17 09:40:55.501 DEBUG (MainThread) [homeassistant.components.zha.core.discovery] Attempting to discover quirks v2 entities for device: a4:c1:38:a1:0b:25:6a:cf-_TZ3210_3ulg9kpo TS0021
2024-03-17 09:40:55.501 DEBUG (MainThread) [homeassistant.components.zha.core.discovery] Device: a4:c1:38:a1:0b:25:6a:cf-_TZ3210_3ulg9kpo TS0021 is not a quirks v2 device - skipping discover_quirks_v2_entities
2024-03-17 09:40:55.501 DEBUG (MainThread) [homeassistant.components.zha.core.gateway] device - 0xAF62:a4:c1:38:a1:0b:25:6a:cf entering async_device_initialized - is_new_join: True
2024-03-17 09:40:55.501 DEBUG (MainThread) [homeassistant.components.zha.core.gateway] device - 0xAF62:a4:c1:38:a1:0b:25:6a:cf has joined the ZHA zigbee network
2024-03-17 09:40:55.502 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xAF62](TS0021): started configuration
2024-03-17 09:40:55.502 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:ZDO](TS0021): 'async_configure' stage succeeded
2024-03-17 09:40:55.505 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: Performing cluster binding
2024-03-17 09:40:55.507 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0000]: Configuring cluster attribute reporting
2024-03-17 09:40:55.507 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0000]: finished cluster handler configuration
2024-03-17 09:40:55.507 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0xef00]: Performing cluster binding
2024-03-17 09:40:55.508 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0019]: finished cluster handler configuration
2024-03-17 09:40:55.508 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0019]: finished cluster handler configuration
2024-03-17 09:40:55.707 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: started IASZoneClusterHandler configuration
2024-03-17 09:40:55.784 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: bound 'power' cluster: Status.SUCCESS
2024-03-17 09:40:55.784 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: Configuring cluster attribute reporting
2024-03-17 09:40:56.206 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: bound 'ias_zone' cluster: Status.SUCCESS
2024-03-17 09:40:56.284 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: Failed to configure reporting for '[]' on 'power' cluster: [ConfigureReportingResponseRecord(status=<Status.SUCCESS: 0>), ConfigureReportingResponseRecord(status=<Status.SUCCESS: 0>)]
2024-03-17 09:40:56.284 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: Successfully configured reporting for '{'battery_percentage_remaining', 'battery_voltage'}' on 'power' cluster
2024-03-17 09:40:56.284 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0001]: finished cluster handler configuration
2024-03-17 09:40:58.342 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: Enroll requested
2024-03-17 09:40:58.342 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: wrote cie_addr: 00:12:4b:00:25:90:6b:f1 to 'ias_zone' cluster
2024-03-17 09:40:58.342 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: Sending pro-active IAS enroll response
2024-03-17 09:40:58.343 DEBUG (MainThread) [homeassistant.components.zha.core.cluster_handlers] [0xAF62:1:0x0500]: finished IASZoneClusterHandler configuration```
Any hints? Tks.
@NdK73 apologies - I found out a bit ago that the quirk signature was not being recognized, but haven't gotten back to working on this yet. I must have had a cached version or something when I thought it was working.
If you go to the service and pick the option to "configure zigbee device" (three dots next to the 'reconfigure' option) you can see the signature. I know I had it being recognized before I added the second endpoint (but still I never got the thing to give me any button entities). Tuya's stuff is just weird and I could stand help from someone who has worked on the ZHA handlers for them.
Maybe I'll look at this again today, but I'm planning to redo my architecture for HA and might be switching to zigbee2mqtt.
I'm moderately experienced with python and handy with grep, so I can easily troubleshoot more or provide more info, but I'm hoping someone witth more knowledge of this software can easily spot the issue!
Did you make any progress with this quirk? I wasn't able to get yours to load for the TS0021 switch without making some changes, such as removing the second endpoints
So I somehow managed to get it so that switches were showing up in the entities instead of an IASZone sensor, however, neither responded to button presses from the actual device. Has anyone else made any progress with this? I was using a slightly modified version of the TS0042 code that already exists as a working quirk.
If only I knew about this issue before ordering...
After adding this switch, I got the same thing as CoarsePiglet, ZHA recognized device as "Opening". The problem is that you don't know the device name until you add it to ZHA, hence you can't know it's not supported.
The strange thing is there are people in aliexpress' reviews saying it's working in HA for them, so I'm not sure can it be some different firmware version or what?
Mentioned zigbee2mqtt issue in OP is done almost two months ago, so is there any chance this one will be fixed soon?
Probably the users saying it's working are using it via a Tuya gateway. Too bad I've had no time yet to look at the issue :(
It's really shame, as I wanted to get into zigbee ecosystem and use a switch instead of my phone for two devices, I ordered this switch as it has 2 gangs, waited for a month and looked forward, just to find out about this issue... now I have a coordinator without any zigbee devices.
Probably the users saying it's working are using it via a Tuya gateway.
They are saying it works with HA, so I'm not sure are they referring to zigbee2mqtt, or it's possible to add this switch over tuya integration instead of ZHA? I assume it won't work that way, as the coordinator is not tuya gateway, but a USB dongle E.
Unfortunately, my system uses HA core, which doesn't support addons, so I can't switch to zigbee2mqtt, and I guess the only way is to wait for someone to add the support. I looked at a code myself, but I never did anything similar, so I have no idea where to start. If there was a class for a similar switch, I could try changing source code a bit. Although, I wouldn't know how to test it.
As @Drethak mentioned, seems like this switch is also recognized in ZHA as TS0042, physically it looks the same.
I ended up ordering the following and it works great out of the box with zha. I forget to check the compatibility list before ordering items and one really should. This button has at least two functions for 1. click and 2. double-click and maybe a 3. long press.
It's really shame, as I wanted to get into zigbee ecosystem and use a switch instead of my phone for two devices, I ordered this switch as it has 2 gangs, waited for a month and looked forward, just to find out about this issue... now I have a coordinator without any zigbee devices.
Believe it or not, the same device is in my cart, and I hesitated between that one and the one from OP. Unfortunately, I made a mistake and ordered this one just because it has 2 gangs.
lol, I did the same!
On Sun, Apr 21, 2024 at 11:37 AM netizeni @.***> wrote:
Believe it or not, the same device is in my cart, and I hesitated between that one and the one from OP. Unfortunately, I made a mistake and ordered this one just because it has 2 gangs.
— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/2847#issuecomment-2068087535, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABAU7PAVTILEJZQU2NHFXNLY6PMKZAVCNFSM6AAAAABA24JCZWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANRYGA4DONJTGU . You are receiving this because you commented.Message ID: @.***>
I have the same issue here: I use HA with Tuya integration using a Tuya ZigBee gateway. In the first addition he appeared as Smoke, in the second as Contact. Pressing the second button shows it as Open in HA. But the rest doesn't work.
Hi @MattWestb, sorry for tagging, but seems like you are our only hope. I was digging around both source code and old issues, and you appeared helping a lot of people with similar issues regarding tuya switches. You can see how it looks in OP. This is the device signature:
It's strange it only has one endpoint, while TS0042 (also 2 gang switch) has two endpoints. Regardless, I tried editing ts0042.py
as it seems to be the closest to this device, loaded it as a custom quirk (logs showing its presence) but it never changes the device "configuration" i.e. always showing "opening" sensor. Do you maybe know what seems to be the problem? Quirk will be pasted below, and I made sure simpleDescriptor has a correct value from a signature.
I've spent way too much time on trying to make this work, so at this point, I will probably just switch to Z2M as it works there with no issues. Understandably, tuya devices are ridiculous and this is an open source project, but the lack of consistency in the source code and a clear documentation make this exceptionally hard to add a working device.
Here's the updated custom quirk, it still doesn't work, but somebody might want to try to fix it. To save some time to whoever tries, I went over different classes in the project and noticed fields of endpoints object are mapped based on SizePrefixedSimpleDescriptor
values for that specific field. The logs were showing device_type mismatch in the previous quirk, so once I put IAS_ZONE
, it now shows input clusters mismatch. Now comes the inconsistency I spoke about, as in multiple classes, the number 61184 in the input_clusters is mapped to multiple different values like TuyaManufCluster, TuyaNewManufCluster, TuyaManufClusterAttributes
and a few more. There's no clear way in the logs to know is this mismatch in endpoints
object or replacement
object. I assume once someone finds the correct combination of input_clusters
array, there won't be a mismatch, so the system will start using the custom quirk.
I bought this same switch and went down the rabbit hole as well. The signature part was pretty easy to get right, but I didn't get nearly as close as @netizeni did.
This really bothers me, so I spend additional time to try to make it work. I've managed to add a correct signature combination, so now the device will show a switch toggle, and even tho it doesn't work, at least it's not "Opening" sensor anymore. Also, "Zigbee info" will now show that custom quirk is being used and under automation, you can see "first button pressed", double pressed and long pressed.
Unfortunately, single, double and long press don't work, as it seems the device doesn't fire zha_event
. I will share the custom quirk below, so hopefully someone will join in fixing it. It would be also helpful if you guys, who have this device, try different combination of clusters (from different switch classes of this project) inside INPUT_CLUSTERS
and OUTPUT_CLUSTERS
arrays of replacement
objects and report back if you find something works. My assumption is once replacement
objects gets filled with correct clusters, the device will start firing events and will work as it should.
I bought a button that works OOtB from aliexpress for something like $5 delivered to the USA. At my hourly rate, that's about 1/10th of an hour. I threw this one away. I use the zigbee compatibility list before buying anything these days.
On Mon, May 6, 2024 at 5:36 PM netizeni @.***> wrote:
This really bothers me, so I spend additional time to try to make it work. I've managed to add a correct signature combination, so now the device will show a switch toggle, and even tho it doesn't work, at least it's not "Opening" sensor anymore. Also, "Zigbee info" will now show that custom quirk is being used and under automation, you can see "first button pressed", double pressed and long pressed.
Unfortunately, single, double and long press don't work, as it seems the device doesn't fire zha_event. I will share the custom quirk below, so hopefully someone will join in fixing it. It would be also helpful if you guys, who have this device, try different combination of clusters (from different switch classes of this project) inside INPUT_CLUSTERS and OUTPUT_CLUSTERS arrays of replacement objects and report back if you find something works. My assumption is once replacement objects gets filled with correct clusters, the device will start firing events and will work as it should. Custom quirk
"""Tuya 2 Button Remote.""" from zigpy.profiles import zhafrom zigpy.quirks import CustomDevicefrom zigpy.zcl.clusters.general import Basic, OnOff, Ota, PowerConfiguration, Timefrom zigpy.zcl.clusters.security import IasZone from zhaquirks.const import ( BUTTON_1, BUTTON_2, COMMAND, DEVICE_TYPE, DOUBLE_PRESS, ENDPOINT_ID, ENDPOINTS, INPUT_CLUSTERS, LONG_PRESS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, SHORT_PRESS, )from zhaquirks.tuya import ( TuyaManufCluster, TuyaNewManufCluster, TuyaManufClusterAttributes, TuyaNoBindPowerConfigurationCluster, TuyaSmartRemoteOnOffCluster, )from zhaquirks.tuya.mcu import ( MoesSwitchManufCluster, TuyaOnOff, TuyaOnOffManufCluster, TuyaOnOffNM, )
class TuyaSmartRemote0021TI(CustomDevice): """Tuya 2-button remote device with time on in cluster."""
def __init__(self, *args, **kwargs): """Init device.""" self.motion_bus = Bus() super().__init__(*args, **kwargs) signature = { # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=1026, device_version=1, input_clusters=[1, 1280, 61184, 0], output_clusters=[25, 10])) MODELS_INFO: [("_TZ3210_3ulg9kpo", "TS0021")], ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ PowerConfiguration.cluster_id, IasZone.cluster_id, TuyaOnOffManufCluster.cluster_id, Basic.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id], }, }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL, INPUT_CLUSTERS: [ Basic.cluster_id, TuyaNoBindPowerConfigurationCluster, TuyaSmartRemoteOnOffCluster, ], OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id], }, }, } device_automation_triggers = { (SHORT_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: SHORT_PRESS}, (LONG_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS}, (DOUBLE_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS}, }
class TuyaSmartRemote0021TO(CustomDevice): """Tuya 2-button remote device with time on out cluster."""
signature = { # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=1026, device_version=1, input_clusters=[1, 1280, 61184, 0], output_clusters=[25, 10])) MODELS_INFO: [("_TZ3210_3ulg9kpo", "TS0021")], ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.IAS_ZONE, INPUT_CLUSTERS: [ PowerConfiguration.cluster_id, IasZone.cluster_id, TuyaOnOffManufCluster.cluster_id, Basic.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id], }, }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL, INPUT_CLUSTERS: [ Basic.cluster_id, TuyaNoBindPowerConfigurationCluster, TuyaSmartRemoteOnOffCluster, ], OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id], }, }, } device_automation_triggers = { (SHORT_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: SHORT_PRESS}, (LONG_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS}, (DOUBLE_PRESS, BUTTON_1): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS}, }
— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/2847#issuecomment-2096965516, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABAU7PAF2SSU4ESSHMWB3S3ZA7ZXLAVCNFSM6AAAAABA24JCZWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOJWHE3DKNJRGY . You are receiving this because you commented.Message ID: @.***>
I understand your point of view, Mike, it's valid, but at least in my case, this is not about the price itself. It's about helping the community and all the people who have or will have this switch. If there weren't all these people selflessly contributing before us, we wouldn't be able to use zha integration.
All in all, I hope someone will join in to help and make this work. I assume Matt West would be able to solve this easily, but I don't want to tag him again.
I definitely agree. On the other hand, manufacturers who build nonstandard stuff shouldn't be supported.
On Tue, May 7, 2024 at 7:20 AM netizeni @.***> wrote:
I understand your point of view, Mike, it's valid, but at least in my case, this is not about the price itself. It's about helping the community and all the people who have or will have this switch. If there weren't all these people selflessly contributing before us, we wouldn't be able to use zha integration.
All in all, I hope someone will join in to help and make this work. I assume Matt West would be able to solve this easily, but I don't want to tag him again.
— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/2847#issuecomment-2098170606, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABAU7PAP5SIWU4GZCON2UMDZBC2HTAVCNFSM6AAAAABA24JCZWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOJYGE3TANRQGY . You are receiving this because you commented.Message ID: @.***>
I finally came up with a hacky quirk that seems to work okay on my system (core 2024.7.0
):
"""Device handler the TS0021."""
from zhaquirks import EventableCluster
from zigpy.quirks import CustomDevice
from zhaquirks.const import (
ARGS,
ATTRIBUTE_ID,
CLUSTER_ID,
COMMAND_ATTRIBUTE_UPDATED,
COMMAND,
SKIP_CONFIGURATION,
DEVICE_TYPE,
ENDPOINT_ID,
ENDPOINTS,
INPUT_CLUSTERS,
LONG_PRESS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PARAMS,
PROFILE_ID,
SHORT_PRESS,
DOUBLE_PRESS,
VALUE,
)
from zhaquirks.tuya import (
TUYA_CLUSTER_ID,
TuyaNewManufCluster,
DPToAttributeMapping,
)
BTN_1 = "Button 1"
BTN_2 = "Button 2"
COMMAND_1_PRESSED = 'btn_1_pressed'
COMMAND_2_PRESSED = 'btn_2_pressed'
class TuyaCustomCluster(TuyaNewManufCluster, EventableCluster):
dp_to_attribute = {
1: DPToAttributeMapping(
TuyaNewManufCluster.ep_attribute,
COMMAND_1_PRESSED,
),
2: DPToAttributeMapping(
TuyaNewManufCluster.ep_attribute,
COMMAND_2_PRESSED,
),
}
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
}
class TS0021(CustomDevice):
signature = {
MODELS_INFO: [("_TZ3210_3ulg9kpo", "TS0021")],
ENDPOINTS: {
1: {
PROFILE_ID: 0x0104,
DEVICE_TYPE: 0x0402,
INPUT_CLUSTERS: [
0x0000,
0x0001,
0x0500,
0xef00,
],
OUTPUT_CLUSTERS: [
0x000a,
0x0019,
],
},
},
}
replacement = {
SKIP_CONFIGURATION: False,
ENDPOINTS: {
1: {
PROFILE_ID: 0x0104,
DEVICE_TYPE: 0x0402,
INPUT_CLUSTERS: [
0x0000,
0x0001,
0x0500,
TuyaCustomCluster,
],
OUTPUT_CLUSTERS: [
0x000a,
0x0019,
],
},
},
}
device_automation_triggers = {
(SHORT_PRESS, BTN_1): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 0},
},
(DOUBLE_PRESS, BTN_1): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 1},
},
(LONG_PRESS, BTN_1): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 2},
},
(SHORT_PRESS, BTN_2): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 0},
},
(DOUBLE_PRESS, BTN_2): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 1},
},
(LONG_PRESS, BTN_2): {
COMMAND: COMMAND_ATTRIBUTE_UPDATED,
CLUSTER_ID: TUYA_CLUSTER_ID,
ENDPOINT_ID: 1,
ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 2},
},
}
I finally came up with a hacky quirk that seems to work okay on my system (core
2024.7.0
):"""Device handler the TS0021.""" from zhaquirks import EventableCluster from zigpy.quirks import CustomDevice from zhaquirks.const import ( ARGS, ATTRIBUTE_ID, CLUSTER_ID, COMMAND_ATTRIBUTE_UPDATED, COMMAND, SKIP_CONFIGURATION, DEVICE_TYPE, ENDPOINT_ID, ENDPOINTS, INPUT_CLUSTERS, LONG_PRESS, MODELS_INFO, OUTPUT_CLUSTERS, PARAMS, PROFILE_ID, SHORT_PRESS, DOUBLE_PRESS, VALUE, ) from zhaquirks.tuya import ( TUYA_CLUSTER_ID, TuyaNewManufCluster, DPToAttributeMapping, ) BTN_1 = "Button 1" BTN_2 = "Button 2" COMMAND_1_PRESSED = 'btn_1_pressed' COMMAND_2_PRESSED = 'btn_2_pressed' class TuyaCustomCluster(TuyaNewManufCluster, EventableCluster): dp_to_attribute = { 1: DPToAttributeMapping( TuyaNewManufCluster.ep_attribute, COMMAND_1_PRESSED, ), 2: DPToAttributeMapping( TuyaNewManufCluster.ep_attribute, COMMAND_2_PRESSED, ), } data_point_handlers = { 1: "_dp_2_attr_update", 2: "_dp_2_attr_update", } class TS0021(CustomDevice): signature = { MODELS_INFO: [("_TZ3210_3ulg9kpo", "TS0021")], ENDPOINTS: { 1: { PROFILE_ID: 0x0104, DEVICE_TYPE: 0x0402, INPUT_CLUSTERS: [ 0x0000, 0x0001, 0x0500, 0xef00, ], OUTPUT_CLUSTERS: [ 0x000a, 0x0019, ], }, }, } replacement = { SKIP_CONFIGURATION: False, ENDPOINTS: { 1: { PROFILE_ID: 0x0104, DEVICE_TYPE: 0x0402, INPUT_CLUSTERS: [ 0x0000, 0x0001, 0x0500, TuyaCustomCluster, ], OUTPUT_CLUSTERS: [ 0x000a, 0x0019, ], }, }, } device_automation_triggers = { (SHORT_PRESS, BTN_1): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 0}, }, (DOUBLE_PRESS, BTN_1): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 1}, }, (LONG_PRESS, BTN_1): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_1_PRESSED, VALUE: 2}, }, (SHORT_PRESS, BTN_2): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 0}, }, (DOUBLE_PRESS, BTN_2): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 1}, }, (LONG_PRESS, BTN_2): { COMMAND: COMMAND_ATTRIBUTE_UPDATED, CLUSTER_ID: TUYA_CLUSTER_ID, ENDPOINT_ID: 1, ARGS: {ATTRIBUTE_ID: COMMAND_2_PRESSED, VALUE: 2}, }, }
Unfortunately this hasn't seemed to fix it for me, it's still either coming up as an IasZone sensor or a door opening sensor. Am I missing something else perhaps? (I just made a new custom quirk using this code)
@Drethak do you see the quirk active like this:
It will still show the "Opening" sensor. What the quirk enables are the automations for the buttons:
Could you check if those are available for you? Otherwise we'd need to take a look at the logs to figure out why the quirk is not kicking in. I'm now using the slightly more polished version from the PR (ts0021.py), but I believe both should work.
@rbaron Thank you! I wasn't even aware this was a thing, many thanks for pointing this out.
Edit: Yes that's working for me (forgot to mention!)
Can confirm it "mostly" works. Buttons are detected, but it still gets reported as a smoke (or door) sensor and battery is fixed at 0%. But at least it can be used in automations! Great! Hope it gets "backported" in ZHA soon.
this is in production now? I am still showing these TS0021 switches as openers, it's recognizing button presses but doesn't seem to show anything but single button press actions. am I just doing something wrong? I have reset them multiple times.
@justinreeves00 indeed even with quirk it still shows up as opener. The events you see on the logbook are not button presses, but "attribute updates". This is the custom way this button implements button presses. The updates are different for each event (single press 1, double press 2 etc), but the UI does not show that.
The only thing the quirk currently does is enabling automations like in this comment. If you can set up different automations for single, double, long press and they are triggered, I'd say it's working. Otherwise let me know and I can try helping debug.
Problem description
Tuya TS0021 is found in ZHA, but offers no functionality. Shows a switch control that does nothing.
Solution description
Add two way switch function.
Screenshots/Video
Screenshots/Video
Device signature
Device signature
```json { "node_descriptor": "NodeDescriptor(logical_type=Diagnostic information
Diagnostic information
```json { "home_assistant": { "installation_type": "Home Assistant Container", "version": "2023.12.3", "dev": false, "hassio": false, "virtualenv": false, "python_version": "3.11.6", "docker": true, "arch": "aarch64", "timezone": "Europe/Berlin", "os_name": "Linux", "os_version": "6.1.21-v8+", "run_as_root": true }, "custom_components": { "powercalc": { "version": "v1.9.10", "requirements": [ "numpy>=1.21.1" ] }, "hacs": { "version": "1.33.0", "requirements": [ "aiogithubapi>=22.10.1" ] }, "adaptive_lighting": { "version": "1.20.0", "requirements": [ "ulid-transform" ] }, "thermal_comfort": { "version": "2.2.0", "requirements": [] }, "ics_calendar": { "version": "4.1.0", "requirements": [ "ics>=0.7.2", "recurring_ical_events>=2.0.2", "icalendar>=5.0.4" ] }, "homematicip_local": { "version": "1.50.0", "requirements": [ "hahomematic==2023.12.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp", "universal_silabs_flasher" ], "requirements": [ "bellows==0.37.3", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.107", "zigpy-deconz==0.22.2", "zigpy==0.60.1", "zigpy-xbee==0.20.1", "zigpy-zigate==0.12.0", "zigpy-znp==0.12.0", "universal-silabs-flasher==0.0.15", "pyserial-asyncio-fast==0.11" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "0403", "pid": "6015", "description": "*conbee*", "known_devices": [ "Conbee III" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_uzg-01._tcp.local.", "name": "uzg-01*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 33192, "manufacturer": "_TZ3210_3ulg9kpo", "model": "TS0021", "name": "_TZ3210_3ulg9kpo TS0021", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 216, "rssi": -46, "last_seen": "2023-12-19T09:30:33", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=Logs
Logs
```python [Paste the logs here] ```Custom quirk
Custom quirk
```python [Paste your custom quirk here] ```Additional information
At zigbee2mqtt is already a open PR for that device. https://github.com/Koenkk/zigbee2mqtt/discussions/19765
The device can be found here https://www.aliexpress.com/item/1005006126584104.html