Help adding a variation of Tuya TS0044, TS004F to ZHA

I have a support request open at [Device Support Request] Tuya zigbee remote TS004F · Issue #897 · zigpy/zha-device-handlers · GitHub

I tried doing something similar but failed miserably. I followed the instructions at https://github.com/zigpy/zha-device-handlers#testing-new-releases. Copied the TS0044.py into the /deps/ folder where it is supposed to go. I hoped it would be a simple matter of changing the MODELS_INFO to correspond but nope. I broke HA. I believe I corrupted the zigbee.db. I had to delete it to get things kinda working and then restore from a snapshot. I may give it another shot with the info from the link but I’m going to make a complete backup before trying.

Oh
my quirk works with no trouble but it cant be mapped to be used as a 4 scene switch.
I had one trouble when adding the switch at first but I just reseted it and synced it again and it was working fine
I added the quirk based on the guide here : GitHub - zigpy/zha-device-handlers: ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices. (so not in the deps directory)

I am currently trying to analyse events in order to map them in a blueprint relying on this one :

If get it working please also submit a pull request to upstream → GitHub - zigpy/zha-device-handlers

I was having some success with the button maps using Node-RED and watching zha_events. I’ll give the docker install a try and see what I can come up with.

that is planned :wink:

Still trying to figure out how to bind the new scheme since there is only one endpoint for all buttons…

On this thread they manage to bind one click for all and long press for 3/4 for Zigbee2MQTT

Since this is the first time I deal with this kind of things on HA (I am a software developer), I still have to fully understand how to create these custom handlers and get all the debug info I need.

FYI 3/4 trigger these events

2021-05-25 20:45:03 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=False disable_default_response=False> manufacturer=None tsn=61 command_id=2>
2021-05-25 20:45:03 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] ZCL request 0x0002: [1, 51, 10]
2021-05-25 20:45:03 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] No handler for cluster command 2
2021-05-25 20:45:03 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event zha_event[L]: device_ieee=60:a4:23:ff:fe:db:30:83, unique_id=60:a4:23:ff:fe:db:30:83:1:0x0008, device_id=87b8bc27dfe9d12510741cebfb3dae1f, endpoint_id=1, cluster_id=8, command=step, args=[1, 51, 10]>

2021-05-25 20:45:01 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=CLUSTER_COMMAND manufacturer_specific=False is_reply=False disable_default_response=False> manufacturer=None tsn=60 command_id=2>
2021-05-25 20:45:01 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] ZCL request 0x0002: [0, 51, 10]
2021-05-25 20:45:01 DEBUG (MainThread) [zigpy.zcl] [0x943a:1:0x0008] No handler for cluster command 2
2021-05-25 20:45:01 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event zha_event[L]: device_ieee=60:a4:23:ff:fe:db:30:83, unique_id=60:a4:23:ff:fe:db:30:83:1:0x0008, device_id=87b8bc27dfe9d12510741cebfb3dae1f, endpoint_id=1, cluster_id=8, command=step, args=[0, 51, 10]>


FYI request on the repo:

1 Like

I think the mapping goes somewhere like this:

        (SHORT_PRESS, BUTTON_3): {
            COMMAND: COMMAND_STEP,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
            ARGS: [0, 51, 10],
        },
        (SHORT_PRESS, BUTTON_4): {
            COMMAND: COMMAND_STEP,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
            ARGS: [1, 51, 10],
        },		
[...]

According to the zigbee2mqtt code, “Hold” would be COMMAND_MOVE

I too have this switch and don’t even know where to start. Did anyone figure this out?

Got my switch in the mail today, realized it’s not working as it should, and thus I ended up here. Anything I can do to help? Just let me know, I know myself around python quite well!
I ripped out the previous switch so I’m very eager to do whatever it takes to get this 4-way switch to work!

5 Likes

Did anyone have any luck with this?

I have tried the quirk above and button 3 & 4 send a zha_event for long and short press. But button 1 & 2 just turn off and on the device’s entity

From HA? It cannot be automagical :wink:

Sorry I am quite new to HA, I didn’t completely understand what you meant.

With the comment above I meant that even without the quirk the default action of button 1 was turning on Test on_off and button 2 would turn the entity off. With the quirk the default action is unchanged.

image

