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.
Apache License 2.0
743 stars 679 forks source link

[Device Support Request] Tuya Smart Plug TS011F _TZ3000_5f43h46b #1442

Closed jasonwragg closed 1 year ago

jasonwragg commented 2 years ago

Is your feature request related to a problem? Please describe. Plug has the following in zigbee2mqtt Screenshot 2022-03-23 at 12 42 23 Screenshot 2022-03-23 at 12 43 15

{
    "child_lock": "UNLOCK",
    "indicator_mode": "off",
    "linkquality": 63,
    "power_outage_memory": "restore",
    "state": "ON"
}

Describe the solution you'd like Add the missing option to ZHA

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",
        "0x0702",
        "0x0b04",
        "0xe000",
        "0xe001"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZ3000_5f43h46b",
  "model": "TS011F",
  "class": "zhaquirks.tuya.ts011f_plug.Plug"
}
**Additional context**
MattWestb commented 2 years ago

What functions is missing / not working in ZHA ? The only thing not implanted in ZHA is the children-lock (that looks not being implanted in Z2M 2 then its no trace of code in there system of it). Its looks like power, current, voltage and energy is not working as is shall in Z2M.

jasonwragg commented 2 years ago

The child lock, power restore (power_outage_memory), power button light control.

From: MattWestb @.> Reply to: zigpy/zha-device-handlers @.> Date: Wednesday, 23 March 2022 at 16:21 To: zigpy/zha-device-handlers @.> Cc: Jason Wragg @.>, Author @.***> Subject: Re: [zigpy/zha-device-handlers] [Device Support Request] Tuya Smart Plug TS011F _TZ3000_5f43h46b (Issue #1442)

What functions is missing / not working in ZHA ? The only thing not implanted in ZHA is the children-lock. Its looks like power, current, voltage and energy is not working as is shall in Z2M.

— Reply to this email directly, view it on GitHubhttps://github.com/zigpy/zha-device-handlers/issues/1442#issuecomment-1076535458, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMU7GI5GPNJ6MD5I2OQYKTLVBNATHANCNFSM5RN5OGCA. You are receiving this because you authored the thread.Message ID: @.***>

MattWestb commented 2 years ago

You have all found functions on the TuyaZBOnOffAttributeCluster: https://github.com/zigpy/zha-device-handlers/blob/039a31f1ca15821e800bdb347eb47fdb02455f31/zhaquirks/tuya/__init__.py#L789-L819 And also switch type on the TuyaZBExternalSwitchTypeCluster: https://github.com/zigpy/zha-device-handlers/blob/039a31f1ca15821e800bdb347eb47fdb02455f31/zhaquirks/tuya/__init__.py#L913-L928 Child lock is not "found" and is not implanted in ZHA or Z2M.

jasonwragg commented 2 years ago

Should i be seeing it in Home Assistant? Screenshot 2022-03-23 at 17 57 35

jasonwragg commented 2 years ago

child lock work in Z2M as I've turn it on (On a different device) and now can't turn it off because I've changed to ZHA Screenshot 2022-03-23 at 17 59 28 A

MattWestb commented 2 years ago

All power measuring looks working OK. The attributes you is finding in "manager cluster" > selecting cluster > selecting attribute you like get or sting.

If you like have switches for then use tamplets switches in HA and connecting them to the attribute you like changing from the GUI or implanting it in ZHA.

You can also looking in the Z2M code and implanting the child-lock if you can finding it there.

MattWestb commented 2 years ago

I have founding the implementation in Z2M: https://github.com/Koenkk/zigbee-herdsman-converters/blob/92d4e6f50c4b600d631b4b6b139b997d1528e97e/converters/toZigbee.js#L6130-L6133 You can implanting the attribute in tuya INIT on the TuyaZBOnOffAttributeCluster i was showing before.

jasonwragg commented 2 years ago

Like this? [Text Description automatically generated] From: MattWestb @.> Reply to: zigpy/zha-device-handlers @.> Date: Wednesday, 23 March 2022 at 18:23 To: zigpy/zha-device-handlers @.> Cc: Jason Wragg @.>, Author @.***> Subject: Re: [zigpy/zha-device-handlers] [Device Support Request] Tuya Smart Plug TS011F _TZ3000_5f43h46b (Issue #1442)

I have founding the implementation in Z2M: https://github.com/Koenkk/zigbee-herdsman-converters/blob/92d4e6f50c4b600d631b4b6b139b997d1528e97e/converters/toZigbee.js#L6130-L6133 You can implanting the attribute in tuya INIT on the TuyaZBOnOffAttributeCluster i was showing before.

— Reply to this email directly, view it on GitHubhttps://github.com/zigpy/zha-device-handlers/issues/1442#issuecomment-1076675683, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMU7GI75AESURGVGVOHHAVLVBNO4BANCNFSM5RN5OGCA. You are receiving this because you authored the thread.Message ID: @.***>

jasonwragg commented 2 years ago

Screenshot 2022-03-23 at 18 47 55

MattWestb commented 2 years ago

First the 0x8000 shall being first for not braking isort.

I have asking and very likely its one (t.Bool) so making it Locked and Unlocked for 0 and 1 (or 1 and 0) and testing if its working OK.

You need doing the changed in the HA docker container or the quirks cant "reading" it.

MattWestb commented 2 years ago

If you is getting it working OK its one more attribute that we have "found" but not implanted that your device can having 0x8003. Look in our cluster matrix https://github.com/zigpy/zigpy/discussions/823#discussioncomment-1539469 and you finding it on the OnOff cluster for tuya Zigbee devices.

Some user of TS011F with power reading is having problems that its power of its self but i can being over current protection or hardware problem but can being good implanting it for the future.

javicalle commented 2 years ago

Maybe you can try with: (no, you can't. see: https://github.com/zigpy/zha-device-handlers/issues/1442#issuecomment-1076863920)

class ChildLock(t.Bool):
    """Tuya child lock states."""

    LOCK = True  # maybe 1 or 0x01
    UNLOCK = False  # maybe 0 or 0x00

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", ChildLock)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})

Not sure how to wrap the t.Bool. You can try with diferent values. The ChildLock is more user friendly, but if give more truoble would be enough with:

    attributes.update({0x8000: ("child_lock", t.Bool)})

edit: fix class description & boolean values

MattWestb commented 2 years ago

Its looks nicer in GUI if reading the state of the attribute if using "normal" writing that is done with the other attribute on the same cluster. ChildLock: Locked and ChildLock: Unlocked

I think """Tuya power on state enum.""" is the proposed looking better ;-)) (Corrupted clipboard buffer bug ?)

I think for testing is attributes.update({0x8000: ("child_lock", t.Bool)}) added in the local quirk its easiest way see if its working OK or not with the device. Setting and getting 0 or 1 from the attribute its working then moving it to INIT.

MattWestb commented 2 years ago

If tuya have doing it little standard it shall being 0 and 1 in the reading the attribute and also writing it.

Was testing reading one bool from one IKEA CWS3 lights color cluster:

Attributes of the selected cluster
color_loop_active (id: 0x4002)

Value
0

And active:

Attributes of the selected cluster
color_loop_active (id: 0x4002)

Value
1
javicalle commented 2 years ago

It seems that Bool can't be extended.

You can keep the definition without the auxiliar class or try with something like:

class ChildLock(t.uint8_t):
    """Tuya power on state enum."""

    LOCK = 1
    UNLOCK = 0

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", ChildLock)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})

Refs:

jasonwragg commented 2 years ago

I seem to be able to get the attribute value for child lock but not set it.

If I wanted to add a switch for an attribute in Home Assistant what would I use as the value_template for any of the above ?

javicalle commented 2 years ago

I seem to be able to get the attribute value for child lock but not set it.

Which value are you trying to set? I would try with 1/0 Any related traces in your logs?

jasonwragg commented 2 years ago

0/1 [homeassistant.components.zha.api] Set attribute for: cluster_id: [6] cluster_type: [in] endpoint_id: [1] attribute: [32768] value: [0] manufacturer: [None] response: [[[WriteAttributesStatusRecord(status=<Status.INVALID_DATA_TYPE: 141>, attrid=32768)]]]

[homeassistant.components.zha.core.device] 0x574F: set: 1 for attr: 32768 to cluster: 6 for ept: 1 - res: [[WriteAttributesStatusRecord(status=<Status.INVALID_DATA_TYPE: 141>, attrid=32768)]]

javicalle commented 2 years ago

Can you try with True/False?

If it's not working, change the declaration to:

    attributes.update({0x8000: ("child_lock", t.Bool)})

and try again with 0/1 and True/False

jasonwragg commented 2 years ago

Still getting

2022-03-24 11:38:32 DEBUG (MainThread) [homeassistant.components.zha.api] Read attribute for: cluster_id: [6] cluster_type: [in] endpoint_id: [1] attribute: [32768] manufacturer: [None] response: [0] failure: [{}],
2022-03-24 11:38:38 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=zha, service=set_zigbee_cluster_attribute, service_data=ieee=a4:c1:38:e0:b5:a5:bb:c6, endpoint_id=1, cluster_id=6, cluster_type=in, attribute=32768, value=True>
2022-03-24 11:38:38 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0x574F](TS011F): set: True for attr: 32768 to cluster: 6 for ept: 1 - res: [[WriteAttributesStatusRecord(status=<Status.INVALID_DATA_TYPE: 141>, attrid=32768)]]
2022-03-24 11:38:38 DEBUG (MainThread) [homeassistant.components.zha.api] Set attribute for: cluster_id: [6] cluster_type: [in] endpoint_id: [1] attribute: [32768] value: [True] manufacturer: [None] response: [[[WriteAttributesStatusRecord(status=<Status.INVALID_DATA_TYPE: 141>, attrid=32768)]]]
javicalle commented 2 years ago

