Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Device Support Request] Tuya TS0001 relay #1118

Closed
PlusPlus-ua opened this issue Nov 1, 2021 · 33 comments · Fixed by #1152
Closed

[Device Support Request] Tuya TS0001 relay #1118

PlusPlus-ua opened this issue Nov 1, 2021 · 33 comments · Fixed by #1152

Comments

@PlusPlus-ua
Copy link
Contributor

Is your feature request related to a problem? Please describe.
Just received Tuya TS0001 relay,
image
image
https://www.aliexpress.com/item/1005002482791975.html

It hasn't quirk, so works just basically.

In Tuya Smart application, it has power outage behavior and external switch type settings. The first setting is already implemented for plugs TS011F and TS0121, so it could implemented without problems. Switch type setting haven't been implemented yet.

Here is a screenshot from Tuya Smart application:
image

Describe the solution you'd like
The external switch type attribute could be added.

Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x010a",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0xe000",
        "0xe001"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZ3000_ark8nv4y",
  "model": "TS0001",
  "class": "ts011f_plug.Plug_0001"
}

Additional context
@MattWestb may be you know attribute id for external switch type?

@MattWestb
Copy link
Contributor

I have making one PR for adding back light for some switches and also adding changing some switches sending light commands or clicks that all is on the on/off cluster but is not being merged.

I have funding that some tuya devices is using switch mode on cluster 0xE001 zigpy/zigpy#823 (comment) but your devices is not having that.

So it can it have implanting it on the On/Off cluster but we dont knowing what attribute tuya is using or they is using it on the 0xE000 cluster but have hidden the cluster and must being added in the quirk for working or they have doing it in one other not known way.

Then you is having one tuya ZBGW and can controlling the device it wold being great if you can sniffing it so we can see how they is doing it if you is having some device for doing sniffing (TI CC-2531 or one EM35X / EFR21MG with NCP firmware).

@PlusPlus-ua
Copy link
Contributor Author

I have funding that some tuya devices is using switch mode on cluster 0xE001 zigpy/zigpy#823 (comment) but your devices is not having that.

No, mine device has 0xE001 cluster. It looks like 0xD030 attribute will make a trick, I'll check it.

@PlusPlus-ua
Copy link
Contributor Author

PlusPlus-ua commented Nov 1, 2021

I've posted wrong ZigBee information after applying my quick and dirty quirk. Here is raw information:

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0100",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0x0004",
        "0x0005",
        "0x0006",
        "0xe000",
        "0xe001"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "242": {
      "profile_id": 41440,
      "device_type": "0x0061",
      "in_clusters": [],
      "out_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "_TZ3000_ark8nv4y",
  "model": "TS0001",
  "class": "zigpy.device.Device"
}

@MattWestb
Copy link
Contributor

MattWestb commented Nov 1, 2021

OK i was missing that then you was not having it in the replace in the quirk so that is great !!

Try implanting it like its done with the power state and i think it will working OK.

My intention is getting it in tuya INI and then adding it to TS011F and TS0121 and also the TS001X quirk but i dont have any one for testing it and the devs have not merger it.

This is interesting !!!

And i think its needed on new quirk TS000X for your device :-)))

@MattWestb
Copy link
Contributor

Then you is making the new 0xE001 you can doing some extra attributes like 0x03, 0x04 and so on and looking if you is getting response from the device and if the function is changed.

@PlusPlus-ua
Copy link
Contributor Author

PlusPlus-ua commented Nov 1, 2021

I've tried to make it in this way

class TuyaSwitchMode(t.enum8):
    """Tuya power on state enum."""

    Toggle = 0x00
    State = 0x01 
    Momentary = 0x02


class TuyaSwitchModeCluster(CustomCluster):
    """Tuya manufacturer specific cluster 57345."""

    name = "Tuya Manufacturer Specific"
    cluster_id = 0xE001
    ep_attribute = "tuya_is_pita_1"
    attributes.update({0xD030: ("switch_mode", TuyaSwitchMode)})

