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
759 stars 697 forks source link

[Device Support Request] Tuya TS0601 with 8 gangs #2492

Closed gkawanami closed 1 year ago

gkawanami commented 1 year ago

Problem description

Hey to all!

I have recently paired a Tuya TS0601 with 8 gangs, bought at Aliexpress, and using instructions in the previously reported issue the manufacturer was included and I was able to get 6 of the 8 buttons to work. The last two are still not responsive thru HA. (Physically working, but not reported to HA).

Running Home Assistant 2023.7.3 Supervisor 2023.07.1 Operating System 10.3 Frontend 20230705.1 - latest Device: Micro PC - Generic x86-64 ZHA thru Sonoff dongle E (flashed)

Solution description

How can I make the last two button work?

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0x0004", "0x0005", "0x0006", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "4": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "5": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "6": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "7": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "8": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZE200_wktrysab", "model": "TS0601", "class": "ts0601_switch.TuyaOctapleSwitchTO_GP" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.7.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.4", "docker": true, "arch": "x86_64", "timezone": "America/Sao_Paulo", "os_name": "Linux", "os_version": "6.1.34", "supervisor": "2023.07.1", "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" ] } }, "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.8", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.101", "zigpy-deconz==0.21.0", "zigpy==0.56.2", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.3" ], "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": 42830, "manufacturer": "_TZE200_wktrysab", "model": "TS0601", "name": "_TZE200_wktrysab TS0601", "quirk_applied": true, "quirk_class": "ts0601_switch.TuyaOctapleSwitchTO_GP", "manufacturer_code": 4417, "power_source": "Mains", "lqi": 108, "rssi": -73, "last_seen": "2023-07-27T21:38:51", "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=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, 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", "0x0004", "0x0005", "0x0006", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "4": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "5": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "6": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "7": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "8": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0006" ], "output_clusters": [] }, "242": { "profile_id": "0xa1e0", "device_type": "0x0061", "input_clusters": [], "output_clusters": [ "0x0021" ] } }, "manufacturer": "_TZE200_wktrysab", "model": "TS0601" }, "active_coordinator": false, "entities": [ { "entity_id": "light.sw_porta_de_cima_light", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_2", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_3", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_4", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_5", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_6", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_7", "name": "_TZE200_wktrysab TS0601" }, { "entity_id": "light.sw_porta_de_cima_light_8", "name": "_TZE200_wktrysab TS0601" } ], "neighbors": [ { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Parent", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x081D", "permit_joining": "Unknown", "depth": "1", "lqi": "81" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x8008", "permit_joining": "Unknown", "depth": "2", "lqi": "75" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xE30E", "permit_joining": "Unknown", "depth": "3", "lqi": "69" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x1922", "permit_joining": "Unknown", "depth": "1", "lqi": "30" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x380E", "permit_joining": "Unknown", "depth": "1", "lqi": "42" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xEBE3", "permit_joining": "Unknown", "depth": "1", "lqi": "27" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xBED5", "permit_joining": "Unknown", "depth": "1", "lqi": "48" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xBACA", "permit_joining": "Unknown", "depth": "3", "lqi": "33" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xD0D3", "permit_joining": "Unknown", "depth": "1", "lqi": "45" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x206D", "permit_joining": "Unknown", "depth": "1", "lqi": "69" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x570F", "permit_joining": "Unknown", "depth": "2", "lqi": "27" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0238", "permit_joining": "Unknown", "depth": "2", "lqi": "15" }, { "device_type": "Coordinator", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0000", "permit_joining": "Unknown", "depth": "0", "lqi": "33" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x2535", "permit_joining": "Unknown", "depth": "1", "lqi": "15" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Child", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x3FF5", "permit_joining": "Unknown", "depth": "3", "lqi": "48" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x73B3", "permit_joining": "Unknown", "depth": "1", "lqi": "24" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xC74F", "permit_joining": "Unknown", "depth": "2", "lqi": "63" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x1842", "permit_joining": "Unknown", "depth": "1", "lqi": "12" }, { "device_type": "EndDevice", "rx_on_when_idle": "Off", "relationship": "Child", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x71ED", "permit_joining": "Unknown", "depth": "3", "lqi": "103" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xD0C2", "permit_joining": "Unknown", "depth": "2", "lqi": "45" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x73DB", "permit_joining": "Unknown", "depth": "2", "lqi": "94" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x15D2", "permit_joining": "Unknown", "depth": "2", "lqi": "21" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x7265", "permit_joining": "Unknown", "depth": "3", "lqi": "45" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x7701", "permit_joining": "Unknown", "depth": "3", "lqi": "42" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xB423", "permit_joining": "Unknown", "depth": "1", "lqi": "45" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x2078", "permit_joining": "Unknown", "depth": "4", "lqi": "48" } ], "routes": [], "endpoint_names": [ { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" }, { "name": "PROXY_BASIC" } ], "user_given_name": "SW - sala de cima (porta)", "device_reg_id": "7adcce3529caaff783c75ceac1175160", "area_id": "sala_de_cima", "cluster_details": { "1": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0001": { "attribute_name": "app_version", "value": 70 }, "0x0004": { "attribute_name": "manufacturer", "value": "_TZE200_wktrysab" }, "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": "tuya_manufacturer", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 1 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": { "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} }, "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 1 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "3": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 1 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "4": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "5": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "6": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 1 } }, "unsupported_attributes": { "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "7": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": {}, "unsupported_attributes": { "0x0000": { "attribute_name": "on_off" }, "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "8": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0006": { "endpoint_attribute": "on_off", "attributes": {}, "unsupported_attributes": { "0x0000": { "attribute_name": "on_off" }, "0x4003": { "attribute_name": "start_up_on_off" } } } }, "out_clusters": {} }, "242": { "device_type": { "name": "PROXY_BASIC", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```