Also with the code changed? Have you deleted the python cache (__pycache__ folder)? Can you enable the zigpy.zcl debug logs?

jasonwragg commented 2 years ago

Still just get:

2022-03-27 19:21:58 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xCB93](TS011F): failed to set attribute: value: 0 attribute: 32768 cluster_id: 6 endpoint_id: 1 [0xcb93:1:0x0006]: Message send failure
2022-03-27 19:21:58 DEBUG (MainThread) [homeassistant.components.zha.api] Set attribute for: cluster_id: [6] cluster_type: [in] endpoint_id: [1] attribute: [32768] value: [0] manufacturer: [None] response: [None]
javicalle commented 2 years ago

These logs are diferent. Good. Have you tried with True and False values?

Can you enable the zigpy.zcl debug logs?

Any of these logs in your traces?

jasonwragg commented 2 years ago

This is the code I'm using

`class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff): """Tuya Zigbee On Off cluster with extra attributes."""

attributes = OnOff.attributes.copy()
attributes.update({0x8000: ("child_lock", ChildLock)})
attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
attributes.update({0x8002: ("power_on_state", PowerOnState)})
attributes.update({0x8004: ("switch_mode", t.Bool)})`

I've tried 1/0 and True/False, Its seems to 'get' ok but the set doesn't work.