but received an error:

  File "/config/zhaquirks/ts011f_plug.py", line 52, in TuyaSwitchModeCluster
    attributes.update({0xD030: ("switch_mode", TuyaSwitchMode)})
NameError: name 'attributes' is not defined

where I have to take attributes?

@MattWestb
Copy link
Contributor

attributes.update({0xD030: ("switch_mode", TuyaSwitchMode)})
Attribute must being imported or defined.

I looking how it was made in the first implementation before i was moving it to tuya INIT.

@MattWestb
Copy link
Contributor

from the original implementation in the TS1021:

class PowerOnState(t.enum8):
    """Tuya power on state enum."""

    Off = 0x00
    On = 0x01
    LastState = 0x02


class OnOffRestorePowerCluster(CustomCluster, OnOff):
    """Tuya on off cluster with restore state."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8002: ("power_on_state", PowerOnState)})

that is not doing one new cluster but is updating the on/off cluster.
The TS130F is doing one new cluster and adding attributes like this:

class TuyaWithBacklightOnOffCluster(CustomCluster):
    """TuyaSmartCurtainOnOffCluster: fire events corresponding to press type."""

    cluster_id = OnOff.cluster_id

    LIGHT_MODE_1 = {0x8001: 0}
    LIGHT_MODE_2 = {0x8001: 1}
    LIGHT_MODE_3 = {0x8001: 2}

    attributes = {0x8001: ("backlight_mode", t.enum8)}

I think the latest is nor like you like to have and changing the cluster_id = OnOff.cluster_id to cluster_id = 0xE001

Good naming you can do later the most importent is you is getting the function working.

@PlusPlus-ua
Copy link
Contributor Author

I can confirm - it works:

class TuyaSwitchMode(t.enum8):
    """Tuya switch mode enum."""

    Toggle = 0x00
    State = 0x01 
    Momentary = 0x02


class TuyaSwitchModeCluster(CustomCluster):
    """Tuya switch mode cluster 57345."""

    name = "Tuya Manufacturer Specific"
    cluster_id = 0xE001
    ep_attribute = "tuya_is_pita_1"
    attributes = {0xD030: ("switch_mode", TuyaSwitchMode)}

@MattWestb
Copy link
Contributor

GREAT !!

Wot is the ep_attribute = "tuya_is_pita_1" doing ?
I think its one cosmic description but i dont knowing, can you looking because i like have better names on things.

Then you have making it working and merger the PR i can moving it to the tuya INI and only using linking in your quirk but you can doing it from the beginning if you like but i ts little trickier edeting the INIT then it must being done in the HA container.

Great work done !!

@PlusPlus-ua
Copy link
Contributor Author

Wot is the ep_attribute = "tuya_is_pita_1" doing ?

Have no idea. I just respect existing code and use the rule "don't touch anything"

@PlusPlus-ua
Copy link
Contributor Author

PlusPlus-ua commented Nov 1, 2021

BTW, in both ts011f_plug.py and ts0121_plug.py have wrong cluster numbers and wrong device_type in "# <SimpleDescriptor" comments. device_type must be 266. In input_clusters number 9 is needless.

@MattWestb
Copy link
Contributor

Its some quirks that is no fitting at all (i think the TS113F is one of them) and that is very bad then trying adding other devices with little different cluster settings.

Look little how other is made and copy it and changing the information its the best.

The profiles / device type you is can finding here: https://github.com/zigpy/zigpy/blob/dev/zigpy/profiles/zha.py

You must finding one good name for the "new made cluster" that all other devices can using in the future !!!

@MattWestb
Copy link
Contributor

I was thinking putting somthing like this in tuya INIT:

class TuyaSwitchMode(t.enum8):
    """Tuya switch mode enum."""

    Toggle = 0x00
    State = 0x01 
    Momentary = 0x02


class TuyaZBSwitchModeCluster(CustomCluster):
    """Tuya switch mode cluster 57345."""

    name = "Tuya Switch Mode Cluster"
    cluster_id = 0xE001
    ep_attribute = "Tuya_Switch_Mode_Cluster"
    attributes = {0xD030: ("switch_mode", TuyaSwitchMode)}

But i dont knowing if its working OK with initiating the cluster.

@jacekk015 you is knowing how to do it right.

I like adding one new tuya cluster to INIT that can sending and receiving this attributes and its looks working OK in local quirks.
But i think it shall have some initiation for working OK.
Do you having some suggestions how to do it right ??

Thanks in advance !!!

@PlusPlus-ua
Copy link
Contributor Author

There already is SwitchMode enum in INIT. I think it's better to name it ExternalSwitchType:

class ExternalSwitchType(t.enum8):
    """Tuya external switch type enum."""

    Toggle = 0x00
    State = 0x01 
    Momentary = 0x02


class TuyaZBExternalSwitchTypeCluster(CustomCluster):
    """Tuya External Switch Type Cluster"""

    name = "Tuya External Switch Type Cluster"
    cluster_id = 0xE001
    ep_attribute = "tuya_external_switch_type"
    attributes = {0xD030: ("external_switch_type", ExternalSwitchType)}

@PlusPlus-ua
Copy link
Contributor Author

And maybe it's better to move constant 0xE001 to constants section, right before TUYA_CLUSTER_ID = 0xEF00

@MattWestb
Copy link
Contributor

MattWestb commented Nov 11, 2021

I think its very good not mixing the variables and getting strange collisions with the naming !!
Thanks for pointing it out and fixing it !!

I trying making all "noraml" tuya Zigbee with names so easy can see its tuya and Zigbee and not the DP devices things belonging.

I was thinking putting the 0xE001 early in the INIT after this:

# ---------------------------------------------------------
# Tuya Custom Cluster ID
# ---------------------------------------------------------
TUYA_CLUSTER_ID = 0xEF00
# ---------------------------------------------------------

@MattWestb
Copy link
Contributor

In line 23:

TUYA_SWITCH_MODE_CLUSTER_ID = 0xE001

and in the new cluster:

    cluster_id = TUYA_SWITCH_MODE_CLUSTER_ID

Looks little long but i think its better doing as the original is being done.
Perhaps with external but then its being very long.

@PlusPlus-ua
Copy link
Contributor Author

I think, anyway, it should be TYPE not MODE

@MattWestb
Copy link
Contributor

More users have the same problem like you but 3 times more #1145 :-)

@MattWestb
Copy link
Contributor

I have making some adding in INIT and moved both "PITA" clusters there:

# ---------------------------------------------------------
# Tuya Custom Cluster ID
# ---------------------------------------------------------
TUYA_CLUSTER_ID = 0xEF00
TUYA_CLUSTER_E000_ID = 0xE000
TUYA_CLUSTER_E001_ID = 0xE001
# ---------------------------------------------------------

And adding definitions for both:

# Tuya Zigbee Cluster 0xE000 Implementation
class TuyaZBE000Cluster(CustomCluster):
    """Tuya manufacturer specific cluster 57344."""

    name = "Tuya Manufacturer Specific"
    cluster_id = TUYA_CLUSTER_E000_ID
    ep_attribute = "tuya_is_pita_0"


# Tuya Zigbee Cluster 0xE001 Implementation
class ExternalSwitchType(t.enum8):
    """Tuya external switch type enum."""

    Toggle = 0x00
    State = 0x01
    Momentary = 0x02


class TuyaZBExternalSwitchTypeCluster(CustomCluster):
    """Tuya External Switch Type Cluster"""

    name = "Tuya External Switch Type Cluster"
    cluster_id = TUYA_CLUSTER_E001_ID
    ep_attribute = "tuya_external_switch_type"
    attributes = {0xD030: ("external_switch_type", ExternalSwitchType)}

The INIT is one updated version with renamed cluster so need also updating the ts011f_plug.py and ts0121_plug.py in the container or ZHA is not loading.

And one new ts000x.py with your relay plus the 3 gang in the new issue.

The TS011F Its loading in my test and production system and i can controlling the power restore state and back light (but not back light shown on the device like yours) but is not having switch mode implanted but other user have TS011F devices that having that.

Can you testing if i have making your device OK and its working and also taking one fast look on the 3 gang if its looks OK then i can testing it on the user.

Also more feedback on the copy and pace code is very welcome !!

custom_zha_quirks.zip

@PlusPlus-ua
Copy link
Contributor Author

Can you testing if i have making your device OK and its working and also taking one fast look on the 3 gang if its looks OK then i can testing it on the user.

Unfortunately, I'm not able to check it. There is a problem with import. Statement:

from zhaquirks.tuya import (

causes error since in original zha-device-handlers/zhaquirks/tuya/__init__.py not defines such classes. I've tried to change import to

from . import (

but the error is "ImportError: attempted relative import with no known parent package" in such case.

@MattWestb
Copy link
Contributor

In witch quirk or is it in the INIT that is giving the error ?
I was getting somthing like that then copy the INIT to zhquirk and not zhaquirk/tuya.
But it was working OK in my production system.
The INIT must being copied into the HA container or its cant being imported of the quirks (both local and updated in the container).

@PlusPlus-ua
Copy link
Contributor Author

I've tried it in custom_quirks. Ok, I'll try to work with HA container

@MattWestb
Copy link
Contributor

MattWestb commented Nov 12, 2021

TS011F and TS0121 must being patched for the new named (in the new INIT) of the power state cluster in the container. After that you can have copy of this in the custom folder (I was first deleting them in the container and its working 2).

@PlusPlus-ua
Copy link
Contributor Author

Yes, my TS0001 works well with this code. Only one issue.

Original device type is zha.DeviceType.ON_OFF_LIGHT. If we keep it in replacement section, there are two entities:

image

I've resolved it by changing it in replacement to zha.DeviceType.ON_OFF_PLUG_IN_UNIT:

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_PLUG_IN_UNIT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

With this change, there is only one entity.

@PlusPlus-ua
Copy link
Contributor Author

@MattWestb, is it possible to expose these attributes as entities with config category in ZHA?

@MattWestb
Copy link
Contributor

I putting it in the replace and then testing the 3 gang on the new user :-))

ZHA is showing some attributes like battery voltage, type and number of batteries in the battery card (ZHA have starting saving all attributes in the device DB so the system is having them).
If like having more information you need doing one custom card in HA or making one extended function one in ZHA.

@MattWestb
Copy link
Contributor

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_PLUG_IN_UNIT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },

@MattWestb
Copy link
Contributor

I think you can doing custom quirks that is exposed as switched and can sending attribute thru bus and getting its status from the bus like is made in tuya TRVs.
But it must being made as custom quirks then its never going in the main ZHA. then its braking the Zigbee standard.

Or you is implanting one nice device card for ZHA :-))

@MattWestb
Copy link
Contributor

Merged :-))

@unaiur
Copy link

unaiur commented Dec 8, 2021

You got two entities but one is disabled. When you play with settings that affect the entity domain (light vs switch in this case), HA creates new entities for you and the old ones are left disabled. You can delete them and will not be created again unless you change the zha.Devicetype again.

In fact, zha.DeviceType.ON_OFF_LIGHT is the right one becase it was the original device type and what HA is using in current installations and because the device is designed to handle lights.

Yes, my TS0001 works well with this code. Only one issue.

Original device type is zha.DeviceType.ON_OFF_LIGHT. If we keep it in replacement section, there are two entities:

image

I've resolved it by changing it in replacement to zha.DeviceType.ON_OFF_PLUG_IN_UNIT:

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_PLUG_IN_UNIT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
        },
    }

With this change, there is only one entity.

@NdK73
Copy link

NdK73 commented Nov 16, 2022

There is a way to set the externalswitchtype w/o editing HA code.

From "manage Zigbee device", clusters tab, select "TuyaZBExternalSwitchTypeCluster (Endpoint id: 1, Id: 0xe001, Type: in)", "Attributes" tab, "external_switch_type (id: 0xd030)".
Click "Read attribute" button and you should get "ExternalSwitchType.Toggle". Replace it with "2" and click "Write attribute".

Now, clicking "Read attribute" should give "ExternalSwitchType.Momentary".

A drop down for noobs like me would be perfect, but at least it's doable :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants