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
753 stars 693 forks source link

[BUG] New Zigbee Zemismart / Tuya Light Smart Switches TS0004 and TS0003 switch on and off as a group in Home Assistant - Physical buttons work fine #2443

Closed incognitto-indago closed 1 year ago

incognitto-indago commented 1 year ago

Bug description

I have been using Zha in HA for a while and have more than 10 smart switches. Recently, I have bought new Zemismart/Tuya Zigbee Light Switches (TS0004 and TS0003). Unlike my previous ones, each one of these new ones are switching on and off as group when I use the entities in Home Assistant. If I press the physical buttons on the switch, they do work well, and they turn on and off just the one I pressed. If I try to turn on or off just one button via Home Assistant, all the buttons on that switch will also turn on or off.

I have same-model switches that work fine here, but they were bought about year ago.

Steps to reproduce

  1. Add the zigbee switch (TS0004 or TS0003) to the zha integration ("+ Add Device" button)
  2. Turn on any entity on the switch in Home Assistant
  3. All buttons/gangs turn on (relay turn on sound) and show they indeed have turned on with light-emitting diodes
  4. In HA one can see that all entities/gangs/buttons on the switch are turned on too
  5. Turn off any entity/gang/button on Home Assistant and they all turn off the same way.

Expected behavior

If I turn on/off a single entity in Home Assistant, I expect to turn on/off only that respective one button at the switch

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

Device signature

TS0004 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": "0x0100", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "4": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZ3000_a37eix1s", "model": "TS0004", "class": "zigpy.device.Device" } ```
TS0003 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": "0x0100", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZ3000_empogkya", "model": "TS0003", "class": "zigpy.device.Device" } ```

Diagnostic information