Logs

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

Custom quirk

Custom quirk ```python """Tuya DP based switches.""" from zigpy.profiles import zgp, zha from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import TuyaSwitch from zhaquirks.tuya.mcu import ( MoesSwitchManufCluster, TuyaOnOff, TuyaOnOffManufCluster, TuyaOnOffNM, ) class TuyaSingleSwitchTI(TuyaSwitch): """Tuya single channel switch time on in cluster device.""" signature = { # "node_descriptor": "", # device_version=1 # input_clusters=[0x0000,0x0004, 0x0005,0x000a, 0xef00] # output_clusters=[0x0019] # MODELS_INFO: [("_TZE200_7tdtqgwv", "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, Time.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Time.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Ota.cluster_id], } } } class TuyaSingleSwitchTO(TuyaSwitch): """Tuya single channel switch time on out cluster device.""" signature = { # "node_descriptor": "", # device_version=1 # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00] # output_clusters=[0x000a, 0x0019] # MODELS_INFO: [ ("_TZE200_amp6tsvy", "TS0601"), ("_TZE200_oisqyl4o", "TS0601"), ("_TZE200_vhy3iakz", "TS0601"), # ¿1 or 4 gangs? ("_TZ3000_uim07oem", "TS0601"), # ¿1 or 4 gangs? ("_TZE200_wfxuhoea", "TS0601"), ("_TZE200_tviaymwx", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } } } class TuyaSingleSwitch_GP(TuyaSwitch): """Tuya single channel switch with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_gbagoilo", "TS0601"), # reported in #1634 ], ENDPOINTS: { # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # ", # device_version=1 # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00] # output_clusters=[0x000a, 0x0019] # MODELS_INFO: [ ("_TZE200_g1ib5ldv", "TS0601"), ("_TZE200_wunufsil", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOff, ], OUTPUT_CLUSTERS: [], }, } } class TuyaDoubleSwitch_GP(TuyaSwitch): """Tuya double channel switch with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_7deq70b8", "TS0601"), ("_TZE200_nh9m9emk", "TS0601"), # reported in #1634 ], ENDPOINTS: { # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # MODELS_INFO: [ ("_TZE200_cduqh1l0", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster, TuyaOnOffNM, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 5: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 6: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, } } class TuyaSextupleSwitchTO_GP(TuyaSwitch): """Tuya sextuple channel switch time on out cluster device with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_cduqh1l0", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # MODELS_INFO: [ ("_TZE200_wktrysab", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster, TuyaOnOffNM, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 5: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 6: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 7: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 8: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, } } class TuyaOctapleSwitchTO_GP(TuyaSwitch): """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_wktrysab", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, #

Additional information

No response

javicalle commented 1 year ago

I don't know how have you implemented the TuyaOctapleSwitchTO_GP quirk (there are no reference in the related issue) but to make the 8 buttons work, the TuyaOnOffManufCluster class needs to be extended adding the adicional DPs:

gkawanami commented 1 year ago

Hey @javicalle !

Thanks for the answer.
I'm a total mess with this thing....

I tried inserting lines 404 to the end at "#### New Edit by Gus ####" position but that didn't work

Where should I insert these lines?

javicalle commented 1 year ago

Just for testing purposes you can try with:

TuyaOnOffManufCluster_8 ```python class TuyaOnOffManufCluster_8(TuyaMCUCluster): """Tuya with On/Off data points.""" dp_to_attribute: Dict[int, DPToAttributeMapping] = { 1: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", ), 2: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=2, ), 3: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=3, ), 4: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=4, ), 5: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=5, ), 6: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=6, ), 7: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=7, ), 8: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=8, ), } data_point_handlers = { 1: "_dp_2_attr_update", 2: "_dp_2_attr_update", 3: "_dp_2_attr_update", 4: "_dp_2_attr_update", 5: "_dp_2_attr_update", 6: "_dp_2_attr_update", 7: "_dp_2_attr_update", 8: "_dp_2_attr_update", } ```

You would need at least also import the DPToAttributeMapping and TuyaMCUCluster classes:

from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    MoesSwitchManufCluster,
    TuyaMCUCluster,
    TuyaOnOff,
    TuyaOnOffManufCluster,
    TuyaOnOffNM,
)

