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
734 stars 673 forks source link

[Device Support Request] custom quirk for Tuya Zemismart blind cover motor TS0601 _TZE200_68nvbio9 with battery #3118

Open stast1 opened 5 months ago

stast1 commented 5 months ago

Problem description

No battery charge display for Tuya Zemismart blind cover motor TS0601 _TZE200_68nvbio9

Solution description

Add battery charge display

Custom quirk

Custom quirk ```python """Tuya based cover and blinds.""" from typing import Optional, Union from zigpy.profiles import zha import zigpy.types as t from zigpy.zcl import foundation from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time from zhaquirks import Bus from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( TuyaManufacturerWindowCover, TuyaManufCluster, TuyaPowerConfigurationCluster, TuyaWindowCover, TuyaWindowCoverControl, TUYA_GET_DATA, TUYA_SET_DATA_RESPONSE, TUYA_DP_TYPE_VALUE, ) TUYA_DP_ID_BATTERY = 0x0D class TuyaZemismartManufacturerWindowCover(TuyaManufacturerWindowCover): """Manufacturer Specific Cluster for Zemismart cover device.""" def handle_cluster_request( self, hdr: foundation.ZCLHeader, args: tuple[TuyaManufCluster.Command], *, dst_addressing: Optional[ Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK] ] = None, ) -> None: """Handle cluster request.""" # Tuya Zemismart Specific Cluster Commands if ( hdr.command_id in (TUYA_GET_DATA, TUYA_SET_DATA_RESPONSE) and args[0].command_id == TUYA_DP_TYPE_VALUE + TUYA_DP_ID_BATTERY ): self.endpoint.device.battery_bus.listener_event( "battery_change", args[0].data[4], ) else: super().handle_cluster_request(hdr, args, dst_addressing=dst_addressing) class TuyaZemismartSmartCover0601_battery(TuyaWindowCover): """Tuya Zemismart blind cover motor.""" def __init__(self, *args, **kwargs): """Init device.""" self.battery_bus = Bus() super().__init__(*args, **kwargs) signature = { # "node_descriptor": "NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=128, manufacturer_code=4098, # maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, # maximum_outgoing_transfer_size=82, descriptor_capability_field=0)", # "endpoints": { # "1": { "profile_id": 260, "device_type": "0x0051", "in_clusters": [ "0x0000", "0x0004","0x0005","0xef00"], "out_clusters": ["0x000a","0x0019"] } # }, # "manufacturer": "_TZE200_zah67ekd", # "model": "TS0601", # "class": "zigpy.device.Device" # } MODELS_INFO: [ ("_TZE200_68nvbio9", "TS0601"), ], ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZemismartManufacturerWindowCover, TuyaPowerConfigurationCluster, TuyaWindowCoverControl, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } } } ```

Additional information

I have added support for displaying battery charge for _TZE200_68nvbio9. May be suitable for other motors with batteries. You just need to change _TZE200_68nvbio9 to your model. Haven't tested the charge updates yet, shows 100%

sushant-here commented 5 months ago

I can definitely confirm that this is reporting something that looks like a battery percentage on a TS0601 _TZE200_68nvbio9. That said... one of my blinds has been plugged in to charger for the last 2 days (so it should be 100%). This quirk is reporting 90% battery.

Blind is 2 years old and has been charged 4-5 times. Not sure if its somehow related to battery degradation.

Other blinds which have not been charged for months are showing lower state of charge (as expected).

Something is better then nothing - I think this can be (cleaned up?) and merged for the wider community to use.

stast1 commented 5 months ago

Tested - the charge data changes.

flybrys commented 4 months ago

Just wanted to say thanks so much for this quirk. Lost the battery moving from Z2M and now it's back! Hopefully it gets added to the main repo

Maks1983 commented 2 months ago

Thnak you, this works good!