Is there a way of getting the value in to home assistant, in a sensor or lock entity?

javicalle commented 2 years ago

Can you try with True/False?

If it's not working, change the declaration to:

    attributes.update({0x8000: ("child_lock", t.Bool)})

and try again with 0/1 and True/False

Can you test with the above suggested change for the child_lock attribute?

jasonwragg commented 2 years ago

That's working!

Would it be possible to add that in to home assistant as template lock or switch?

javicalle commented 2 years ago

I have reviewed it again and I believe that it must to work with a helper class.

Could you try again with this code:

class ChildLock(t.Bool):
    """Tuya child lock states."""

    LOCK = t.Bool.true
    UNLOCK = t.Bool.false

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", ChildLock)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})
jasonwragg commented 2 years ago

That doesn't work I get :

TypeError: ChildLock: cannot extend enumeration 'Bool'

javicalle commented 2 years ago

Thanks for testing again.

MattWestb commented 2 years ago

@jasonwragg Try with this 2 versions:

class ChildLock(t.Bool):
    """Tuya child lock states enum."""

    Unlocked = False
    Locked = True

or

class ChildLock(t.Bool):
    """Tuya child lock states enum."""

    Unlocked = 0
    Locked = 1

Also then you can reading the attribute is it 0/1 or True / False the device / system is returning (i think 0/1 then my test color lope was doing that) ? I dont knowing if Python is case sensitive or not but all code is made with True/False what i have seen and it shall not being needing declaring the type 2 or more times in the function (its not German lang !!).

javicalle commented 2 years ago

It seems that the problem is related with extending the t.Bool class that is not allowed.

class ChildLock(t.Bool):

MattWestb commented 2 years ago

Looks some quirks is using it for attribute but Xiaomi is no good reference (its the first PITA before the tuya invasion) but Danfoss is more "normal".Zigbee devices Take one look on: https://github.com/zigpy/zha-device-handlers/blob/93b11d3e48c798c633aab62e084dcc398f4a382a/zhaquirks/danfoss/thermostat.py#L43 But perhaps is not possible doing it with enum :-((

javicalle commented 2 years ago

One last test and I stop bothering. I assure. Would you be so kind as to try this?

class ChildLock(t.enum8):
    """Tuya child lock states."""

    LOCK = t.Bool.true
    UNLOCK = t.Bool.false

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", ChildLock)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})
jasonwragg commented 2 years ago