Also the Dict one:

from typing import Dict

Then, your quirk will be something like:

TuyaOctapleSwitchTO_GP ```python class TuyaOctapleSwitchTO_GP(TuyaSwitch): """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_wktrysab", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, #

The TuyaOnOffManufCluster_8 must be upper in file than the quirk. Be sure to delete any __pycache__ folder from your local quirk folder.

gkawanami commented 1 year ago

Hi @javicalle

Edited the quirk file (below) but still no response from the last two buttons.

I inserted the dict reference, but I don't know if I got what to do with it. Put it just below thezhaquirks import, in the beginning of the file.

Restarted and still non responsive buttons.

What am I doing wrong?

Code (click to expand) ```python """Tuya DP based switches.""" from zigpy.profiles import zgp, zha from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import TuyaSwitch from zhaquirks.tuya.mcu import ( DPToAttributeMapping, MoesSwitchManufCluster, TuyaMCUCluster, TuyaOnOff, TuyaOnOffManufCluster, TuyaOnOffNM, ) from typing import Dict class TuyaSingleSwitchTI(TuyaSwitch): """Tuya single channel switch time on in cluster device.""" signature = { # "node_descriptor": "", # device_version=1 # input_clusters=[0x0000,0x0004, 0x0005,0x000a, 0xef00] # output_clusters=[0x0019] # MODELS_INFO: [("_TZE200_7tdtqgwv", "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, Time.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Time.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Ota.cluster_id], } } } class TuyaSingleSwitchTO(TuyaSwitch): """Tuya single channel switch time on out cluster device.""" signature = { # "node_descriptor": "", # device_version=1 # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00] # output_clusters=[0x000a, 0x0019] # MODELS_INFO: [ ("_TZE200_amp6tsvy", "TS0601"), ("_TZE200_oisqyl4o", "TS0601"), ("_TZE200_vhy3iakz", "TS0601"), # ¿1 or 4 gangs? ("_TZ3000_uim07oem", "TS0601"), # ¿1 or 4 gangs? ("_TZE200_wfxuhoea", "TS0601"), ("_TZE200_tviaymwx", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } } } class TuyaSingleSwitch_GP(TuyaSwitch): """Tuya single channel switch with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_gbagoilo", "TS0601"), # reported in #1634 ], ENDPOINTS: { # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # ", # device_version=1 # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00] # output_clusters=[0x000a, 0x0019] # MODELS_INFO: [ ("_TZE200_g1ib5ldv", "TS0601"), ("_TZE200_wunufsil", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, MoesSwitchManufCluster, TuyaOnOff, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOff, ], OUTPUT_CLUSTERS: [], }, } } class TuyaDoubleSwitch_GP(TuyaSwitch): """Tuya double channel switch with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_7deq70b8", "TS0601"), ("_TZE200_nh9m9emk", "TS0601"), # reported in #1634 ], ENDPOINTS: { # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # MODELS_INFO: [ ("_TZE200_cduqh1l0", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster, TuyaOnOffNM, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, 2: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 3: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 4: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 5: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, 6: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, INPUT_CLUSTERS: [ TuyaOnOffNM, ], OUTPUT_CLUSTERS: [], }, } } class TuyaSextupleSwitchTO_GP(TuyaSwitch): """Tuya sextuple channel switch time on out cluster device with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_cduqh1l0", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, # 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Groups.cluster_id, Scenes.cluster_id, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, #
javicalle commented 1 year ago

Despite hard to read, your code looks good to me. Any error in your logs? It could be a format error in your file. The startup log would tell us if there is something wrong.

There is a simplified version for your quirk:

ts0601_switch_8.py ```python """Tuya DP based switches.""" from zigpy.profiles import zgp, zha from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import TuyaSwitch from zhaquirks.tuya.mcu import ( DPToAttributeMapping, MoesSwitchManufCluster, TuyaMCUCluster, TuyaOnOff, TuyaOnOffManufCluster, TuyaOnOffNM, ) from typing import Dict class TuyaOnOffManufCluster_8(TuyaMCUCluster): """Tuya with On/Off data points.""" dp_to_attribute: Dict[int, DPToAttributeMapping] = { 1: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", ), 2: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=2, ), 3: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=3, ), 4: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=4, ), 5: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=5, ), 6: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=6, ), 0x65: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=7, ), 0x66: DPToAttributeMapping( TuyaOnOff.ep_attribute, "on_off", endpoint_id=8, ), } data_point_handlers = { 1: "_dp_2_attr_update", 2: "_dp_2_attr_update", 3: "_dp_2_attr_update", 4: "_dp_2_attr_update", 5: "_dp_2_attr_update", 6: "_dp_2_attr_update", 0x65: "_dp_2_attr_update", 0x66: "_dp_2_attr_update", } class TuyaOctapleSwitchTO_GP(TuyaSwitch): """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_wktrysab", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, #

Once again, be sure to delete any __pycache__ folder in your local quirk folder.

Save changes and restart HA. Check the startup logs for errors.

EDIT: fix code indentation EDIT2: fixed 7's & 8's DPs

gkawanami commented 1 year ago

Hi @javicalle

I decided to remove the previous file (the ones that make the 4 and 6 gang switches work), and created a new file in my quirks folder with just the "simplified version" you sent me in your last message. Restarted. After that I uploaded the original quirk file and substituted the entire “8 gang” portion with your last message’s “simplified version”, restarted again. Removed the modified file and re-uploaded the original quirk file. Restarted.

The 3 methods made the same following error show up:

Invalid entity ID at position 2: start type: logbook entities:

  • light.sw_porta_de_cima_light_7
  • light.sw_porta_de_cima_light_8
  • start
  • update.home_assistant_operating_system_update title: LOGS

None os the 8 gangs are "lit" or are clickable on integration/devices screen. Pressing "reconfigure" shows no errors, but makes no difference in allowing me to click any of the gangs. They only become lit and are clickable with the original quirk file (the one on my first post)

Please help!

btw: no subfolders in my quirks folder, just my usual 3 files.

javicalle commented 1 year ago

Just to be sure: my 'simplified version' must be the full content of the quirk file. You can delete your current quirk file (or rename with a diferent extension) and put another file (the name doesn't matter) with that content.

Check for errors in the homeassistant.log file. If there are format errors in file the logs will tell to you. Put your logs and comments inside ``` marks:

All your code/comments/logs here

gkawanami commented 1 year ago

Hi again @javicalle

OK, renamed all the extensions to .inactive Created one new "JaviCalleFile.py" with just the copied "simplified version".

Log:

2023-08-01 11:55:29.237 WARNING (SyncWorker_4) [homeassistant.loader] We found a custom integration hacs which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2023-08-01 11:55:40.080 ERROR (MainThread) [zhaquirks] Unexpected exception importing custom quirk 'JaviCalleFile'
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 "<frozen importlib._bootstrap_external>", line 605, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1120, in load_module
  File "<frozen importlib._bootstrap_external>", line 945, in load_module
  File "<frozen importlib._bootstrap>", line 290, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 721, in _load
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 936, in exec_module
  File "<frozen importlib._bootstrap_external>", line 1074, in get_code
  File "<frozen importlib._bootstrap_external>", line 1004, in source_to_code
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/config/custom_zha_quirks/JaviCalleFile.py", line 84
    """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device."""
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after class definition on line 83
2023-08-01 11:55:40.759 ERROR (bellows.thread_0) [bellows.uart] CRC error in frame b'51a8bd7e' (b'a8bd' != b'ab24')

None of the TS0601 (6 ou 8 gangs) are responding. Clicking reconfigure results in:

The device reconfiguration failed. Additional information may be available in the logs.
javicalle commented 1 year ago

The class is not loading because the code error. I have updated the code but you need just to indent the TuyaOctapleSwitchTO_GP comment like this:

class TuyaOctapleSwitchTO_GP(TuyaSwitch):
    """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device."""

    signature = {
        MODELS_INFO: [
            ("_TZE200_wktrysab", "TS0601"),
        ],
        .../...

Save changes, restart HA and pair it again.

gkawanami commented 1 year ago

Made the changes.

In the end, the resulting section is:


    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        5: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        7: "_dp_2_attr_update",
        8: "_dp_2_attr_update",
    }

class TuyaOctapleSwitchTO_GP(TuyaSwitch):
    """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device."""

    signature = {
        MODELS_INFO: [
            ("_TZE200_wktrysab", "TS0601"),
        ],

        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=81
            # input_clusters=[0x0000,0x0004,0x0005,0xEF00]
            # output_clusters=[0x000A,0x0019]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaOnOffManufCluster.cluster_id,
                ],

Restarted, repaired. The lights are now clickable at the devices screen; but clicking the last 2 buttons still don't get transmitted to the wall switch.

Logs:

2023-08-01 16:31:31.212 WARNING (MainThread) [zhaquirks] Loaded custom quirks. Please contribute them to https://github.com/zigpy/zha-device-handlers
2023-08-01 16:31:32.420 ERROR (bellows.thread_0) [bellows.uart] CRC error in frame b'f4df5589fd7e3fa7ebcd02457e' (b'0245' != b'56e4')
2023-08-01 16:31:32.421 ERROR (bellows.thread_0) [bellows.uart] CRC error in frame b'1bc3b1a90d2aee2eebcdda86987e' (b'8698' != b'619b')

@javicalle thanks for the help so far... I know its taking you some time.. Anything else I could try?

TheJulianJES commented 1 year ago

Z2M has different datapoint IDs for two of the buttons: https://github.com/Koenkk/zigbee-herdsman-converters/blob/77547a0888dbc5f955027c0bdfb11543d99bf202/src/devices/tuya.ts#L5104-L5113

I'd try changing those two in your quirk and see if it works.

gkawanami commented 1 year ago

Hi @TheJulianJES

Really don't know how to do that..

Tried this in @javicalle's Simplified Code, adjusted. Still the non responsive last two buttons.

Is this what I was supposed to do with the quirk?

class TuyaOnOffManufCluster_8(TuyaMCUCluster): 
    """Tuya with On/Off data points."""

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
        ),
        2: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=2,
        ),
        3: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=3,
        ),
        4: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=4,
        ),
        5: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=5,
        ),
        6: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=6,
        ),
        7: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=0x65,
        ),
        8: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=0x66,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        5: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        0x65: "_dp_2_attr_update",
        0x66: "_dp_2_attr_update",
    }
