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
743 stars 679 forks source link

[Device Support Request] Tint E14 RGB CCT #1773

Closed nicufarmache closed 1 year ago

nicufarmache commented 2 years ago

Is your feature request related to a problem? Please describe. My Tint E14 light doesn't correctly report the color capabilities (I can only change the color temperature in HA) https://zigbee.blakadder.com/Muller_Licht_404019.html

Describe the solution you'd like Add a quirk for it

Device signature ```yaml { "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=4635, 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": 260, "device_type": "0x010d", "in_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x0300", "0x1000", "0x100f" ], "out_clusters": [ "0x0019" ] }, "242": { "profile_id": 41440, "device_type": "0x0061", "in_clusters": [], "out_clusters": [ "0x0021" ] } }, "manufacturer": "MLI", "model": "tint-ExtendedColor", "class": "zhaquirks.mli.tintE14rgbcct.TintRGBCCTLight" } ```
Diagnostic information ```yaml { "home_assistant": { "installation_type": "Home Assistant Container", "version": "2022.9.5", "dev": false, "hassio": false, "virtualenv": false, "python_version": "3.10.5", "docker": true, "arch": "aarch64", "timezone": "Europe/Berlin", "os_name": "Linux", "os_version": "5.15.61-v8+", "run_as_root": true }, "custom_components": { "hacs": { "version": "1.27.2", "requirements": [ "aiogithubapi>=22.2.4" ] }, "samsungtv_smart": { "version": "0.7.6", "requirements": [ "websocket-client!=1.4.0,>=0.58.0", "wakeonlan>=2.0.0", "aiofiles>=0.8.0" ] }, "xiaomi_cloud_map_extractor": { "version": "v2.2.0", "requirements": [ "pillow", "pybase64", "python-miio", "requests", "pycryptodome" ] }, "dwd_weather": { "version": "1.2.24", "requirements": [ "simple_dwd_weatherforecast==1.1.5", "markdownify==0.6.5" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.33.1", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.79", "zigpy-deconz==0.18.1", "zigpy==0.50.3", "zigpy-xbee==0.15.0", "zigpy-zigate==0.9.2", "zigpy-znp==0.8.2" ], "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" ] } ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" } ], "dependencies": [ "file_upload" ], "after_dependencies": [ "onboarding", "usb", "zeroconf" ], "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 45480, "manufacturer": "MLI", "model": "tint-ExtendedColor", "name": "MLI tint-ExtendedColor", "quirk_applied": true, "quirk_class": "zhaquirks.mli.tintE14rgbcct.TintRGBCCTLight", "manufacturer_code": 4635, "power_source": "Mains", "lqi": 255, "rssi": -80, "last_seen": "2022-09-20T11:54:20", "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=4635, 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": 260, "device_type": "0x010d", "in_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0006", "0x0008", "0x0300", "0x1000", "0x100f" ], "out_clusters": [ "0x0019" ] }, "242": { "profile_id": 41440, "device_type": "0x0061", "in_clusters": [], "out_clusters": [ "0x0021" ] } } }, "active_coordinator": false, "entities": [ { "entity_id": "button.bed_lamp_identifybutton", "name": "MLI tint-ExtendedColor" }, { "entity_id": "light.bedroom_bed_lamp", "name": "MLI tint-ExtendedColor" }, { "entity_id": "number.bed_lamp_startupcurrentlevelconfiguration", "name": "MLI tint-ExtendedColor" }, { "entity_id": "select.bed_lamp_startuponoffselect", "name": "MLI tint-ExtendedColor" } ], "neighbors": [ { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Parent", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0321", "permit_joining": "Unknown", "depth": "1", "lqi": "61" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x2AC3", "permit_joining": "Unknown", "depth": "1", "lqi": "118" }, { "device_type": "Coordinator", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x0000", "permit_joining": "Unknown", "depth": "0", "lqi": "34" }, { "device_type": "Router", "rx_on_when_idle": "On", "relationship": "Sibling", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0x7153", "permit_joining": "Unknown", "depth": "1", "lqi": "104" }, { "device_type": "EndDevice", "rx_on_when_idle": "Off", "relationship": "Child", "extended_pan_id": "**REDACTED**", "ieee": "**REDACTED**", "nwk": "0xFA70", "permit_joining": "Unknown", "depth": "3", "lqi": "134" } ], "endpoint_names": [ { "name": "EXTENDED_COLOR_LIGHT" }, { "name": "unknown 97 device_type of 0xa1e0 profile id" } ], "user_given_name": "Bed Lamp", "device_reg_id": "e09e3187f33dae9c6949484584c27879", "area_id": "2d16b96db6e441aee6c3075c67cb744a", "cluster_details": { "1": { "device_type": { "name": "EXTENDED_COLOR_LIGHT", "id": 269 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "MLI" }, "0x0005": { "attribute_name": "model", "value": "tint-ExtendedColor" } }, "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": 1 }, "0x4003": { "attribute_name": "start_up_on_off", "value": 1 } }, "unsupported_attributes": {} }, "0x0008": { "endpoint_attribute": "level", "attributes": { "0x0000": { "attribute_name": "current_level", "value": 13 }, "0x4000": { "attribute_name": "start_up_current_level", "value": 255 } }, "unsupported_attributes": { "0x0014": { "attribute_name": "default_move_rate" }, "0x0010": { "attribute_name": "on_off_transition_time" }, "0x0011": { "attribute_name": "on_level" }, "0x0012": { "attribute_name": "on_transition_time" }, "0x0013": { "attribute_name": "off_transition_time" } } }, "0x0300": { "endpoint_attribute": "light_color", "attributes": { "0x0000": { "attribute_name": "current_hue", "value": 207 }, "0x0001": { "attribute_name": "current_saturation", "value": 212 }, "0x0007": { "attribute_name": "color_temperature", "value": 172 }, "0x0008": { "attribute_name": "color_mode", "value": 1 }, "0x000f": { "attribute_name": "options", "value": 0 }, "0x4002": { "attribute_name": "color_loop_active", "value": 0 }, "0x400a": { "attribute_name": "color_capabilities", "value": 31 }, "0x400b": { "attribute_name": "color_temp_physical_min", "value": 153 }, "0x400c": { "attribute_name": "color_temp_physical_max", "value": 555 }, "0x4010": { "attribute_name": "start_up_color_temperature", "value": 65535 } }, "unsupported_attributes": { "0x4000": { "attribute_name": "enhanced_current_hue" }, "0x0003": { "attribute_name": "current_x" }, "0x0004": { "attribute_name": "current_y" }, "0xfffe": { "attribute_name": "attr_reporting_status" }, "0x0012": { "attribute_name": "primary1_y" } } }, "0x1000": { "endpoint_attribute": "lightlink", "attributes": {}, "unsupported_attributes": {} }, "0x100f": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "242": { "device_type": { "name": "unknown", "id": 97 }, "profile_id": 41440, "in_clusters": {}, "out_clusters": { "0x0021": { "endpoint_attribute": "green_power", "attributes": {}, "unsupported_attributes": {} } } } } } } ```
Additional logs ``` ```