No problem, I can 'get' the attribute but I can't 'set' it. The get show 'ChildLock.UNLOCK'. I've tried setting with 0/1 & true/false.

I'm running HA core so it easy for me to test.

javicalle commented 2 years ago

Maybe with True/False?

El vie., 1 abr. 2022 23:36, Jason Wragg @.***> escribió:

No problem, I can 'get' the attribute but I can't 'set' it. The get show 'ChildLock.UNLOCK'. I've tried setting with 0/1 & true/false.

I'm running HA core so it easy for me to test.

— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/1442#issuecomment-1086347371, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHUEP7LYLOFWW4XLSKQZIOLVC5T5FANCNFSM5RN5OGCA . You are receiving this because you commented.Message ID: @.***>

jasonwragg commented 2 years ago

Tried that and it didn't work either. :(

javicalle commented 2 years ago

Ok, let's keep the t.Bool. I will try to ask for support with this topic. Is not a rare case and there must be a (easy) way to be done.

Thanks for testing.

javicalle commented 2 years ago

@jasonwragg I have another test to try. Maybe already done but I have not found it. Would you be so kind as to try this?

class ChildLock(t.enum8):
    """Tuya child lock states."""

    LOCK = 1
    UNLOCK = 0

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", ChildLock)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})

I am generating an issue with this matter and I want to be sure that I have exhausted the options.

Thanks in advanced.

jasonwragg commented 2 years ago

No that doesn't work either.

jasonwragg commented 2 years ago

The only one that works is:

class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff):
    """Tuya Zigbee On Off cluster with extra attributes."""

    attributes = OnOff.attributes.copy()
    attributes.update({0x8000: ("child_lock", t.Bool)})
    attributes.update({0x8001: ("backlight_mode", SwitchBackLight)})
    attributes.update({0x8002: ("power_on_state", PowerOnState)})
    attributes.update({0x8004: ("switch_mode", SwitchMode)})
github-actions[bot] commented 2 years ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

evlo commented 2 years ago

I have TS011Fs from about 10 different "manufacturers" and non is showing option to set backlight or status indicator as I would call it, in HA if I'm using ZHA, i searched the issues and quirks, but found nothing, I think I must be missing something basic.

image image

I don't understand what these zigbee clusters are at all, but it looks interesting.

IE. setting like this image will disable the indicator light

MattWestb commented 2 years ago

Then tuya have implanting it not Zigbee standard way we have getting it working on cluster level and you have founding the right place.doing it. My LIDL plug have ON, Inverted and Off but some other device have different or no function = tuya have making it different and we dont knowing it or its not implanted in the device.

evlo commented 2 years ago

I thought quirks are to support these manufacturers deviations from the standard, so even if I tried quirk can't be done?

Asking more for possible needs in the future, not these devices. For me the current implementation of "settings" is ok.

MattWestb commented 2 years ago

The quirk is making devices Zigbee standard if they is not and ZHA is making GUI handles for Zigbee command.

tuya MCU and most "normal" Zigbee device is -999 % Zigbee standard and using commands that cant being converted to Zigbee standard like back light mode cant being converted to Zigbee standard then its dont have command for that in the standard.

We have trying getting extra functionality in ZHA for this devices in the ZHA GUI but have getting one no way so not possible.

dmulcahey commented 2 years ago

This is no longer the case. See https://github.com/home-assistant/core/pull/79106 as an example. The functionality gets implemented in ZHA and not in quirks though.

evlo commented 2 years ago

OT question: do the inovelli switches react every time to the press? Does it use microswitches? Seems like pretty nice options. Does it have option to "detach" relay from the button press?

MattWestb commented 2 years ago

@dmulcahey Is it one time map for implanting the extra functions that we have made in "normal" Zigbee devices like power on state, Backlight mode and switch mode etc in ZHA GUI ?

It being one great enchaining the user experiences in ZHA and tuya device is the most used of our user today and for long time forward.

javicalle commented 2 years ago

I will try to take a look at this in the next days.

evlo commented 2 years ago

https://github.com/zigpy/zha-device-handlers/issues/1396

Super weird behaviour for me - if i have plug in any other mode then default - light on when on, It cuts power after a while, but switch in HA says it is ON.

It might be just bad hw piece, but then it is even weirder that it does not have this issue in default mode.

There is no relay click, but power just stops, so that leads me more towards HW fault. But then it also stops reacting to On/Off commands from HA. It does NOT show as unavailable in HA - even when I have it unplugged for an hour. Also not possible to even put plug into pairing mode. So I kinda wonder if anyone else had this experience.

And if the wrong setting for that cluster might have caused the issues.