TheJulianJES commented 1 year ago

Not really familiar with the Tuya stuff, but from a quick look at it, you could try this:

class TuyaOnOffManufCluster_8(TuyaMCUCluster): 
    """Tuya with On/Off data points."""

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
        ),
        2: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=2,
        ),
        3: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=3,
        ),
        4: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=4,
        ),
        5: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=5,
        ),
        6: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=6,
        ),
        0x65: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=7,
        ),
        0x66: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=8,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        5: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        0x65: "_dp_2_attr_update",
        0x66: "_dp_2_attr_update",
    }
gkawanami commented 1 year ago

Hey guys!

Well, JaviCalle.py is the file which contains exclusively the @javicalle simplified version, with the substitution provided by @TheJulianJES.

After rebooting the logs showed:

2023-08-02 13:15:38.363 ERROR (MainThread) [zhaquirks] Unexpected exception importing custom quirk 'JaviCalle'
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 "<frozen importlib._bootstrap_external>", line 605, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1120, in load_module
  File "<frozen importlib._bootstrap_external>", line 945, in load_module
  File "<frozen importlib._bootstrap>", line 290, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 721, in _load
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/config/custom_zha_quirks/JaviCalle.py", line 23, in <module>
    class TuyaOnOffManufCluster_8(TuyaMCUCluster):
  File "/config/custom_zha_quirks/JaviCalle.py", line 26, in TuyaOnOffManufCluster_8
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
                     ^^^^
NameError: name 'Dict' is not defined
2023-08-02 13:15:39.419 ERROR (bellows.thread_0) [bellows.uart] CRC error in frame b'f6de2f83fd7e1f240932fe768b29027e' (b'2902' != b'ae90')

Line 26 reads:

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {

And this is the entire file:

"""Tuya DP based switches."""
from zigpy.profiles import zgp, zha
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaSwitch
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    MoesSwitchManufCluster,
    TuyaMCUCluster,
    TuyaOnOff,
    TuyaOnOffManufCluster,
    TuyaOnOffNM,
)

class TuyaOnOffManufCluster_8(TuyaMCUCluster): 
    """Tuya with On/Off data points."""

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        1: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
        ),
        2: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=2,
        ),
        3: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=3,
        ),
        4: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=4,
        ),
        5: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=5,
        ),
        6: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=6,
        ),
        0x65: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=7,
        ),
        0x66: DPToAttributeMapping(
            TuyaOnOff.ep_attribute,
            "on_off",
            endpoint_id=8,
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        5: "_dp_2_attr_update",
        6: "_dp_2_attr_update",
        0x65: "_dp_2_attr_update",
        0x66: "_dp_2_attr_update",
    }

class TuyaOctapleSwitchTO_GP(TuyaSwitch):
    """Tuya octaple channel switch time on out cluster device with GreenPowerProxy cluster device."""

    signature = {
        MODELS_INFO: [
            ("_TZE200_wktrysab", "TS0601"),
        ],

        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=81
            # input_clusters=[0x0000,0x0004,0x0005,0xEF00]
            # output_clusters=[0x000A,0x0019]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaOnOffManufCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
            # 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: {
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaOnOffManufCluster_8,
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            3: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            4: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            5: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            6: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            7: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            8: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                PROFILE_ID: zgp.PROFILE_ID,
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        }
    }