Additional context I already created a quirk for it and I'm currently using it successfully but I don't know how I should summit it here. I posted the code in the comments

nicufarmache commented 2 years ago
"""Tint E14 RGB CCT."""
from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    GreenPowerProxy,
    Groups,
    Identify,
    LevelControl,
    OnOff,
    Ota,
    Scenes,
)
from zigpy.zcl.clusters.lighting import Color
from zigpy.zcl.clusters.lightlink import LightLink

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

class TintRGBCCTColorCluster(CustomCluster, Color):
    """Tint RGB+CCT Lighting custom cluster."""

    # Set correct capabilities to ct, xy, hs
    # Tint bulbs do not correctly report this attribute
    _CONSTANT_ATTRIBUTES = {0x400A: 0b11111}

class TintRGBCCTLight(CustomDevice):
    """Tint E15 RGB+CCT Lighting device."""

    signature = {
        MODELS_INFO: [("MLI", "tint-ExtendedColor")],
        ENDPOINTS: {
            1: {
                #   "profile_id": 260,
                #   "device_type": "0x010d",
                #   "in_clusters": [
                #     "0x0000",
                #     "0x0003",
                #     "0x0004",
                #     "0x0005",
                #     "0x0006",
                #     "0x0008",
                #     "0x0300",
                #     "0x1000",
                #     "0x100f"
                #   ],
                #   "out_clusters": [
                #     "0x0019"
                #   ]
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.EXTENDED_COLOR_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Color.cluster_id,
                    LightLink.cluster_id,
                    4111,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            242: {
                #   "profile_id": 41440,
                #   "device_type": "0x0061",
                #   "in_clusters": [],
                #   "out_clusters": [
                #     "0x0021"
                #   ]
                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.EXTENDED_COLOR_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    TintRGBCCTColorCluster,
                    LightLink.cluster_id,
                    4111,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 97,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        }
    }
nicufarmache commented 1 year ago

Is it ok if I create a PR with this file?

TheJulianJES commented 1 year ago

Yes, please do so!

TheJulianJES commented 1 year ago

Fixed with https://github.com/zigpy/zha-device-handlers/pull/2071