I just keep checking back hoping. This sort of thing is above my current knowledge. Maybe I can look into quirks.

1 Like

Anyone had luck with this?
I’m still struggling to my it works. The only way I managed to used it is with NodeRed.

3 Likes

Same here, only the top & bottom right buttons respond in NodeRED through zha_events.

Let’s work together to make this into the official quirk db, shall we?
I don’t have the device myself.

@quentinn Would you be so kind as to post the latest version of your quirk, please
@all Never did it myself but you can now create custom quirks in HA.

The steps as I understand them:

  1. Create a custom quirk dir in HA, e.g., /config/custom_zha_quirks
  2. In configuration.yaml, point to this directory:
zha:
  custom_quirks_path: /config/custom_zha_quirks/
  1. in this directory, create a file ts004f.py with content of the quirk that will be posted

If anyone has actual experience with custom quirks, please shout if I say something stupid (@Hedda ?)

3 Likes

Hello
sorry did not have time to focus on this.

The problem I think comes from the function referenced in the quirk replacement TuyaSmartRemoteOnOffCluster which cannot handle the specific events of this type of switch.

here is my quirk

"""Tuya 4 Button Remote TS004F"""

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, OnOff, Identify, Ota, LevelControl, PowerConfiguration, Time, Groups, Scenes
from zigpy.zcl.clusters.lightlink import LightLink

from zhaquirks.const import (
    BUTTON_1,
    BUTTON_2,
    BUTTON_3,
    BUTTON_4,
    COMMAND,
    DEVICE_TYPE,
    DOUBLE_PRESS,
    ENDPOINT_ID,
    ENDPOINTS,
    INPUT_CLUSTERS,
    LONG_PRESS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    SHORT_PRESS,
)
from zhaquirks.tuya import TuyaSmartRemoteOnOffCluster


class Tuya4NewButtonTriggers:
    """Tuya 4-button New version remote device triggers."""

    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: 1, COMMAND: SHORT_PRESS},
        (LONG_PRESS, BUTTON_2): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS},
        (DOUBLE_PRESS, BUTTON_2): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS},
        (SHORT_PRESS, BUTTON_3): {ENDPOINT_ID: 1, COMMAND: SHORT_PRESS},
        (LONG_PRESS, BUTTON_3): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS},
        (DOUBLE_PRESS, BUTTON_3): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS},
        (SHORT_PRESS, BUTTON_4): {ENDPOINT_ID: 1, COMMAND: SHORT_PRESS},
        (LONG_PRESS, BUTTON_4): {ENDPOINT_ID: 1, COMMAND: LONG_PRESS},
        (DOUBLE_PRESS, BUTTON_4): {ENDPOINT_ID: 1, COMMAND: DOUBLE_PRESS},
    }


class TuyaSmartRemote004F(CustomDevice, Tuya4NewButtonTriggers):
    """Tuya 4-button New version remote device."""

    signature = {
        # "node_descriptor": "NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=128, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=0, *allocate_address=True, *complex_descriptor_available=False, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False, *is_valid=True, *logical_type=<LogicalType.EndDevice: 2>, *user_descriptor_available=False)",
        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=260, device_version=1, input_clusters=[0, 1, 3, 4, 6, 4096], output_clusters=[25, 10, 3, 4, 5, 6, 8, 4096])
        MODELS_INFO: [("_TZ3000_xabckq1v", "TS004F")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    OnOff.cluster_id,
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }
    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    TuyaSmartRemoteOnOffCluster,
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaSmartRemoteOnOffCluster,
                    LevelControl.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }


class ZemiSmartRemote004F(CustomDevice, Tuya4NewButtonTriggers):
    """Tuya 4-button New version remote device."""

    signature = {
        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=260, device_version=1, input_clusters=[0, 1, 3, 4, 6, 4096], output_clusters=[25, 10, 3, 4, 5, 6, 8, 4096])
        MODELS_INFO: [("_TZ3000_xabckq1v", "TS004F")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    OnOff.cluster_id,
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }
    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    TuyaSmartRemoteOnOffCluster,
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaSmartRemoteOnOffCluster,
                    LevelControl.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }
1 Like

Thanks.
Am I correct that “ZemiSmartRemote004F” and “TuyaSmartRemote004F” are duplicates?

Yes. It is a copy of the other template. I’ve kept the architecture.