TS0004 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/Sao_Paulo", "os_name": "Linux", "os_version": "6.1.34", "supervisor": "2023.06.2", "host_os": "Home Assistant OS 10.3", "docker_version": "23.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": { "deepstack_face": { "version": "0.9.0", "requirements": [ "pillow", "deepstack-python==0.8" ] }, "smartthinq_sensors": { "version": "0.31.8", "requirements": [ "pycountry>=20.7.3", "xmltodict>=0.12.0", "charset_normalizer>=2.0.0" ] }, "sonoff": { "version": "3.5.1", "requirements": [ "pycryptodome>=3.6.6" ] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "deepstack_object": { "version": "4.6.0", "requirements": [ "pillow", "deepstack-python==0.8" ] } }, "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": 55035, "manufacturer": "_TZ3000_a37eix1s", "model": "TS0004", "name": "_TZ3000_a37eix1s TS0004", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 108, "rssi": -73, "last_seen": "2023-06-26T14:55:40", "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": "0x0100", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "4": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZ3000_a37eix1s", "model": "TS0004" }, "active_coordinator": false, "entities": [ { "entity_id": "button.switch_zigbee_upstairs_hall_identify", "name": "_TZ3000_a37eix1s TS0004" }, { "entity_id": "light.switch_zigbee_upstairs_hall_light", "name": "_TZ3000_a37eix1s TS0004" }, { "entity_id": "light.switch_zigbee_upstairs_hall_light_2", "name": "_TZ3000_a37eix1s TS0004" }, { "entity_id": "light.switch_zigbee_upstairs_hall_light_3", "name": "_TZ3000_a37eix1s TS0004" }, { "entity_id": "light.switch_zigbee_upstairs_hall_light_4", "name": "_TZ3000_a37eix1s TS0004" }, { "entity_id": "sensor.tz3000_a37eix1s_ts0004_lqi", "name": "_TZ3000_a37eix1s TS0004" } ], "neighbors": [ { "device_type": "Coordinator", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0000", "permit_joining": "Unknown", "depth": "0", "lqi": "103" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x11F3", "permit_joining": "Unknown", "depth": "15", "lqi": "70" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x15AA", "permit_joining": "Unknown", "depth": "15", "lqi": "58" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x34E0", "permit_joining": "Unknown", "depth": "15", "lqi": "99" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x43FA", "permit_joining": "Unknown", "depth": "15", "lqi": "51" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x489A", "permit_joining": "Unknown", "depth": "15", "lqi": "68" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xA84B", "permit_joining": "Unknown", "depth": "15", "lqi": "131" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xC50B", "permit_joining": "Unknown", "depth": "15", "lqi": "146" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Parent", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xDCC1", "permit_joining": "Unknown", "depth": "15", "lqi": "176" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xF85C", "permit_joining": "Unknown", "depth": "15", "lqi": "37" } ], "routes": [ { "dest_nwk": "0xB545", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x43FA" }, { "dest_nwk": "0xF85C", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xF85C" }, { "dest_nwk": "0xDCC1", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0xDCC1" }, { "dest_nwk": "0x3C00", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x15AA" }, { "dest_nwk": "0x15AA", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x11F3" }, { "dest_nwk": "0x43FA", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x43FA" }, { "dest_nwk": "0x34E0", "route_status": "Active", "memory_constrained": false, "many_to_one": false, "route_record_required": false, "next_hop": "0x34E0" }, { "dest_nwk": "0x0000", "route_status": "Active", "memory_constrained": false, "many_to_one": true, "route_record_required": false, "next_hop": "0x0000" } ], "endpoint_names": [ { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": "Switch Zigbee Upstairs Hall", "device_reg_id": "b85539a5b5567a25e2f3ac2fd0e13cab", "area_id": "upstairs_hall", "cluster_details": { "1": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZ3000_a37eix1s" }, "0x0005": { "attribute_name": "model", "value": "TS0004" } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "3": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "4": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "242": { "device_type": { "name": "unknown", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```
TS0003 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/Sao_Paulo", "os_name": "Linux", "os_version": "6.1.34", "supervisor": "2023.06.2", "host_os": "Home Assistant OS 10.3", "docker_version": "23.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": { "deepstack_face": { "version": "0.9.0", "requirements": [ "pillow", "deepstack-python==0.8" ] }, "smartthinq_sensors": { "version": "0.31.8", "requirements": [ "pycountry>=20.7.3", "xmltodict>=0.12.0", "charset_normalizer>=2.0.0" ] }, "sonoff": { "version": "3.5.1", "requirements": [ "pycryptodome>=3.6.6" ] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "deepstack_object": { "version": "4.6.0", "requirements": [ "pillow", "deepstack-python==0.8" ] } }, "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": 21511, "manufacturer": "_TZ3000_empogkya", "model": "TS0003", "name": "_TZ3000_empogkya TS0003", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 100, "rssi": -75, "last_seen": "2023-06-26T14:50:10", "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": "0x0100", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xe000", "0xe001" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZ3000_empogkya", "model": "TS0003" }, "active_coordinator": false, "entities": [ { "entity_id": "button.switch_1a_zigbee_upstairs_bedroom_identify", "name": "_TZ3000_empogkya TS0003" }, { "entity_id": "light.switch_1a_zigbee_upstairs_bedroom_light", "name": "_TZ3000_empogkya TS0003" }, { "entity_id": "light.switch_1a_zigbee_upstairs_bedroom_light_2", "name": "_TZ3000_empogkya TS0003" }, { "entity_id": "light.switch_1a_zigbee_upstairs_bedroom_light_3", "name": "_TZ3000_empogkya TS0003" } ], "neighbors": [], "routes": [ { "dest_nwk": "0x0000", "route_status": "Active", "memory_constrained": false, "many_to_one": true, "route_record_required": false, "next_hop": "0x0000" } ], "endpoint_names": [ { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": "Switch 1A Zigbee Upstairs Bedroom", "device_reg_id": "7b4298d9d85114214ed3a7379dd2a044", "area_id": "upstairs_bedroom", "cluster_details": { "1": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZ3000_empogkya" }, "0x0005": { "attribute_name": "model", "value": "TS0003" } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "3": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xe000": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0xe001": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "242": { "device_type": { "name": "unknown", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

Logs ```python [Paste the logs here] ```

Additional information

No response

TheJulianJES commented 1 year ago

You can test this custom quirk for the TS0004 (how to install):

(Copy + paste the Python stuff below into a file like ts0004_custom_quirk.py, put that in your custom quirk folder, restart HA, re-pair the switch and see if it works.)

Possible custom quirk to test ```python """tuya TS000X Switches (CUSTOM QUIRK TEST: https://github.com/zigpy/zha-device-handlers/issues/2443).""" from zigpy.profiles import zgp, zha from zigpy.zcl.clusters.general import ( Basic, GreenPowerProxy, Groups, Identify, OnOff, Ota, Scenes, Time, ) from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODEL, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, TuyaZBOnOffAttributeCluster, ) from zhaquirks.tuya.mcu import EnchantedDevice class Switch_4G_GPP_Var2(EnchantedDevice): """Tuya 4 gang switch module with.""" signature = { MODEL: "TS0004", ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 242: { PROFILE_ID: zgp.PROFILE_ID, DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC, INPUT_CLUSTERS: [], OUTPUT_CLUSTERS: [ GreenPowerProxy.cluster_id, ], }, }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 242: { PROFILE_ID: zgp.PROFILE_ID, DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC, INPUT_CLUSTERS: [], OUTPUT_CLUSTERS: [ GreenPowerProxy.cluster_id, ], }, }, } ```
incognitto-indago commented 1 year ago

Hello.

Thanks for helping me.

About the custom quirk, after the restart, the quirk did not load properly, I believe. I got the following error in the logs:

` Logger: zhaquirks Source: custom_zha_quirks/ts0004_custom_quirk.py:3 First occurred: 8:14:51 AM (1 occurrences) Last logged: 8:14:51 AM

Unexpected exception importing custom quirk 'ts0004_custom_quirk' Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/zhaquirks/init.py", line 454, in setup importer.find_module(modname).load_module(modname) File "", line 605, in _check_name_wrapper File "", line 1120, in load_module File "", line 945, in load_module File "", line 290, in _load_module_shim File "", line 721, in _load File "", line 690, in _load_unlocked File "", line 940, in exec_module File "", line 241, in _call_with_frames_removed File "/config/custom_zha_quirks/ts0004_custom_quirk.py", line 3, in from zigpy.profiles import zgp, zha ImportError: cannot import name 'zgp' from 'zigpy.profiles' (/usr/local/lib/python3.11/site-packages/zigpy/profiles/init.py) `

MattWestb commented 1 year ago

@incognitto-indago Is you running HA 2023.6.X ? The ZGP was implanted as one function in that and is needed for getting the ZGP cluster that your device is having.

Edit: I see 2023.6.3 in your log so it shall not being the problem.

TheJulianJES commented 1 year ago

Ah, right. It'll only be in the next major HA version.

Try this modified version:

Possible custom quirk to test (for older HA versions) ```python """tuya TS000X Switches (CUSTOM QUIRK TEST: https://github.com/zigpy/zha-device-handlers/issues/2443).""" from zigpy.profiles import zha from zigpy.zcl.clusters.general import ( Basic, GreenPowerProxy, Groups, Identify, OnOff, Ota, Scenes, Time, ) from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODEL, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, TuyaZBOnOffAttributeCluster, ) from zhaquirks.tuya.mcu import EnchantedDevice class Switch_4G_GPP_Var2(EnchantedDevice): """Tuya 4 gang switch module with.""" signature = { MODEL: "TS0004", ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 242: { 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.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 242: { PROFILE_ID: 41440, DEVICE_TYPE: 97, INPUT_CLUSTERS: [], OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], }, }, } ```
incognitto-indago commented 1 year ago

Yes, indeed, I am running 2023.6.3.

The enviroment is:

Home Assistant 2023.6.3 Supervisor 2023.06.2 Operating System 10.3 Frontend 20230608.0 - latest

incognitto-indago commented 1 year ago

Will test it now.

Ah, right. It'll only be in the next major HA version.

Try this modified version:

Possible custom quirk to test (for older HA versions)

MattWestb commented 1 year ago

Your HA is having ziogpy 0.55.0 and the function was implanted in https://github.com/zigpy/zigpy/releases/tag/0.56.0 so i dont understanding way other quirks is working but your is not. @TheJulianJES any clue ?

incognitto-indago commented 1 year ago

It worked!!!!

Will test it now.

Ah, right. It'll only be in the next major HA version. Try this modified version: Possible custom quirk to test (for older HA versions)

incognitto-indago commented 1 year ago

Now, can we apply the same reasoning for TS0003?

TheJulianJES commented 1 year ago

Try to paste the below code at the end of your custom quirk file:

Possible additional code for TS0003 ```python class Switch_3G_GPP_Var2(EnchantedDevice): """Tuya 3 gang switch module.""" signature = { MODEL: "TS0003", ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, OnOff.cluster_id, 0xE000, 0xE001, ], OUTPUT_CLUSTERS: [], }, 242: { 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.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [ Time.cluster_id, Ota.cluster_id, ], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Identify.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaZBOnOffAttributeCluster, TuyaZBE000Cluster, TuyaZBExternalSwitchTypeCluster, ], OUTPUT_CLUSTERS: [], }, 242: { PROFILE_ID: 41440, DEVICE_TYPE: 97, INPUT_CLUSTERS: [], OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], }, }, } ```
incognitto-indago commented 1 year ago

It worked as well.

Thanks a lot again!

Should I do anything else? Will I always need the custom quirk?

Try to paste the below code at the end of your custom quirk file:

Possible additional code for TS0003

class Switch_3G_GPP_Var2(EnchantedDevice):
    """Tuya 3 gang switch module."""

    signature = {
        MODEL: "TS0003",
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    0xE000,
                    0xE001,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    0xE000,
                    0xE001,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    0xE000,
                    0xE001,
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                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.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [
                    Time.cluster_id,
                    Ota.cluster_id,
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaZBOnOffAttributeCluster,
                    TuyaZBE000Cluster,
                    TuyaZBExternalSwitchTypeCluster,
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 97,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }
TheJulianJES commented 1 year ago

If https://github.com/zigpy/zha-device-handlers/pull/2445 gets merged, the next zha-quirks release is made, the library gets bumped in the HA Core repo, and a new HA core version is released, the quirk will be included and you should delete your custom quirk.

We should be able to get it in for the next major HA beta releasing tomorrow (2023.7.x).

If anyone can have a quick look at the PR to see if everything's fine, that would be great too.

incognitto-indago commented 1 year ago

Thanks!

Should I close this issue now?

If #2445 gets merged, the next zha-quirks release is made, the library gets bumped in the HA Core repo, and a new HA core version is released, the quirk will be included and you should delete your custom quirk.

We should be able to get it in for the next major HA beta releasing tomorrow (2023.7.x).

If anyone can have a quick look at the PR to see if everything's fine, that would be great too.

airtonac commented 1 year ago

If #2445 gets merged, the next zha-quirks release is made, the library gets bumped in the HA Core repo, and a new HA core version is released, the quirk will be included and you should delete your custom quirk.

We should be able to get it in for the next major HA beta releasing tomorrow (2023.7.x).

If anyone can have a quick look at the PR to see if everything's fine, that would be great too.

Hello,

So I bought both switches (TS0003 and TS0004) from the Zemismart store on Ali Express. I managed to make the TS0004 work perfectly using the quirk given as example. I added a TS0004.py to the custom_zha_quirks folder and added this lines to configuration. yaml:

zha: custom_quirks_path: /config/custom_zha_quirks/ enable_quirks: true

For some reason the quirk for the 3-gang version didn't work out of the box for me. Do I have to do something for ZHA to know I'm using a handler or the device should just work? Do I have to create any folder to be able to use handlers that were included to the main branch? I've just moved to ZHA from Z2M, so I'm a bit puzzled.

I tried to do the same process I did to the 4-gang device to the 3-gang version, but the switches are still all grouped on HA. I even tried a TS000X.py file that contained instructions for both devices and still only the 4-gang one works as expected (switches turn on and off individually on HA). Please check below the file I replaced the TS0004.py with (TS000X.py):

FUNNY PART IS EVEN IF I DELETE ALL QUIRKS FROM THE custom_zha_quirks FOLDER AND ALSO CLEARED THE CACHE FOLDER, THE 4-GANG STILL WORKS PERFECTLY. (BUT NOT THE 3-GANG DEVICE) Very confusing... Any help would be very much appreciated.

Thanks, Airton

`"""tuya TS000X Switches."""

from zigpy.profiles import zgp, zha from zigpy.zcl.clusters.general import ( Basic, GreenPowerProxy, Groups, Identify, OnOff, Ota, Scenes, Time, )

from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODEL, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import ( TuyaZBE000Cluster, TuyaZBElectricalMeasurement, TuyaZBExternalSwitchTypeCluster, TuyaZBMeteringCluster, TuyaZBOnOffAttributeCluster, ) from zhaquirks.tuya.mcu import EnchantedDevice

class Switch_1G_GPP(EnchantedDevice): """Tuya 1 gang switch module with restore power state support."""

signature = {
    MODEL: "TS0001",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=266 device_type=256
        # device_version=1
        # input_clusters=[0, 3, 4, 5, 6, 57344, 57345]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=1
        # input_clusters=[]
        # output_clusters=[33]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
    },
}

class Switch_1G_Metering(EnchantedDevice): """Tuya 1 gang switch with metering support."""

signature = {
    MODEL: "TS0001",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=266 device_type=256
        # input_clusters=["0x0000","0x0003","0x0004","0x0005","0x0006","0x0702","0x0b04","0xe000","0xe001"]
        # output_clusters=["0x000a","0x0019"]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBMeteringCluster.cluster_id,
                TuyaZBElectricalMeasurement.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=1
        # input_clusters=[]
        # output_clusters=["0x0021"]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBMeteringCluster,
                TuyaZBElectricalMeasurement,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
    },
}

class Switch_2G_GPP(EnchantedDevice): """Tuya 2 gang switch module with restore power state support."""

signature = {
    MODEL: "TS0002",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # device_version=1
        # input_clusters=[0, 3, 4, 5, 6, 57344, 57345]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=[33]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_2G_Metering(EnchantedDevice): """Tuya 2 gang switch with metering support."""

signature = {
    MODEL: "TS0002",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # input_clusters=["0x0000","0x0003","0x0004","0x0005","0x0006","0x0702","0x0b04","0xe000","0xe001"]
        # output_clusters=["0x000a", "0x0019"]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBMeteringCluster.cluster_id,
                TuyaZBElectricalMeasurement.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=["0x0021"]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBMeteringCluster,
                TuyaZBElectricalMeasurement,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_2G_Var03(EnchantedDevice): """Tuya 2 gang (variation 03)."""

signature = {
    MODEL: "TS0002",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # device_version=1
        # input_clusters=[0, 3, 4, 5, 6, 57344, 57345]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # device_version=1
        # input_clusters=[3, 4, 5, 6, 57344, 57345]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=[33]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_3G_GPP(EnchantedDevice): """Tuya 3 gang switch module with restore power state support."""

signature = {
    MODEL: "TS0003",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # device_version=1
        # input_clusters=[0, 3, 4, 5, 6, 57344, 57345]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=3 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=[33]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_3G_Metering(EnchantedDevice): """Tuya 3 gang switch with metering support."""

signature = {
    MODEL: "TS0003",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # input_clusters=["0x0000","0x0003","0x0004","0x0005","0x0006","0x0702","0x0b04","0xe000","0xe001"]
        # output_clusters=["0x000a", "0x0019"]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBMeteringCluster.cluster_id,
                TuyaZBElectricalMeasurement.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=["0x0021"]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBMeteringCluster,
                TuyaZBElectricalMeasurement,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_3G_GPP_Var2(EnchantedDevice): """Tuya 3 gang switch module."""

signature = {
    MODEL: "TS0003",
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_4G_GPP(EnchantedDevice): """Tuya 4 gang switch module with restore power state support."""

signature = {
    MODEL: "TS0004",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # device_version=1
        # input_clusters=[0, 3, 4, 5, 6, 57344, 57345]
        # output_clusters=[10, 25]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=3 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=3 profile=260 device_type=256
        # device_version=1
        # input_clusters=[4, 5, 6, 57345]
        # output_clusters=[]>
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=[33]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_4G_Metering(EnchantedDevice): """Tuya 4 gang switch with metering support."""

signature = {
    MODEL: "TS0004",
    ENDPOINTS: {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=256
        # input_clusters=["0x0000","0x0003","0x0004","0x0005","0x0006","0x0702","0x0b04","0xe000","0xe001"]
        # output_clusters=["0x000a", "0x0019"]>
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                TuyaZBMeteringCluster.cluster_id,
                TuyaZBElectricalMeasurement.cluster_id,
                TuyaZBE000Cluster.cluster_id,
                TuyaZBExternalSwitchTypeCluster.cluster_id,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=2 profile=260 device_type=256
        # input_clusters=["0x0004", "0x0005", "0x0006"]
        # output_clusters=[]>
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
            ],
            OUTPUT_CLUSTERS: [],
        },
        # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
        # device_version=0
        # input_clusters=[]
        # output_clusters=["0x0021"]>
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}
replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBMeteringCluster,
                TuyaZBElectricalMeasurement,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

class Switch_4G_GPP_Var2(EnchantedDevice): """Tuya 4 gang switch module."""

signature = {
    MODEL: "TS0004",
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [],
        },
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                OnOff.cluster_id,
                0xE000,
                0xE001,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}

replacement = {
    ENDPOINTS: {
        1: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Basic.cluster_id,
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [
                Time.cluster_id,
                Ota.cluster_id,
            ],
        },
        2: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        3: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        4: {
            PROFILE_ID: zha.PROFILE_ID,
            DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
            INPUT_CLUSTERS: [
                Identify.cluster_id,
                Groups.cluster_id,
                Scenes.cluster_id,
                TuyaZBOnOffAttributeCluster,
                TuyaZBE000Cluster,
                TuyaZBExternalSwitchTypeCluster,
            ],
            OUTPUT_CLUSTERS: [],
        },
        242: {
            PROFILE_ID: zgp.PROFILE_ID,
            DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
            INPUT_CLUSTERS: [],
            OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
        },
    },
}`
TheJulianJES commented 1 year ago

@airtonac Please open a new issue for each switch, as it's easier to track (and provide the custom quirk code again).

The "spell" is only required once, hence the device now works without the quirk. It should still have the quirk though, as the "spell" may get lost when re-pairing and/or power-cycling the device.

The three gang one might have an issue in the quirk (again, separate issue for this please).