Closed jonnylangefeld closed 2 years ago
I suggest you to remove your quirk and post the 'original' device signature. The one you have posted is with the quirk applied. Also can be useful to attach the logs when you operate the physical device. Enable debug logs as described here: https://www.home-assistant.io/integrations/zha/#debug-logging
Thanks so much for getting back to me!
Ah I didn't realize that was the device signature with the quirk enabled. I ran rm zhaquirks/tuya/ts110e.py
and restarted home assistant. As expected, the quirk doesn't show in the home assistant UI:
The device signature looks pretty close to what I originally posted, just the last line is different. It says
"class": "zigpy.device.Device"
now:
{
"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": "0x0101",
"in_clusters": [
"0x0000",
"0x0004",
"0x0005",
"0x0006",
"0x0008",
"0xe001"
],
"out_clusters": [
"0x000a",
"0x0019"
]
},
"242": {
"profile_id": 41440,
"device_type": "0x0061",
"in_clusters": [],
"out_clusters": [
"0x0021"
]
}
},
"manufacturer": "_TZ3210_ngqk6jia",
"model": "TS110E",
"class": "zigpy.device.Device"
}
I also activated the logs (thanks for the link) and got these logs when clicking the switch on the home assistant UI to 'off':
2022-03-07 01:48:32 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_off, service_data=entity_id=light.kitchen_backsplash_2_level_on_off>
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=6, TSN=39, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x01\x27\x00')
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=39)
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=6, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=75, SecurityUse=<Bool.false: 0>, TimeStamp=647701, TSN=0, Data=b'\x18\x27\x0B\x00\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0006] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=39 command_id=Command.Default_Response>
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=6, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=75, SecurityUse=<Bool.false: 0>, TimeStamp=647903, TSN=0, Data=b'\x08\x63\x0A\x00\x00\x10\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0006] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=99 command_id=Command.Report_Attributes>
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0006] ZCL request 0x000a: [[Attribute(attrid=0, value=<TypeValue type=Bool, value=Bool.false>)]]
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0006] Attribute report received: on_off=0
2022-03-07 01:48:32 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=light.kitchen_backsplash_2_level_on_off, old_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=201, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:42:40.532954+00:00>, new_state=<state light.kitchen_backsplash_2_level_on_off=off; supported_color_modes=['brightness'], off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:48:32.570891+00:00>>
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=6, TSN=99, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x63\x0B\x0A\x00')
2022-03-07 01:48:32 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0006]: executed 'off' command with args: '()' kwargs: '{}' result: [0, <Status.SUCCESS: 0>]
2022-03-07 01:48:32 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned off: [0, <Status.SUCCESS: 0>]
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-07 01:48:32 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=99)
Then I used the home assistant UI to slide the brightness to 49 and got these logs:
2022-03-07 01:56:22 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_on, service_data=entity_id=light.kitchen_backsplash_2_level_on_off, brightness_pct=49>
2022-03-07 01:56:22 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=40, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x01\x28\x04\x7D\x01\x00')
2022-03-07 01:56:22 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-07 01:56:22 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=40)
2022-03-07 01:56:22 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=75, SecurityUse=<Bool.false: 0>, TimeStamp=14300235, TSN=0, Data=b'\x18\x28\x0B\x04\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-07 01:56:22 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=40 command_id=Command.Default_Response>
2022-03-07 01:56:22 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: executed 'move_to_level_with_on_off' command with args: '(125, 1)' kwargs: '{}' result: [4, <Status.SUCCESS: 0>]
2022-03-07 01:56:22 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned on: {'move_to_level_with_on_off': [4, <Status.SUCCESS: 0>]}
2022-03-07 01:56:22 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=light.kitchen_backsplash_2_level_on_off, old_state=<state light.kitchen_backsplash_2_level_on_off=off; supported_color_modes=['brightness'], off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:48:32.570891+00:00>, new_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=125, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:56:22.649522+00:00>>
Only interesting thing I can find in the logs is that the off command shows something like brightness=201
and the brightness command shows something like brightness=125
. Maybe all the brightnesses ever set are over 100?
Hmm inspecting this closer I don't think the problem is that the brightness is over 100. It seems like brightness is a scale from 0 to 255. Like when I slide the slider to 2, there is a
executed 'move_to_level_with_on_off' command with args: '(5, 1)'
full logs for that:
2022-03-07 02:03:23 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_on, service_data=entity_id=light.kitchen_backsplash_2_level_on_off, brightness_pct=2>
2022-03-07 02:03:23 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=44, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x01\x2C\x04\x05\x01\x00')
2022-03-07 02:03:23 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-07 02:03:23 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=44)
2022-03-07 02:03:23 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=72, SecurityUse=<Bool.false: 0>, TimeStamp=9161317, TSN=0, Data=b'\x18\x2C\x0B\x04\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-07 02:03:23 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=44 command_id=Command.Default_Response>
2022-03-07 02:03:23 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: executed 'move_to_level_with_on_off' command with args: '(5, 1)' kwargs: '{}' result: [4, <Status.SUCCESS: 0>]
2022-03-07 02:03:23 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned on: {'move_to_level_with_on_off': [4, <Status.SUCCESS: 0>]}
2022-03-07 02:03:23 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=light.kitchen_backsplash_2_level_on_off, old_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=252, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:56:22.649522+00:00>, new_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=5, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:56:22.649522+00:00>>
And If I move it to 98 there is a
executed 'move_to_level_with_on_off' command with args: '(250, 1)'
full logs for that
2022-03-07 02:06:34 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_on, service_data=entity_id=light.kitchen_backsplash_2_level_on_off, brightness_pct=98>
2022-03-07 02:06:34 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=45, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x01\x2D\x04\xFA\x01\x00')
2022-03-07 02:06:34 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-07 02:06:34 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=45)
2022-03-07 02:06:34 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=72, SecurityUse=<Bool.false: 0>, TimeStamp=5381833, TSN=0, Data=b'\x18\x2D\x0B\x04\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-07 02:06:34 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=45 command_id=Command.Default_Response>
2022-03-07 02:06:34 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: executed 'move_to_level_with_on_off' command with args: '(250, 1)' kwargs: '{}' result: [4, <Status.SUCCESS: 0>]
2022-03-07 02:06:34 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned on: {'move_to_level_with_on_off': [4, <Status.SUCCESS: 0>]}
2022-03-07 02:06:34 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=light.kitchen_backsplash_2_level_on_off, old_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=5, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:56:22.649522+00:00>, new_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=250, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-07T01:56:22.649522+00:00>>
Is there anything else interesting you can find in the logs?
Thanks for the signature.
It seems that your device its a 'normal' zigbee device with the 0xe001
cluster from Tuya. Your quirk seems adequate for device signature, but for some reason the dim events don't seem to arrive/come from the proper cluster.
Try to get traces from operate the physical device. Usually when you interact with the device, it reports its status and we can get some information from that message.
PS: dim values are from 0 to 255 😉
I see now what you meant. Not just control the slider of the UI, but actually the physical device. So I did that and got a good chunk of logs. Attached are the logs for me dimming the light from all the way bright to all the way dark.
I can't quite wrap my head around yet what I can make out of that yet. The slider in the UI for the dimmer doesn't move at all when I dim the physical light.
I do see log lines like
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=75>)]]
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=75
2022-03-08 04:48:25 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 75
I see that the dim values from the device itself are between 0 and 1000. So that has to be mapped to the dim values 0 to 255. I think for the existing quirks that's done here: https://github.com/zigpy/zha-device-handlers/blob/e3fa034284437595d1997326a8597086d623f413/zhaquirks/tuya/__init__.py#L1156
So I probably somehow have to incorporate that TuyaLevelControl
class. Which I tried before with no success.
I also see that 0x0008
in there, which translates to the generic LevelControl
, so I think that's a good thing.
I also see that attribute 0x3891
and 61440
but not sure what that means.
Do you see anything in the logs when operating the physical device below that could give me a hint of what I'm missing?
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=3993970, TSN=0, Data=b'\x08\x87\x0A\x00\xF0\x21\x4B\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=135 command_id=Command.Report_Attributes>
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=75>)]]
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=75
2022-03-08 04:48:25 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 75
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=135, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x87\x0B\x0A\x00')
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=135)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=84, SecurityUse=<Bool.false: 0>, TimeStamp=4019549, TSN=0, Data=b'\x08\x88\x0A\x00\xF0\x21\x89\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=136 command_id=Command.Report_Attributes>
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=137>)]]
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=137
2022-03-08 04:48:26 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 137
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=136, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x88\x0B\x0A\x00')
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=136)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=96, SecurityUse=<Bool.false: 0>, TimeStamp=4045189, TSN=0, Data=b'\x08\x89\x0A\x00\xF0\x21\xC8\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=137 command_id=Command.Report_Attributes>
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=200>)]]
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=200
2022-03-08 04:48:26 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 200
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=137, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x89\x0B\x0A\x00')
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=137)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=4070767, TSN=0, Data=b'\x08\x8A\x0A\x00\xF0\x21\x07\x01', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=138 command_id=Command.Report_Attributes>
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=263>)]]
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=263
2022-03-08 04:48:26 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 263
2022-03-08 04:48:26 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=138, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8A\x0B\x0A\x00')
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=138)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=4096392, TSN=0, Data=b'\x08\x8B\x0A\x00\xF0\x21\x45\x01', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=139 command_id=Command.Report_Attributes>
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=325>)]]
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=325
2022-03-08 04:48:27 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 325
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=139, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8B\x0B\x0A\x00')
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=139)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=84, SecurityUse=<Bool.false: 0>, TimeStamp=4121931, TSN=0, Data=b'\x08\x8C\x0A\x00\xF0\x21\x84\x01', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=140 command_id=Command.Report_Attributes>
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=388>)]]
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=388
2022-03-08 04:48:27 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 388
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=140, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8C\x0B\x0A\x00')
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:27 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=140)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4147594, TSN=0, Data=b'\x08\x8D\x0A\x00\xF0\x21\xC3\x01', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=141 command_id=Command.Report_Attributes>
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=451>)]]
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=451
2022-03-08 04:48:28 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 451
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=141, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8D\x0B\x0A\x00')
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=141)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=4173234, TSN=0, Data=b'\x08\x8E\x0A\x00\xF0\x21\x02\x02', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=142 command_id=Command.Report_Attributes>
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=514>)]]
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=514
2022-03-08 04:48:28 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 514
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=142, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8E\x0B\x0A\x00')
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:28 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=142)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=4198871, TSN=0, Data=b'\x08\x8F\x0A\x00\xF0\x21\x40\x02', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=143 command_id=Command.Report_Attributes>
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=576>)]]
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=576
2022-03-08 04:48:29 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 576
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=143, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x8F\x0B\x0A\x00')
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=143)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=90, SecurityUse=<Bool.false: 0>, TimeStamp=4224444, TSN=0, Data=b'\x08\x90\x0A\x00\xF0\x21\x7F\x02', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=144 command_id=Command.Report_Attributes>
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=639>)]]
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=639
2022-03-08 04:48:29 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 639
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=144, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x90\x0B\x0A\x00')
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=144)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4250026, TSN=0, Data=b'\x08\x91\x0A\x00\xF0\x21\xBE\x02', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=145 command_id=Command.Report_Attributes>
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=702>)]]
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=702
2022-03-08 04:48:29 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 702
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=145, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x91\x0B\x0A\x00')
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:29 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=145)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4275645, TSN=0, Data=b'\x08\x92\x0A\x00\xF0\x21\xFD\x02', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=146 command_id=Command.Report_Attributes>
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=765>)]]
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=765
2022-03-08 04:48:30 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 765
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=146, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x92\x0B\x0A\x00')
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=146)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4301214, TSN=0, Data=b'\x08\x93\x0A\x00\xF0\x21\x3B\x03', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=147 command_id=Command.Report_Attributes>
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=827>)]]
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=827
2022-03-08 04:48:30 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 827
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=147, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x93\x0B\x0A\x00')
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:30 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=147)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=84, SecurityUse=<Bool.false: 0>, TimeStamp=4326890, TSN=0, Data=b'\x08\x94\x0A\x00\xF0\x21\x7A\x03', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=148 command_id=Command.Report_Attributes>
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=890>)]]
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=890
2022-03-08 04:48:31 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 890
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=148, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x94\x0B\x0A\x00')
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=148)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4352469, TSN=0, Data=b'\x08\x95\x0A\x00\xF0\x21\xB9\x03', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=149 command_id=Command.Report_Attributes>
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=953>)]]
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=953
2022-03-08 04:48:31 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 953
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=149, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x95\x0B\x0A\x00')
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=149)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=4372171, TSN=0, Data=b'\x08\x96\x0A\x00\xF0\x21\xE4\x03', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=150 command_id=Command.Report_Attributes>
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=996>)]]
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=996
2022-03-08 04:48:31 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 61440 update with value: 996
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=150, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=30, Data=b'\x18\x96\x0B\x0A\x00')
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 04:48:31 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=150)
Maybe interesting: When I bring back my custom quirk with these input clusters enabled:
TuyaManufacturerClusterOnOff,
TuyaOnOff,
TuyaManufacturerLevelControl,
TuyaLevelControl,
And then setting the brightness via UI slider I get
2022-03-08 06:13:36 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_on, service_data=entity_id=light.kitchen_backsplash_2_level_on_off, brightness_pct=53>
2022-03-08 06:13:36 DEBUG (MainThread) [zhaquirks.tuya] a4:c1:38:76:3f:03:3e:46 Sending Tuya Cluster Command.. Cluster Command is 4, Arguments are (135, 1)
2022-03-08 06:13:36 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=25, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x05\x41\x11\x19\x00\x00\x00\x02\x02\x00\x04\x00\x00\x02\x11')
2022-03-08 06:13:36 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 06:13:36 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=25)
2022-03-08 06:13:36 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=84, SecurityUse=<Bool.false: 0>, TimeStamp=2763000, TSN=0, Data=b'\x18\x19\x0B\x00\x83', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 06:13:36 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0xef00] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=25 command_id=Command.Default_Response>
2022-03-08 06:13:36 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: executed 'move_to_level_with_on_off' command with args: '(135, 1)' kwargs: '{}' result: [0, <Status.UNSUP_MANUF_CLUSTER_COMMAND: 131>]
2022-03-08 06:13:36 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned on: {'move_to_level_with_on_off': [0, <Status.UNSUP_MANUF_CLUSTER_COMMAND: 131>]}
Which has a different ClusterId=61184
and it says result: [0, <Status.UNSUP_MANUF_CLUSTER_COMMAND: 131>]
.
But I do I get my quirk to set this attribute 61440
(which is 0xF000
) to a value between 0 and 1000?
Ok, first I am going to try to explain to you what we are seeing and then we will see what can be done.
2022-03-08 04:48:25 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=
)]]
Here we have an attributte report from the device.
This [0x3891:1:0x0008]
is some standard part of ZHA messages and is telling us that the device 0x3891
from endpoint 1
and cluster 0x0008
is sending the attribute report.
Tha part is correct. You can see in the device signature this endpoint and this cluster (which, as you said, corresponds to the LevelControl
)
The second part is telling us that the attribute 61440
is updating its value (from 0 to 1000). And that is a problem.
HA (and the Zigbee standard) expect dim values (current_level
) to be reported in the 0x0000
attribute (and not the 0xF000
as that device is doing):
Also, the expected that values are from 0 to 255.
And, what can be done?
Obviously we need to create a quirk for this cluster. It is necessary to convert the attrid
and its value both ways ZHA --> device and device --> ZHA
Create a new quirk for this LevelControl
cluster. It may be something like:
class F000LevelControlCluster(LevelControl):
"""LevelControlCluster that reports to attrid 0xF000."""
class TuyaLevelPayload(t.Struct):
"""Tuya Level payload."""
level: t.uint16_t
transtime: t.uint16_t
manufacturer_attributes = {0xF000: ("manufacturer_current_level", t.uint16_t),}
manufacturer_server_commands = {
0x00F0: ("moveToLevelTuya", (TuyaLevelPayload,), False),
}
# 0xF000 reported values are 0-1000, convert to 0-255
def _update_attribute(self, attrid, value):
if attrid == 0xF000:
value = (value * 255) // 1000
attrid = 0x0000
super()._update_attribute(attrid, value)
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
return await super().command(
0x00F0,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer,
expect_reply,
tsn
)
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
Be carefull with new imports.
Then you can use this cluster in your quirk:
class DimmerSwitchWithNeutral1Gang(TuyaDimmerSwitch):
"""Tuya Dimmer Switch Module With Neutral 1 Gang"""
signature = {
MODELS_INFO: [("_TZ3210_ngqk6jia", "TS110E")],
ENDPOINTS: {
# <SimpleDescriptor endpoint=1 profile=260 device_type=257
# input_clusters=[0, 4, 5, 6, 8, 57345]
# output_clusters=[10, 25]>
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.DIMMABLE_LIGHT,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
OnOff.cluster_id,
LevelControl.cluster_id,
TuyaZBExternalSwitchTypeCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
# <SimpleDescriptor endpoint=242 profile=41440 device_type=97
# input_clusters=[]
# output_clusters=[33]
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.DIMMABLE_LIGHT,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
OnOff.cluster_id,
F000LevelControlCluster,
TuyaZBExternalSwitchTypeCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
The _update_attribute
will handle "device --> ZHA" messages and is responsible for the reported values being updated in HA.
The command
will be in charge of sending the values that the device expects. This part makes me more doubtful because I haven't located a similar implementation.
edit: code update
Only for info i have one 2 gang with no neutral version TS110F _TZ3000_92chsky7
that is working OK but its not having the extra function with min and max dim level cluster (0xE001) (what i knowing) that this is having and is working OK in ZHA without quirk.
This devices its little normal tuya devices we is having but its working nice (until IKEA was taking the group binding away and i cant controlling the gangs from them only the all the device on / off).
@MattWestb do you know about any quirk that is 'translating' from one cluster attribute (0xF000
here) to other one (the standard 0x0000
)?
I haven't find any implementation like this and I'm not sure about the "HA --> device" part.
I have not seen one, then tuya is making all thing not 100% the same like the power on default is 2/3 function OK and have leaving it on the tuya attribute and not "converting" it to ZCL standard.
Perhaps the tuya TRVs is using many attributes but i dont knowing is some is being "moved" to ZCL standard but its not the same then its to and from DP commands.
Perhaps our @puddly is knowing if some Xiaomi devices is doing it (they using different attributes / commands strings for attribute reporting and setting)?
I have putting in the new found attribute in the matrix as WIP and linked here. https://github.com/zigpy/zigpy/discussions/823#discussioncomment-1539469
Then have the level working is the device very likely have more attributes that is not implanted but can being done like what Bulb type is connected (found in latest tuya dev docks and all is not tested but some is working like min and may dim).
Wow awesome, thanks so much for your help so far. So you were exactly right, the _update_attribute
function works as expected. As I dim on the physical device I can see the brightness slider in the home assistant UI change in real time. That's pretty cool.
2022-03-08 22:21:36 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL request 0x000a: [[Attribute(attrid=61440, value=<TypeValue type=uint16_t, value=494>)]]
2022-03-08 22:21:36 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Attribute report received: 61440=494
2022-03-08 22:21:36 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: received attribute: 0 update with value: 125
You were also right that the command
function doesn't quite work yet, so I can't update the brightness from home assistant yet.
First I got an error that I fixed quickly by adding an async
before the def command
because it told me await
can't be in a function without async
.
Now home assistant starts up and successfully updates the values as I dim the physical device, but whenever I move the slider int he UI I get
2022-03-08 22:22:41 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Sending Cluster Command. Cluster Command is 4, Arguments are (138, 1)
2022-03-08 22:22:41 ERROR (MainThread) [zigpy.zcl] [0x3891:1:0x0008] 61440 is not a valid attribute id
and then a little further down
2022-03-08 22:22:41 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [546955499648] list index out of range
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1495, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1530, in _execute_service
await handler.job.target(service_call)
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 209, in handle_service
await self.hass.helpers.service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 663, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 896, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 700, in _handle_entity_call
await result
File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 494, in async_handle_light_on_service
await light.async_turn_on(**filter_turn_on_params(light, params))
File "/usr/src/homeassistant/homeassistant/components/zha/light.py", line 236, in async_turn_on
if not isinstance(result, list) or result[1] is not Status.SUCCESS:
IndexError: list index out of range
So it expects result[1]
to be there.
I guess what we're returning in return await self.write_attributes({0xF000: brightness}, manufacturer=manufacturer)
somehow needs to return a list?
Is it now guesswork to find out what command the device needs?
Do you think something similar to this helps? https://github.com/zigpy/zha-device-handlers/blob/e3fa034284437595d1997326a8597086d623f413/zhaquirks/tuya/__init__.py#L429-L450
I already tries some variations with now success yet.
Try uncomment this line from F000LevelControlCluster
:
manufacturer_attributes = {0xF000: ("current_level", t.uint8_t),} # maybe needed for write_attributes
Hmm no, still the same error:
File "/usr/src/homeassistant/homeassistant/components/zha/light.py", line 236, in async_turn_on
if not isinstance(result, list) or result[1] is not Status.SUCCESS:
IndexError: list index out of range
But what's new is that for every tuya value greater than 256 I get this error as well:
2022-03-08 23:17:28 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Sending Cluster Command. Cluster Command is 4, Arguments are (102, 1)
2022-03-08 23:17:28 ERROR (MainThread) [zigpy.zcl] [0x3891:1:0x0008] 400 is not an unsigned 8 bit integer
changing it to
manufacturer_attributes = {0xF000: ("current_level", t.uint16_t),} # maybe needed for write_attributes
removes the second error, but still has the first error...
Maybe this way (as a quick&dirty workaround):
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
self.write_attributes({0xF000: brightness}, manufacturer=manufacturer)
return [[foundation.WriteAttributesStatusRecord(foundation.Status.SUCCESS)]]
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
I'll keep looking...
I think that there is a better approach:
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
(res,) = await self.write_attributes({0xF000: brightness}, manufacturer=manufacturer)
return [command_id, res[0].status]
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
🤞🏻
Another test you can perform is try to read & update this attribute from cluster F000LevelControlCluster
.
From the device view --> "Manage clusters" --> Select 'F000LevelControlCluster' --> Select attribute from cluster 'current_level (id: 0xF000)' --> 'Get zigbee attribute'
You can try to put a 0-255 value and hit 'Set zigbee attribute', this should change the dim value from device.
Look at the logs and attach all you find relevant.
So I tried the second better approach you sent and no error anymore, but also not changing the brightness on the device. Log of sliding the brightness to a new point:
2022-03-08 23:56:44 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=light, service=turn_on, service_data=entity_id=light.kitchen_backsplash_2_level_on_off, brightness_pct=78>
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] Sending Cluster Command. Cluster Command is 4, Arguments are (199, 1)
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x3891), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=8, TSN=25, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x00\x19\x02\x00\xF0\x21\x0C\x03')
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataRequestExt.Rsp(Status=<Status.SUCCESS: 0>)
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.DataConfirm.Callback(Status=<Status.SUCCESS: 0>, Endpoint=1, TSN=25)
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=8, SrcAddr=0x3891, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=87, SecurityUse=<Bool.false: 0>, TimeStamp=6899442, TSN=0, Data=b'\x18\x19\x04\x00', MacSrcAddr=0x3891, MsgResultRadius=29)
2022-03-08 23:56:44 DEBUG (MainThread) [zigpy.zcl] [0x3891:1:0x0008] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=25 command_id=Command.Write_Attributes_rsp>
2022-03-08 23:56:44 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x3891:1:0x0008]: executed 'move_to_level_with_on_off' command with args: '(199, 1)' kwargs: '{}' result: [4, <Status.SUCCESS: 0>]
2022-03-08 23:56:44 DEBUG (MainThread) [homeassistant.components.zha.entity] light.kitchen_backsplash_2_level_on_off: turned on: {'move_to_level_with_on_off': [4, <Status.SUCCESS: 0>]}
2022-03-08 23:56:44 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=light.kitchen_backsplash_2_level_on_off, old_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=110, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-08T23:55:22.696105+00:00>, new_state=<state light.kitchen_backsplash_2_level_on_off=on; supported_color_modes=['brightness'], color_mode=brightness, brightness=199, off_brightness=None, friendly_name=Kitchen Backsplash 2 level, on_off, supported_features=33 @ 2022-03-08T23:55:22.696105+00:00>>
I will try the "Manage clusters" read and update attribute next.
First thing that's interesting there is that there's two current_level
attributes with different ids:
Does this look wrong?
No, that is what I has expected.
0xF000
is the manufacturer_attribute
that we have defined you can change the current_level
to whatever you want. Also is the attribute that this device is using to report the dim values.
0x0000
is the zigbee standar current_level
attribute for dimmers.
The problem is that HA will 'talk' with the 0x0000 attribute, but it seems that device is listening to the 0xF000.
It would be probably more appropriate to rename it to manufacturer_current_level
🤷🏻♂️
hmm so I tried all combinations in the "Manage Cluster" interface. But all I got working from there was the on and off commands from the on off cluster.
No attributes or commands of the F000LevelControlCluster
were working yet. They all didn't change the brightness.
What's also interesting is that if I move the slider in the UI and click 'Get Zigbee Attribute', then I get the updated value. If I change the brightness on the physical dimmer, then the click on 'Get Zigbee Attribute' doesn't give me a new value...
If I click 'Issue Zigbee Command' for move_to_level_with_on_off
, I get this error:
File "/usr/local/lib/python3.9/site-packages/zhaquirks/tuya/ts110e.py", line 81, in command
brightness = (args[0] * 1000) // 255
IndexError: tuple index out of range
The 'sets' from 0x0000
attribute are not expected to does nothing.
'Gets' probably return an empty value. Maybe even after trying to assign a value to it.
'Gets' for the 0xF000
attribute should return the dimm value.
Setting values should change the dimm value.
Wich one of the current_level
attributes is updating his value?
If I click 'Issue Zigbee Command' for
move_to_level_with_on_off
, I get this error:
That's normal because UI command can't get values for methods. This method requires a 'value' to work (and no, the manufacturer Id is not that value). That is why args[0] is out of range.
Okay so for the 0xF000
attribute it only changes the values if I set it via the UI slider (I'm setting it on my phone as a second device and keep getting the value).
As I'm dimming the physical device, the 0xF000
one doesn't change. It stays on what I set in the UI slider last. Even though the UI slider gets updated to the current dim level (the success we had earlier).
So, it seems that device is NOT using the standard 0x0000
attribute for current_level
It is reporting the current_level
in attribute 0xF000
But is NOT using neither the 0xF000
attribute for setting current_level
Wonderfull... maybe it's using another attribute for setting values.
One last try that you can make is to change the write_attributes
call this way (yes b""
):
(res,) = await self.write_attributes({0xF000: brightness}, manufacturer=b"")
It's rest time for me. Tomorrow I will look if this device has been implemented in other libraries and maybe someone have found how to set the dim value 🤦🏻♂️
Yeah it's really weird. But the write_attribute
method definitely works because as I'm sliding the slider in the UI, I can click 'Get Zigbee Attribute' and the value for 0xf000 updates.
Also as I'm using the physical device, the slider in the UI updates, that means the _update_attribute
works as well.
What's weird is that as I'm using the physical device the click on 'Get Zigbee Attribute' doesn't update and also that when I'm using the slider in the UI the brightness of the physical device doesn't update.
I tried manufacturer=b""
as well with no success.
That would be awesome to look at other implementations. I actually did look around a bit and found these lines in zigbee2mqtt: https://github.com/Koenkk/zigbee-herdsman-converters/blob/baf446a61da472667ac1a263f7dde90a7861d02f/devices/lonsonho.js#L84-L91
I'm just really bad at reading this and it doesn't mean much to me. Does that mean anything to you? It looks like it's using this behind the scenes.
Hmm it appears in this thread they also discovered that this device is hard to implement and in September they reverted support for the TS110E
device. After all, I thought I would get the TS110F
device, but apparently they sent me the TS110E
device... Maybe I'm just in bad luck?
Okay sorry for posting so much, but after even more digging, there's a post that promises more hope: A lot of other issues on zigbee2mqtt linked to this post: https://github.com/Koenkk/zigbee2mqtt/issues/9878 They report that this converter is working for them, they just never added it properly to zigbee2mqtt. Can you interpret what the converter is doing and how we could translate it into our quirk?
The key seems to be this non-standard command:
In the file .src/zcl/definition/cluster.ts you need to add a new command for the 0008 cluster:
moveToLevelTuya: { ID: 240, parameters: [ { name: 'level', type: dataType_1.default.uint16 }, { name: 'transtime', type: dataType_1.default.uint16 }, ], },
I'm also reading the same posts.
Today last offer:
class F000LevelControlCluster(LevelControl):
"""LevelControlCluster that reports to attrid 0xF000."""
class TuyaLevelPayload(t.Struct):
"""Tuya Level payload."""
level: t.uint16_t
transtime: t.uint16_t
manufacturer_attributes = {0xF000: ("manufacturer_current_level", t.uint16_t),}
manufacturer_server_commands = {
0x00F0: ("moveToLevelTuya", (TuyaLevelPayload,), False),
}
# 0xF000 reported values are 0-1000, convert to 0-255
def _update_attribute(self, attrid, value):
if attrid == 0xF000:
value = (value * 255) // 1000
attrid = 0x0000
super()._update_attribute(attrid, value)
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
return await super().command(
0x00F0,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer,
expect_reply,
tsn
)
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
Not sure if it must be manufacturer_server_commands
or manufacturer_client_commands
. Try to change if gives you problems.
I will check the results in (my) morning. 😴
Wow! Good news for when you wake up 😄 After a few more changes it's finally working 🎉! Thank you so much!!
I had to move the class TuyaLevelPayload
outside the class because otherwise it would say NameError: name 'TuyaLevelPayload' is not defined
.
I also had to name the parameters manufacturer
, expect_reply
and tsn
cause otherwise they would count into the *args
of the command
method. But with that it's finally working now!
Here's the final product:
class TuyaLevelPayload(t.Struct):
"""Tuya Level payload."""
level: t.uint16_t
transtime: t.uint16_t
class F000LevelControlCluster(LevelControl):
"""LevelControlCluster that reports to attrid 0xF000."""
manufacturer_attributes = {0xF000: ("manufacturer_current_level", t.uint16_t),}
manufacturer_server_commands = {
0x00F0: ("moveToLevelTuya", (TuyaLevelPayload,), False),
}
# 0xF000 reported values are 0-1000, convert to 0-255
def _update_attribute(self, attrid, value):
if attrid == 0xF000:
value = (value * 255) // 1000
attrid = 0x0000
super()._update_attribute(attrid, value)
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
return await super().command(
0x00F0,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer=manufacturer,
expect_reply=expect_reply,
tsn=tsn
)
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
I will clean up the imports, format with black and whip up a PR.
Also, do you have a bitcoin lightning address? I'd like to send you a tip! This was amazing help!
I'm glad you got it working. Nice job!
I have a few changes (and tests) if you like to play a little more.
Z2M indicates that there are a few more attributes for this device:
0xFC02
: bulb_type0xFC03
: manufacturer_min_level0xFC04
: manufacturer_max_levelThe bulb_type
has been seen around with other ID.
There are standard zigbee attributes in LevelControl
cluster for the min/max level, but for now I think we're going to leave them unchanged.
The manufacturer_attributes
could be removed from the device definition and use only the standard attributes.
I think I prefer to keep both values. For the manufacturer_current_level
also the standar current_level
attribute will be updated.
The same change can be done for the min/max level, but it will requiere modify the _update_attributes
and also the write_attributes
method.
For now I don't think it's worth it.
write_attributes
overwrite?If you want to use the standard cluster attributes to be able to read and write its values (in addition to _update_attributes
) you must override the write_attributes
method.
This may be necessary if (for example) in the future HA allows to configure the min/max level attribute from UI. The same way that HA only understand the standard current_level
attribute, in this case HA will function only with the standard min_level
and max_level
attributes.
Overriding the method will require 'translating' the attributes to use and performing the conversion of values 0-255 vs 0-1000
For now I think we can leave it as is.
This is (more or less) the proposed version:
TUYA_LEVEL_ATTRIBUTE = 0xF000
TUYA_BULB_TYPE_ATTRIBUTE = 0xFC02
TUYA_MIN_LEVEL_ATTRIBUTE = 0xFC03
TUYA_MAX_LEVEL_ATTRIBUTE = 0xFC04
TUYA_CUSTOM_LEVEL_COMMAND = 0x00F0
class TuyaLevelPayload(t.Struct):
"""Tuya Level payload."""
level: t.uint16_t
transtime: t.uint16_t
class TuyaBulbType(t.enum8):
"""Tuya bulb type."""
LED = 0x00
INCANDESCENT = 0x01
HALOGEN = 0x02
class F000LevelControlCluster(LevelControl):
"""LevelControlCluster that reports to attrid 0xF000."""
manufacturer_attributes = {
TUYA_LEVEL_ATTRIBUTE: ("manufacturer_current_level", t.uint16_t),
TUYA_BULB_TYPE_ATTRIBUTE: ("bulb_type", TuyaBulbType), # 0xFC02
TUYA_MIN_LEVEL_ATTRIBUTE: ("manufacturer_min_level", t.uint16_t), # 0xFC03
TUYA_MAX_LEVEL_ATTRIBUTE: ("manufacturer_max_level", t.uint16_t), # 0xFC04
}
manufacturer_server_commands = {
TUYA_CUSTOM_LEVEL_COMMAND: ("moveToLevelTuya", (TuyaLevelPayload,), False),
}
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
# update also `current_level` attribute
if attrid == TUYA_LEVEL_ATTRIBUTE:
# manufacturer reported values are 0-1000, convert to 0-255
value = (value * 255) // 1000
attrid = 0x0000
super()._update_attribute(attrid, value)
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
return await super().command(
TUYA_CUSTOM_LEVEL_COMMAND,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer=manufacturer,
expect_reply=expect_reply,
tsn=tsn,
)
return super().command(command_id, *args, manufacturer, expect_reply, tsn)
A few comments about the new attributes.
bulb_type
attribute. I haven't read anything conclusive about it.manufacturer_attributes
is 0-1000.manufacturer_attributes
from the "manage clusters" view (except manufacturer_current_level
that must be addressed from the UI slider or any HA method)manufacturer_attributes = { TUYA_LEVEL_ATTRIBUTE: ("manufacturer_current_level", t.uint16_t), TUYA_BULB_TYPE_ATTRIBUTE: ("bulb_type", TuyaBulbType), # 0xFC02 TUYA_MIN_LEVEL_ATTRIBUTE: ("manufacturer_min_level", t.uint16_t), # 0xFC03 TUYA_MAX_LEVEL_ATTRIBUTE: ("manufacturer_max_level", t.uint16_t), # 0xFC04 } manufacturer_server_commands = { TUYA_CUSTOM_LEVEL_COMMAND: ("moveToLevelTuya", (TuyaLevelPayload,), False), }
@MattWestb a few more Tuya attributes and a new server command for the inventory. Tuya devices are plenty of 🎁
We is having one device that looks the same but is being one 10V dimer (its sending 0-10V to light and for the light level in PRO light systems) that is using the 0xfc00 attribute for min and max level and its verified working OK for the user but we have not getting one PR for it (I think hi cant doing so much coding and testing for the moment (UA) ;-/ #1149. ZCL is having one attribute for min and one for max. If you have the knowledge "converting it to ZCL attribute its one great things for the user and was the reason its not making on PR then its more or less useless for normal users.
The attribute 0xfc03
Scr state (uint8) 0x00–0xFF (default 0x01) and 0xfc04
Current percentage (uint8) 0x00–0xFF (default 0x01) i have found in lates tuya dev docks but is the function not OK ??
The 0xF000 "tuya Level control"
(TUYA_LEVEL_ATTRIBUTE) is onet.uint16_t
is it having full range (0x0 - 0xffff) or is it limited ?
Is the command TUYA_CUSTOM_LEVEL_COMMAND
having one number that i can putting in the matrix and also parameter (unit number and range) ?
And last but most important great work done !!!
The attribute
0xfc03
Scr state (uint8) 0x00–0xFF (default 0x01) and0xfc04
Current percentage (uint8) 0x00–0xFF (default 0x01) i have found in lates tuya dev docks but is the function not OK ??
Not for this device. According to Z2M (not tested yet here):
The
0xF000 "tuya Level control"
(TUYA_LEVEL_ATTRIBUTE) is onet.uint16_t
is it having full range (0x0 - 0xffff) or is it limited ?
Has been verified to get 0-1000 values. This is the reason we put t.uint16_t
here.
Is the command
TUYA_CUSTOM_LEVEL_COMMAND
having one number that i can putting in the matrix and also parameter (unit number and range) ?
Yes, TUYA_CUSTOM_LEVEL_COMMAND = 0x00F0
. I got this value (again) in Z2M
Its parameters are the TuyaLevelPayload
:
And you can guess where this values came from...
And you can guess where this values came from...
deCONZ ??? :-)))))))
I putting in the 0xF000 attribute and the 0x00F0 command and we can fixing the other then its being tested and perhaps its can having different functions (its still tuya devices).
Do you knowing the unit (S / 1/4 S / 1/10 S ?) an the range for the 0x00F0
transtime: (t.uint16_t)
?
Not nervelessly but if you knowing i think its good pouting it in for reference and for future.
Do you knowing the unit (S / 1/4 S / 1/10 S ?) an the range for the
0x00F0
transtime: (t.uint16_t)
? Not nervelessly but if you knowing i think its good pouting it in for reference and for future.
No, I haven't found any clues about yhis attribute units.
Maybe @jonnylangefeld can do some tests by changing the transtime
value from 0 to (for example) 1, 10, 100, 1000... to see if it gives us an idea of what is used for and its meaning (I guess it's about the transition time between values):
return await super().command(
TUYA_CUSTOM_LEVEL_COMMAND,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer=manufacturer,
expect_reply=expect_reply,
tsn=tsn,
)
So I set the values from 0 to 100 and then also to 1000 and always restarted in between, but nothing changed. I was expecting for the dimmer to just "dim slower", but it was always the same. I also read the values for man level and max level and they were 10 and 1000. So technically the scale has to adapt to that right?
I also noticed two more things:
Here the logs:
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Sending Cluster Command. Cluster Command is 4, Arguments are (254, 1)
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Setting brightness to 1000
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Attribute report received: manufacturer_current_level=1000
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Getting brightness 1000
2022-03-12 23:40:50 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0xA1EC:1:0x0008]: received attribute: 0 update with value: 255
2022-03-12 23:40:51 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Attribute report received: manufacturer_current_level=996
2022-03-12 23:40:51 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Getting brightness 996
2022-03-12 23:40:51 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0xA1EC:1:0x0008]: received attribute: 0 update with value: 254
I updated the PR, but feel free to change things around.
The usual behavior of the devices is as follows:
What you are seeing are the traces of those 2 events:
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Sending Cluster Command. Cluster Command is 4, Arguments are (254, 1)
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Setting brightness to 1000
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Attribute report received: manufacturer_current_level=1000
2022-03-12 23:40:50 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Getting brightness 1000
2022-03-12 23:40:50 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0xA1EC:1:0x0008]: received attribute: 0 update with value: 255
2022-03-12 23:40:51 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Attribute report received: manufacturer_current_level=996
2022-03-12 23:40:51 DEBUG (MainThread) [zigpy.zcl] [0xa1ec:1:0x0008] Getting brightness 996
2022-03-12 23:40:51 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0xA1EC:1:0x0008]: received attribute: 0 update with value: 254
I would not modify the calculation of the dim value. As I've said before IMHO it's something that should be approached in a generic way and not device by device.
- Min/max values only affects to the dim from the physical device so that the values always stay in the range min<max. I'm not sure about this, but probably dim from HA will not respect this min/max values. Most Z2M devices take these limits into account and allow replicate the behavior from the physical device. I have not seen it implemented in ZHA, but IMHO it is a topic to address in a more generic way and not for each device.
@jonnylangefeld Can you check if the cluster attributes manufacturer_min_level
and manufacturer_max_level
have any value for your device?
This one worked for my one gang with neutral lonsonho smart dimmers as intended but I have dimmer function on my 2 gang no neutral ones, they are both TS110E devices, is it possible to modify the quirk to make it compatible with those too?, also the dimming function from HA on the ones that work is going from around 20% to 80% from totally off to totally on, there is no difference between 0-20 and 80 to 100... @javicalle @jonnylangefeld
Thid is the device signature for the two gang with no neutral ones (QS-Zigbee-D02-TRIAC-2C-L)
{ "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": "0x0101", "in_clusters": [ "0x0000", "0x0004", "0x0005", "0x0006", "0x0008", "0x0300", "0xef00" ], "out_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": 260, "device_type": "0x0101", "in_clusters": [ "0x0004", "0x0005", "0x0006", "0x0008", "0x0300", "0xef00" ], "out_clusters": [] }, "242": { "profile_id": 41440, "device_type": "0x0061", "in_clusters": [], "out_clusters": [ "0x0021" ] } }, "manufacturer": "_TZ3210_4ubylghk", "model": "TS110E", "class": "zigpy.device.Device" }
Hi guys.
I rushed out and bought one of these on ebay without checking first they were compatible.
I'm having the same issues with not being able to dim them.
I've tried using the code above and putting it into a quirk but I get errors. It says that some of the code has been deprecated.
Is there another fix for this?
Hello. I have https://www.zigbee2mqtt.io/devices/TS110E_2gang_2.html, which does not directly know the state of the physical push switch (S1 or S2 state). Is there any way to get the status information of (S1 or S2) in zigbee2mqtt and Home Assistant? Thank you
Hi, I have the same exact model _TZ3210_ngqk6jia (TS110E) and tried to apply the quirk but its not working for me, its not working and Hass doestn even display the quirk. I have the quirk stored in config - custom_zha_quirks - ts110e.py
Im sorry if im being stupid, Im a little noob ;)
Here is the code I've inserted, I dont even know if I copied the right one, sorry!
TUYA_BULB_TYPE_ATTRIBUTE = 0xFC02
TUYA_MIN_LEVEL_ATTRIBUTE = 0xFC03
TUYA_MAX_LEVEL_ATTRIBUTE = 0xFC04
TUYA_CUSTOM_LEVEL_COMMAND = 0x00F0
class TuyaLevelPayload(t.Struct):
"""Tuya Level payload."""
level: t.uint16_t
transtime: t.uint16_t
class TuyaBulbType(t.enum8):
"""Tuya bulb type."""
LED = 0x00
INCANDESCENT = 0x01
HALOGEN = 0x02
class F000LevelControlCluster(LevelControl):
"""LevelControlCluster that reports to attrid 0xF000."""
manufacturer_attributes = {
TUYA_LEVEL_ATTRIBUTE: ("manufacturer_current_level", t.uint16_t),
TUYA_BULB_TYPE_ATTRIBUTE: ("bulb_type", TuyaBulbType), # 0xFC02
TUYA_MIN_LEVEL_ATTRIBUTE: ("manufacturer_min_level", t.uint16_t), # 0xFC03
TUYA_MAX_LEVEL_ATTRIBUTE: ("manufacturer_max_level", t.uint16_t), # 0xFC04
}
manufacturer_server_commands = {
TUYA_CUSTOM_LEVEL_COMMAND: ("moveToLevelTuya", (TuyaLevelPayload,), False),
}
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
# update also `current_level` attribute
if attrid == TUYA_LEVEL_ATTRIBUTE:
# manufacturer reported values are 0-1000, convert to 0-255
value = (value * 255) // 1000
attrid = 0x0000
super()._update_attribute(attrid, value)
async def command(
self,
command_id: Union[foundation.Command, int, t.uint8_t],
*args,
manufacturer: Optional[Union[int, t.uint16_t]] = None,
expect_reply: bool = True,
tsn: Optional[Union[int, t.uint8_t]] = None,
):
"""Override the default Cluster command."""
self.debug(
"Sending Cluster Command. Cluster Command is %x, Arguments are %s",
command_id,
args,
)
# move_to_level, move, move_to_level_with_on_off
if command_id in (0x0000, 0x0001, 0x0004):
# convert dim values to 0-1000
brightness = (args[0] * 1000) // 255
return await super().command(
TUYA_CUSTOM_LEVEL_COMMAND,
TuyaLevelPayload(level=brightness, transtime=0),
manufacturer=manufacturer,
expect_reply=expect_reply,
tsn=tsn,
)
return super().command(command_id, *args, manufacturer, expect_reply, tsn)```
I am not sure if this is a device request, or if the device itself is just not working. Maybe someone can halp?
I ordered two of these in-wall dimmers:
If successfully installed it and paired it with home assistant (I'm using zha) and was able to use the on-off switch right away, but the dimmer slider wouldn't do anything. So naturally I thought I'd need a quirk. However, I wasn't able to get the dimmer slider working.
I pasted the device signature below and you can see that the
in_clusters
already have"0x0006"
and"0x0008"
which isOnOff
andLevelControl
. A lot of the other tuya quirks for the dimmers didn't have those, so I understand that a quirk was necessary. In this case however I was surprised that it wasn't working right out of the box, because the blakadder.com entry confirmed it working with ZHA. However, the blakadder.com entry lists it asZigbee ID: "TS110F"; "_TYZB01_qezuin6k"
, while the one I actually got itZigbee ID: "TS110E"; "_TZ3210_ngqk6jia"
. So a small difference, even though the device itself looks exactly as on the pictures on blakadder.com and aliexpress.com.I came up with the following quirk that I stored in
tuya/ts110e.py
:The quirk is seen by home assistant (I see the
Quirk: zhaquirks.tuya.ts110e.DimmerSwitchWithNeutral1Gang
on the device in the home assistant UI). As you can see I experimented with all combinations of theOnOff
andLevelControl
alternatives. So far only the originalworks for at least the switch but not the dimmer.
Other combinations i tried:
that comes with error
Which makes sense. So I tried
Which didn't throw an error and allowed me to call the switch in the UI of home assistant, but it wouldn't turn on the light and the switch in the UI jumps back like 2 seconds later.
Does anyone have any other suggestions of what I could try?
Device signature:
Additional context Add any other context or screenshots about the feature request here.