After the reboot All button are grey and non clickable....

javicalle commented 1 year ago

Thanks @TheJulianJES !!!

@gkawanami, you left the Dict import from my file:

"""Tuya DP based switches."""
from zigpy.profiles import zgp, zha
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaSwitch
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    MoesSwitchManufCluster,
    TuyaMCUCluster,
    TuyaOnOff,
    TuyaOnOffManufCluster,
    TuyaOnOffNM,
)

from typing import Dict

class TuyaOnOffManufCluster_8(TuyaMCUCluster): 
    """Tuya with On/Off data points."""
javicalle commented 1 year ago

@gkawanami Did you manage to get it working without problems?

gkawanami commented 1 year ago

Hey @javicalle

I'm out of town. I'll be back home in a couple of days.

Will surely test it as soon as I get home.

gkawanami commented 1 year ago

Ok!!!

@TheJulianJES @javicalle

JaviCalle file is now working great!
I've deleted the eight gang section of the original file, and that got all the switches (3, 4 and 6 gangs) working thru the original file and the 8 gang switch is working thru the new file you both created!

Problem solved! Thanks to you both a lot!!!!!!

Is there any problem in having 2 or more files in the quirks folder? Should I try to merge both files?

javicalle commented 1 year ago

Is there any problem in having 2 or more files in the quirks folder?

No, no problem at all as long as you don't repeat definitions of the same device in both files. If you are not using any custom code from the 3, 4 and 6 gangs devices, you can remove the file from your custom_quirk folder and just keep the 8 gang file.

Should I try to merge both files?

Next steps would be to create a PR to integrate that code to mainstream. I'm not sure what to do with that new TuyaOnOffManufCluster_8 class. We can just update the original TuyaOnOffManufCluster with the 7th and 8th DP, but not sure if these are quite Tuya 'standar' values.

Once the PR for your device is created and merged, you would remove the file with the next HA minor update (the nex 2023.X version after PR gets merged).

gkawanami commented 1 year ago

Great!

Problem solved then!

Thanks very much for the support!

matthewcoates commented 1 year ago

thank you guys soooo much i have been working on getting my 16ch tuya relay board working for months and just came across this, and with a little editing i got all 16ch to work ts0601_switch_8.txt

javicalle commented 1 year ago

Could anyone test with that version of quirk (or just replace all the DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, with DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,:

TuyaSwitchX8_GP ```python class TuyaSwitchX8_GP(TuyaSwitch): """Tuya x8 channels switch with GreenPowerProxy cluster device.""" signature = { MODELS_INFO: [ ("_TZE200_wktrysab", "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, TuyaOnOffManufCluster.cluster_id, ], OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], }, #

DISCLAIMER: This change will create all new switch entities for the channels and the light entities will be unavailable.

gkawanami commented 1 year ago

Hi @javicalle !

Just tested with the Light to switch substitutions.

It works. After rebooting I lost the lights, but 8 new working switches were created just fine.