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
775 stars 703 forks source link

[Device Support Request] Tuya HC-T020-ZIGBEE Series Thermostat #2441

Closed adamantivm closed 11 months ago

adamantivm commented 1 year ago

Problem description

Device is recognized quickly as TS0601 by _TZE200_ztvwu4nk but doesn't expose any sensors or controls

Solution description

At the bare minimum, it would be really nice to be able to read current temperature and set desired temperature, that would already allow quite a bit of automation through Home Assistant.

In an ideal scenario, exposing all the functionality available in the device (usable through the Tuya app) would be great.

Screenshots/Video

Screenshots/Video Here is a great writeup by @notenoughtech that describes the device in some detail: https://notenoughtech.com/home-automation/a-budget-zigbee-thermostat/

Device signature

Device signature ```json { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *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": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_ztvwu4nk", "model": "TS0601", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.6.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.4", "docker": true, "arch": "aarch64", "timezone": "America/Argentina/Buenos_Aires", "os_name": "Linux", "os_version": "6.1.21-v8", "supervisor": "2023.06.2", "host_os": "Home Assistant OS 10.3", "docker_version": "23.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": { "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "dahua_vto": { "version": "1.0.7", "requirements": [] }, "huawei_solar": { "version": "1.2.5", "requirements": [ "huawei-solar==2.2.6" ] }, "alarmdotcom": { "version": "2.2.2", "requirements": [ "beautifulsoup4>=4.10.0", "pyalarmdotcomajax==0.4.14" ] }, "zha_toolkit": { "version": "v0.8.39", "requirements": [ "packaging>=20.8", "pytz" ] }, "localtuya": { "version": "5.2.0", "requirements": [] }, "tplink_deco": { "version": "3.3.1", "requirements": [ "pycryptodome>=3.12.0" ] }, "dahua": { "version": "0.5.0", "requirements": [] }, "alexa_media": { "version": "4.6.4", "requirements": [ "alexapy==1.26.8", "packaging>=20.3", "wrapt>=1.12.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "requirements": [ "bellows==0.35.5", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.100", "zigpy-deconz==0.21.0", "zigpy==0.55.0", "zigpy-xbee==0.18.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.1" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 12017, "manufacturer": "_TZE200_ztvwu4nk", "model": "TS0601", "name": "_TZE200_ztvwu4nk TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 149, "rssi": null, "last_seen": "2023-06-25T13:13:39", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *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": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_ztvwu4nk", "model": "TS0601" }, "active_coordinator": false, "entities": [], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "SMART_PLUG" } ], "user_given_name": "Termostato prueba", "device_reg_id": "eb69990869b8e3a6946d3af10aa68cc1", "area_id": "sum", "cluster_details": { "1": { "device_type": { "name": "SMART_PLUG", "id": 81 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0001": { "attribute_name": "app_version", "value": 68 }, "0x0004": { "attribute_name": "manufacturer", "value": "_TZE200_ztvwu4nk" }, "0x0005": { "attribute_name": "model", "value": "TS0601" } }, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0xef00": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

Logs Happy to include them but first I'd need to understand what exactly to repro

Custom quirk

Custom quirk ```python print("Hello World") ```

Additional information

I would be happy to work on the quirk myself, but would greatly appreciate some guidance. I'm a developer IRL, but never worked on ZHA or any other Home Assistant component for that matter. Relatively new to ZigBee although been reading and playing for a bit now. Interested in contributing this as a hobby.

adamantivm commented 1 year ago

This request should also give some hints: https://github.com/Koenkk/zigbee2mqtt/issues/10456

adamantivm commented 1 year ago

I'm using this very rich thread and its various links to learn what to do: https://github.com/zigpy/zha-device-handlers/issues/1109

I learned how to add a quirk locally to my installation and managed to get the ts0601_electric_heating.py quirk loaded, but unfortunately it doesn't work for me.

Now doing some logging with debug enabled to see if I can understand more details.

Here's a snippet FWIW.

[core-ssh config]$ grep 0x94D8 home-assistant.log | head -30
2023-06-26 22:16:59.597 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.TCDevInd.Callback(SrcNwk=0x94D8, SrcIEEE=70:ac:08:ff:fe:3e:ca:51, ParentNwk=0x0000)
2023-06-26 22:16:59.604 INFO (MainThread) [zigpy_znp.zigbee.application] TC device join: ZDO.TCDevInd.Callback(SrcNwk=0x94D8, SrcIEEE=70:ac:08:ff:fe:3e:ca:51, ParentNwk=0x0000)
2023-06-26 22:16:59.606 DEBUG (MainThread) [zigpy_znp.api] Sending request: ZDO.ExtRouteDisc.Req(Dst=0x94D8, Options=<RouteDiscoveryOptions.UNICAST: 0>, Radius=30)
2023-06-26 22:16:59.657 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.EndDeviceAnnceInd.Callback(Src=0x94D8, NWK=0x94D8, IEEE=70:ac:08:ff:fe:3e:ca:51, Capabilities=<MACCapabilities.Router|MainsPowered|RXWhenIdle|AllocateShortAddrDuringAssocNeeded: 142>)
2023-06-26 22:16:59.875 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.MsgCbIncoming.Callback(Src=0x94D8, IsBroadcast=<Bool.true: 1>, ClusterId=19, SecurityUse=0, TSN=130, MacDst=0xFFFF, Data=b'\xD8\x94\x51\xCA\x3E\xFE\xFF\x08\xAC\x70\x8E')
2023-06-26 22:16:59.885 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.Broadcast: 15>, address=<BroadcastAddress.ALL_ROUTERS_AND_COORDINATOR: 65532>), dst_ep=0, source_route=None, extended_timeout=False, tsn=130, profile_id=0, cluster_id=19, data=Serialized[b'\x82\xd8\x94Q\xca>\xfe\xff\x08\xacp\x8e'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:16:59.891 DEBUG (MainThread) [zigpy.application] Received frame on uninitialized device <Device model=None manuf=None nwk=0x94D8 ieee=70:ac:08:ff:fe:3e:ca:51 is_initialized=False> from ep 0 to ep 0, cluster 19: b'\x82\xd8\x94Q\xca>\xfe\xff\x08\xacp\x8e'
2023-06-26 22:16:59.892 DEBUG (MainThread) [zigpy.zdo] [0x94d8:zdo] ZDO request ZDOCmd.Device_annce: [0x94D8, 70:ac:08:ff:fe:3e:ca:51, 142]
2023-06-26 22:16:59.897 DEBUG (MainThread) [zigpy_znp.zigbee.application] Sending packet ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), dst_ep=0, source_route=None, extended_timeout=True, tsn=40, profile_id=0, cluster_id=<ZDOCmd.Node_Desc_req: 0x0002>, data=Serialized[b'(\xd8\x94'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:16:59.898 DEBUG (MainThread) [zigpy_znp.api] Sending request: ZDO.ExtRouteChk.Req(Dst=0x94D8, RtStatus=<RouteStatus.ACTIVE: 1>, Options=<RouteOptions.MTO_ROUTE|NO_ROUTE_CACHE: 3>)
2023-06-26 22:16:59.929 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x94D8), DstEndpoint=0, DstPanId=0x0000, SrcEndpoint=0, ClusterId=2, TSN=40, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=0, Data=b'\x28\xD8\x94')
2023-06-26 22:16:59.946 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.SrcRtgInd.Callback(DstAddr=0x94D8, Relays=[])
2023-06-26 22:16:59.996 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.SrcRtgInd.Callback(DstAddr=0x94D8, Relays=[])
2023-06-26 22:16:59.999 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=61184, SrcAddr=0x94D8, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=<Bool.false: 0>, LQI=47, SecurityUse=<Bool.false: 0>, TimeStamp=6827792, TSN=0, Data=b'\x19\x51\x24\x00\x00', MacSrcAddr=0x94D8, MsgResultRadius=29)
2023-06-26 22:17:00.003 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=0, profile_id=260, cluster_id=61184, data=Serialized[b'\x19Q$\x00\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=29, non_member_radius=0, lqi=47, rssi=None)
2023-06-26 22:17:00.005 DEBUG (MainThread) [zigpy.application] Received frame on uninitialized device <Device model=None manuf=None nwk=0x94D8 ieee=70:ac:08:ff:fe:3e:ca:51 is_initialized=False> from ep 1 to ep 1, cluster 61184: b'\x19Q$\x00\x00'
2023-06-26 22:17:00.050 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.NodeDescRsp.Callback(Src=0x94D8, Status=<Status.SUCCESS: 0>, NWK=0x94D8, NodeDescriptor=NullableNodeDescriptor(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.FullFunctionDevice|MainsPowered|RxOnWhenIdle|AllocateAddress: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, 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))
2023-06-26 22:17:00.058 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.MsgCbIncoming.Callback(Src=0x94D8, IsBroadcast=<Bool.false: 0>, ClusterId=32770, SecurityUse=0, TSN=40, MacDst=0x0000, Data=b'\x00\xD8\x94\x01\x40\x8E\x02\x10\x52\x52\x00\x00\x2C\x52\x00\x00')
2023-06-26 22:17:00.063 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, source_route=None, extended_timeout=False, tsn=40, profile_id=0, cluster_id=32770, data=Serialized[b'(\x00\xd8\x94\x01@\x8e\x02\x10RR\x00\x00,R\x00\x00'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:17:00.065 DEBUG (MainThread) [zigpy.application] Received frame on uninitialized device <Device model=None manuf=None nwk=0x94D8 ieee=70:ac:08:ff:fe:3e:ca:51 is_initialized=False> from ep 0 to ep 0, cluster 32770: b'(\x00\xd8\x94\x01@\x8e\x02\x10RR\x00\x00,R\x00\x00'
2023-06-26 22:17:00.073 DEBUG (MainThread) [zigpy_znp.zigbee.application] Sending packet ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), dst_ep=0, source_route=None, extended_timeout=False, tsn=41, profile_id=0, cluster_id=<ZDOCmd.Active_EP_req: 0x0005>, data=Serialized[b')\xd8\x94'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:17:00.075 DEBUG (MainThread) [zigpy_znp.api] Sending request: ZDO.ExtRouteChk.Req(Dst=0x94D8, RtStatus=<RouteStatus.ACTIVE: 1>, Options=<RouteOptions.MTO_ROUTE|NO_ROUTE_CACHE: 3>)
2023-06-26 22:17:00.093 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0x94D8), DstEndpoint=0, DstPanId=0x0000, SrcEndpoint=0, ClusterId=5, TSN=41, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK: 32>, Radius=0, Data=b'\x29\xD8\x94')
2023-06-26 22:17:00.247 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.SrcRtgInd.Callback(DstAddr=0x94D8, Relays=[])
2023-06-26 22:17:00.249 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.ActiveEpRsp.Callback(Src=0x94D8, Status=<Status.SUCCESS: 0>, NWK=0x94D8, ActiveEndpoints=[1])
2023-06-26 22:17:00.255 DEBUG (MainThread) [zigpy_znp.api] Received command: ZDO.MsgCbIncoming.Callback(Src=0x94D8, IsBroadcast=<Bool.false: 0>, ClusterId=32773, SecurityUse=0, TSN=41, MacDst=0x0000, Data=b'\x00\xD8\x94\x01\x01')
2023-06-26 22:17:00.258 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=0, source_route=None, extended_timeout=False, tsn=41, profile_id=0, cluster_id=32773, data=Serialized[b')\x00\xd8\x94\x01\x01'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:17:00.260 DEBUG (MainThread) [zigpy.application] Received frame on uninitialized device <Device model=None manuf=None nwk=0x94D8 ieee=70:ac:08:ff:fe:3e:ca:51 is_initialized=False> from ep 0 to ep 0, cluster 32773: b')\x00\xd8\x94\x01\x01'
2023-06-26 22:17:00.264 DEBUG (MainThread) [zigpy_znp.zigbee.application] Sending packet ZigbeePacket(src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), src_ep=0, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x94D8), dst_ep=0, source_route=None, extended_timeout=False, tsn=42, profile_id=0, cluster_id=<ZDOCmd.Simple_Desc_req: 0x0004>, data=Serialized[b'*\xd8\x94\x01'], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=None, rssi=None)
2023-06-26 22:17:00.265 DEBUG (MainThread) [zigpy_znp.api] Sending request: ZDO.ExtRouteChk.Req(Dst=0x94D8, RtStatus=<RouteStatus.ACTIVE: 1>, Options=<RouteOptions.MTO_ROUTE|NO_ROUTE_CACHE: 3>)
adamantivm commented 1 year ago

Trying with ts0601_trv instead also doesn't work but at least logs seem a bit more understandable:

2023-06-26 22:58:29.995 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0101 (command 0x0001)
2023-06-26 22:58:30.098 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0101 (command 0x0001)
2023-06-26 22:58:30.200 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0101 (command 0x0001)
2023-06-26 22:58:30.310 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0101 (command 0x0001)
2023-06-26 22:58:30.408 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0, 0, 0, 21] for attribute 0x0210 (command 0x0001)
2023-06-26 22:58:30.505 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0402 (command 0x0001)
2023-06-26 22:58:30.599 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0417 (command 0x0001)
2023-06-26 22:58:30.693 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0128 (command 0x0001)
2023-06-26 22:58:30.805 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0429 (command 0x0001)
2023-06-26 22:58:30.906 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0, 0, 0, 0] for attribute 0x022a (command 0x0001)
2023-06-26 22:58:31.009 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [2] for attribute 0x052d (command 0x0001)
2023-06-26 22:58:31.120 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0403 (command 0x0001)
2023-06-26 22:58:31.229 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [6, 0, 0, 20, 8, 0, 0, 15, 11, 30, 0, 15, 13, 30, 0, 15, 17, 0, 0, 22, 22, 0, 0, 15, 6, 0, 0, 20, 22, 0, 0, 1
5] for attribute 0x001e (command 0x0001)
2023-06-26 22:58:31.325 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0, 0, 0, 20] for attribute 0x0218 (command 0x0001)
2023-06-26 22:58:31.429 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0104 (command 0x0001)
2023-06-26 22:58:31.532 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0, 0, 0, 35] for attribute 0x0213 (command 0x0001)
2023-06-26 22:58:31.623 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0, 0, 0, 5] for attribute 0x021a (command 0x0001)
2023-06-26 22:58:31.719 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [255, 255, 255, 253] for attribute 0x021b (command 0x0001)
2023-06-26 22:58:31.818 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [2] for attribute 0x042b (command 0x0001)
2023-06-26 22:59:42.309 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0x0201] Mapping standard occupied_heating_setpoint (0x0012) with value 2100 to custom {514: 21}
2023-06-26 23:04:21.434 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [1] for attribute 0x0402 (command 0x0001)
2023-06-26 23:04:27.096 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0402 (command 0x0001)
2023-06-26 23:04:27.574 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0402 (command 0x0001)
2023-06-26 23:04:27.888 DEBUG (MainThread) [zhaquirks.tuya] [0x94d8:1:0xef00] Received value [0] for attribute 0x0402 (command 0x0001)
adamantivm commented 1 year ago

Continuing with the monologue, I'm happy to report that with some minor tweaks, I was able to get my device's basic functions with the ts0601_electric_heating.py quirk.

Proof:

image

adamantivm commented 1 year ago

The changes:

index 1d5ca31..b09d301 100644
--- a/zhaquirks/tuya/ts0601_electric_heating.py
+++ b/zhaquirks/tuya/ts0601_electric_heating.py
@@ -24,11 +24,12 @@ from zhaquirks.tuya import (
 # https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/converters/fromZigbee.js#L239
 # and https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/converters/common.js#L113
 MOESBHT_TARGET_TEMP_ATTR = 0x0210  # [0,0,0,21] target room temp (degree)
-MOESBHT_TEMPERATURE_ATTR = 0x0218  # [0,0,0,200] current room temp (decidegree)
-MOESBHT_SCHEDULE_MODE_ATTR = 0x0403  # [1] false [0] true   /!\ inverted
+MOESBHT_TEMPERATURE_ATTR = 0x0218  # [0,0,0,20] current room temp (degree)
+# JAC: Change to a random attribute to avoid collision with Running Mode
+MOESBHT_SCHEDULE_MODE_ATTR = 0x0404  # [1] false [0] true   /!\ inverted
 MOESBHT_MANUAL_MODE_ATTR = 0x0402  # [1] false [0] true /!\ inverted
 MOESBHT_ENABLED_ATTR = 0x0101  # [0] off [1] on
-MOESBHT_RUNNING_MODE_ATTR = 0x0424  # [1] idle [0] heating /!\ inverted
+MOESBHT_RUNNING_MODE_ATTR = 0x0403  # [1] idle [0] heating /!\ inverted
 MOESBHT_CHILD_LOCK_ATTR = 0x0128  # [0] unlocked [1] child-locked

 _LOGGER = logging.getLogger(__name__)
@@ -59,7 +60,7 @@ class MoesBHTManufCluster(TuyaManufClusterAttributes):
             self.endpoint.device.thermostat_bus.listener_event(
                 "temperature_change",
                 "local_temperature",
-                value * 10,  # decidegree to centidegree
+                value * 100,  # degree to centidegree
             )
         elif attrid == MOESBHT_SCHEDULE_MODE_ATTR:
             if value == 0:  # value is inverted
@@ -144,6 +147,7 @@ class MoesBHT(TuyaThermostat):
             ("_TZE200_2ekuz3dz", "TS0601"),
             ("_TZE200_ye5jkfsb", "TS0601"),
             ("_TZE200_u9bfwha0", "TS0601"),
+            ("_TZE200_ztvwu4nk", "TS0601"),
         ],
         ENDPOINTS: {
             1: {

Now I just need to find the time to make this a bit more tidy and send a PR to see if this can be adopted

github-actions[bot] commented 11 months 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.