Blue Switch / HA/ ZHA Unable to bind group to switch

Having a strange issue - trying to bind the Blue 2in1 switch to a ZHA light group, but just sits there spinning for ever. No error message, no binding.

I’m going to the switch, then the 3 dots, ‘manage zigbee device’, then set as follows:
ibebIcE1

Am i missing something? The instructions differ a bit from the current version of HA, but seems like the correct menu. Thanks for any insight!

ok so if i do individual lights, ie, the hallway has 3 lights… i individually select & bind them and it works. but this is not good, some areas have 20-30 lights… is the group option broken for anyone else?

I know @Eric_Inovelli bound a bunch of hue lights

1 Like

Just to make sure, you followed these instructions?

I can try to replicate on my end, but I’m not sure when I can get to it.

2 Likes

yep! i used thatexact video as my guide, just FYI the device page is different now for some reason; the binding is under a diff menu now:

I just added another new blue series switch to my bedroom, and the behavior is the same - will not bind the group. All hue lights, all on ZHA with a “SONOFF Zigbee 3.0 USB Dongle Plus V2”
Image 5

here’s the bedroom ZHA group:

all my version numbers:
Home Assistant 2022.10.4
Supervisor 2022.10.0
Operating System 9.2
Frontend 20221010.0 - latest

Dang HA always updating their UI all the time lol. Ok I need to finish writing up the tutorials for Hubitat tonight, but after I will get back on ZHA to see if I see the same issue.

1 Like

Well, good news and bad news.

Good news is I was able to get group binding to work, bad news is now we have to figure out why you can’t lol.

I noticed in the pictures you selected, “Level Control” with an endpoint of 2. Do you have one available with the endpoint of 1?

ah well i’m glad it’s somehow isolated to me.

Nope i don’t see an option for endpoint 1 for LevelControl, only 2. only thing under endpoint 1 is ‘ota’. just checked, that screen shot is the same for all switches i have installed so far (4 switches)

I’m not clear what this endpoint designation means - can i move it to 1? or do i need to reset and re-add the switch? Happy to provide any logs, or even access to my instance if needed.

thanks for the help!

Well, I just noticed I’m on beta firmware and an older instance of HA, so I’m in the process of updating things to see if I can fully emulate your setup.

Hang tight :slight_smile:

2 Likes

Ok, had some help from @dmulcahey and @chack and determined it was bc I was on an older version of HA that I was able to get the endpoints to show differently.

I believe they fixed it (and can likely tell you what happened better than me) and pushed an update to HA. So, hopefully it should all work in a little bit.

Good news! There’s a fix for you if you’re so inclined to set up a custom quirk (instructions to follow). The fix is also in a pull request and hopefully making it into a hotfix on HA soon™ (all credit to @dmulcahey for his help with this) if you prefer to wait for that release and just update HA to resolve it instead (targeted for 2022.10.5).

Manual Instructions:

Need to edit the ZHA configuration in “configuration.yaml” to add the custom quirks path (this may look different than yours, you only need to add the custom quirks path):

zha:
  zigpy_config:
    network:
      channel: 25
      channels: [25]
    ota:
      inovelli_provider: true
      #otau_directory: /config/ota
  custom_quirks_path: /config/zhacustomquirks/

Now create a folder in the config directory matching the name above (zhacustomquirks in my example) using either mkdir or if you’re using Samba, etc you can right click to create a new folder I believe.

Navigate into that folder and create a file named - “CustomVZM31SN.py” and it should look like this:

CustomVZM31SN.py
"""VZM31-SN Two in One Switch/Dimmer Module."""

from zigpy.profiles import zha
from zigpy.profiles.zha import DeviceType
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    Groups,
    Identify,
    LevelControl,
    OnOff,
    Ota,
    Scenes,
)
from zigpy.zcl.clusters.homeautomation import Diagnostic, ElectricalMeasurement
from zigpy.zcl.clusters.smartenergy import Metering

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

INOVELLI_VZM31SN_CLUSTER_ID = 64561
WWAH_CLUSTER_ID = 64599


class InovelliVZM31SNv11(CustomDevice):
    """VZM31-SN 2 in 1 Switch/Dimmer Module."""

    signature = {
        MODELS_INFO: [("Inovelli", "VZM31-SN")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],  # 19
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Basic.cluster_id, Identify.cluster_id],  # 0  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                ],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    Inovelli_VZM31SN_Cluster,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Ota.cluster_id,  # 19
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Basic.cluster_id, Identify.cluster_id],  # 0  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [0x0021],
            },
        },
    }

    device_automation_triggers = INOVELLI_AUTOMATION_TRIGGERS


class InovelliVZM31SNv10(CustomDevice):
    """VZM31-SN 2 in 1 Switch/Dimmer Module."""

    signature = {
        MODELS_INFO: [("Inovelli", "VZM31-SN")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],  # 3  # 19
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Basic.cluster_id, Identify.cluster_id],  # 0  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                ],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    Inovelli_VZM31SN_Cluster,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Ota.cluster_id,  # 19
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Basic.cluster_id, Identify.cluster_id],  # 0  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
        },
    }

    device_automation_triggers = INOVELLI_AUTOMATION_TRIGGERS


class InovelliVZM31SNv9(CustomDevice):
    """VZM31-SN 2 in 1 Switch/Dimmer Module."""

    signature = {
        MODELS_INFO: [("Inovelli", "VZM31-SN")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],  # 3  # 19
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Identify.cluster_id],  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                ],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    Inovelli_VZM31SN_Cluster,  # 64561
                    WWAH_CLUSTER_ID,  # 64599
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Ota.cluster_id,  # 19
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Identify.cluster_id],  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
        },
    }

    device_automation_triggers = INOVELLI_AUTOMATION_TRIGGERS


class InovelliVZM31SN(CustomDevice):
    """VZM31-SN 2 in 1 Switch/Dimmer Module."""

    signature = {
        MODELS_INFO: [("Inovelli", "VZM31-SN")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                ],
                OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],  # 3  # 19
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Identify.cluster_id],  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    INOVELLI_VZM31SN_CLUSTER_ID,  # 64561
                ],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMABLE_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,  # 0
                    Identify.cluster_id,  # 3
                    Groups.cluster_id,  # 4
                    Scenes.cluster_id,  # 5
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Metering.cluster_id,  # 1794
                    ElectricalMeasurement.cluster_id,  # 2820
                    Diagnostic.cluster_id,  # 2821
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Ota.cluster_id,  # 19
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [Identify.cluster_id],  # 3
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,  # 3
                    OnOff.cluster_id,  # 6
                    LevelControl.cluster_id,  # 8
                    Inovelli_VZM31SN_Cluster,  # 64561
                ],
            },
        },
    }

    device_automation_triggers = INOVELLI_AUTOMATION_TRIGGERS

Now create a file named - “__init__.py” and it should look like this:

__init__.py
"""Module for Inovelli quirks implementations."""

import logging
from typing import Any, List, Optional, Union

from zigpy.quirks import CustomCluster
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.manufacturer_specific import ManufacturerSpecificCluster

from zhaquirks.const import (
    BUTTON,
    BUTTON_1,
    BUTTON_2,
    BUTTON_3,
    COMMAND,
    COMMAND_DOUBLE,
    COMMAND_HOLD,
    COMMAND_ID,
    COMMAND_PRESS,
    COMMAND_QUAD,
    COMMAND_RELEASE,
    COMMAND_TRIPLE,
    DOUBLE_PRESS,
    PRESS_TYPE,
    QUADRUPLE_PRESS,
    QUINTUPLE_PRESS,
    TRIPLE_PRESS,
    ZHA_SEND_EVENT,
)

_LOGGER = logging.getLogger(__name__)
INOVELLI_VZM31SN_CLUSTER_ID = 64561

# Press Types
# 0 - pressed
# 1 - released
# 2 - held
# 3 - 2x
# 4 - 3x
# 5 - 4x
# 6 - 5x
COMMAND_QUINTUPLE = "quintuple"
PRESS_TYPES = {
    0: COMMAND_PRESS,
    1: COMMAND_RELEASE,
    2: COMMAND_HOLD,
    3: COMMAND_DOUBLE,
    4: COMMAND_TRIPLE,
    5: COMMAND_QUAD,
    6: COMMAND_QUINTUPLE,
}

LED_NOTIFICATION_TYPES = {
    0: "LED_1",
    1: "LED_2",
    2: "LED_3",
    3: "LED_4",
    4: "LED_5",
    5: "LED_6",
    6: "LED_7",
    16: "ALL_LEDS",
    255: "CONFIG_BUTTON_DOUBLE_PRESS",
}

# Buttons
# 1 - down button
# 2 - up button
# 3 - config button

BUTTONS = {1: BUTTON_1, 2: BUTTON_2, 3: BUTTON_3}
ON = "Up"
OFF = "Down"
CONFIG = "Config"

NOTIFICATION_TYPE = "notification_type"


class Inovelli_VZM31SN_Cluster(CustomCluster):
    """Inovelli VZM31-SN custom cluster."""

    cluster_id = 0xFC31
    name = "InovelliVZM31SNCluster"
    ep_attribute = "inovelli_vzm31sn_cluster"

    attributes = ManufacturerSpecificCluster.attributes.copy()
    attributes.update(
        {
            0x0001: ("dimming_speed_up_remote", t.uint8_t, True),
            0x0002: ("dimming_speed_up_local", t.uint8_t, True),
            0x0003: ("ramp_rate_off_to_on_local", t.uint8_t, True),
            0x0004: ("ramp_rate_off_to_on_remote", t.uint8_t, True),
            0x0005: ("dimming_speed_down_remote", t.uint8_t, True),
            0x0006: ("dimming_speed_down_local", t.uint8_t, True),
            0x0007: ("ramp_rate_on_to_off_local", t.uint8_t, True),
            0x0008: ("ramp_rate_on_to_off_remote", t.uint8_t, True),
            0x0009: ("minimum_level", t.uint8_t, True),
            0x000A: ("maximum_level", t.uint8_t, True),
            0x000B: ("invert_switch", t.Bool, True),
            0x000C: ("auto_off_timer", t.uint16_t, True),
            0x000D: ("default_level_local", t.uint8_t, True),
            0x000E: ("default_level_remote", t.uint8_t, True),
            0x000F: ("state_after_power_restored", t.uint8_t, True),
            0x0011: ("load_level_indicator_timeout", t.uint8_t, True),
            0x0012: ("active_power_reports", t.uint8_t, True),
            0x0013: ("periodic_power_and_energy_reports", t.uint8_t, True),
            0x0014: ("active_energy_reports", t.uint16_t, True),
            0x0015: ("power_type", t.uint8_t, True),
            0x0016: ("switch_type", t.uint8_t, True),
            0x0032: ("button_delay", t.uint8_t, True),
            0x0033: ("device_bind_number", t.uint8_t, True),
            0x0034: ("smart_bulb_mode", t.Bool, True),
            0x0035: ("double_tap_up_for_full_brightness", t.Bool, True),
            0x003C: ("default_led1_strip_color_when_on", t.uint8_t, True),
            0x003D: ("default_led1_strip_color_when_off", t.uint8_t, True),
            0x003E: ("default_led1_strip_intensity_when_on", t.uint8_t, True),
            0x003F: ("default_led1_strip_intensity_when_off", t.uint8_t, True),
            0x0041: ("default_led2_strip_color_when_on", t.uint8_t, True),
            0x0042: ("default_led2_strip_color_when_off", t.uint8_t, True),
            0x0043: ("default_led2_strip_intensity_when_on", t.uint8_t, True),
            0x0044: ("default_led2_strip_intensity_when_off", t.uint8_t, True),
            0x0046: ("default_led3_strip_color_when_on", t.uint8_t, True),
            0x0047: ("default_led3_strip_color_when_off", t.uint8_t, True),
            0x0048: ("default_led3_strip_intensity_when_on", t.uint8_t, True),
            0x0049: ("default_led3_strip_intensity_when_off", t.uint8_t, True),
            0x004B: ("default_led4_strip_color_when_on", t.uint8_t, True),
            0x004C: ("default_led4_strip_color_when_off", t.uint8_t, True),
            0x004D: ("default_led4_strip_intensity_when_on", t.uint8_t, True),
            0x004E: ("default_led4_strip_intensity_when_off", t.uint8_t, True),
            0x0050: ("default_led5_strip_color_when_on", t.uint8_t, True),
            0x0051: ("default_led5_strip_color_when_off", t.uint8_t, True),
            0x0052: ("default_led5_strip_intensity_when_on", t.uint8_t, True),
            0x0053: ("default_led5_strip_intensity_when_off", t.uint8_t, True),
            0x0055: ("default_led6_strip_color_when_on", t.uint8_t, True),
            0x0056: ("default_led6_strip_color_when_off", t.uint8_t, True),
            0x0057: ("default_led6_strip_intensity_when_on", t.uint8_t, True),
            0x0058: ("default_led6_strip_intensity_when_off", t.uint8_t, True),
            0x005A: ("default_led7_strip_color_when_on", t.uint8_t, True),
            0x005B: ("default_led7_strip_color_when_off", t.uint8_t, True),
            0x005C: ("default_led7_strip_intensity_when_on", t.uint8_t, True),
            0x005D: ("default_led7_strip_intensity_when_off", t.uint8_t, True),
            0x005F: ("led_color_when_on", t.uint8_t, True),
            0x0060: ("led_color_when_off", t.uint8_t, True),
            0x0061: ("led_intensity_when_on", t.uint8_t, True),
            0x0062: ("led_intensity_when_off", t.uint8_t, True),
            0x0100: ("local_protection", t.Bool, True),
            0x0101: ("remote_protection", t.Bool, True),
            0x0102: ("output_mode", t.Bool, True),
            0x0103: ("on_off_led_mode", t.Bool, True),
            0x0104: ("firmware_progress_led", t.Bool, True),
            0x0105: ("relay_click_in_on_off_mode", t.Bool, True),
        }
    )

    server_commands = {
        0x00: foundation.ZCLCommandDef(
            "button_event",
            {"button_pressed": t.uint8_t, "press_type": t.uint8_t},
            is_reply=False,
            is_manufacturer_specific=True,
        ),
        0x01: foundation.ZCLCommandDef(
            "led_effect",
            {
                "led_effect": t.uint8_t,
                "led_color": t.uint8_t,
                "led_level": t.uint8_t,
                "led_duration": t.uint8_t,
            },
            is_reply=False,
            is_manufacturer_specific=True,
        ),  # LED Effect
        0x02: foundation.ZCLCommandDef(
            "reset_energy_meter",
            {},
            is_reply=False,
            is_manufacturer_specific=True,
        ),  # LED Effect
        0x03: foundation.ZCLCommandDef(
            "individual_led_effect",
            {
                "led_number": t.uint8_t,
                "led_effect": t.uint8_t,
                "led_color": t.uint8_t,
                "led_level": t.uint8_t,
                "led_duration": t.uint8_t,
            },
            is_reply=False,
            is_manufacturer_specific=True,
        ),  # individual LED Effect
        0x24: foundation.ZCLCommandDef(
            "led_effect_complete",
            {
                "notification_type": t.uint8_t,
            },
            is_reply=False,
            is_manufacturer_specific=True,
        ),
    }

    def handle_cluster_request(
        self,
        hdr: foundation.ZCLHeader,
        args: List[Any],
        *,
        dst_addressing: Optional[
            Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
        ] = None,
    ):
        """Handle a cluster request."""
        _LOGGER.debug(
            "%s: handle_cluster_request - Command: %s Data: %s",
            self.name,
            hdr.command_id,
            args,
        )
        if hdr.command_id == self.commands_by_name["button_event"].id:
            button = BUTTONS[args.button_pressed]
            press_type = PRESS_TYPES[args.press_type]
            action = f"{button}_{press_type}"
            event_args = {
                BUTTON: button,
                PRESS_TYPE: press_type,
                COMMAND_ID: hdr.command_id,
            }
            self.listener_event(ZHA_SEND_EVENT, action, event_args)
            return
        if hdr.command_id == self.commands_by_name["led_effect_complete"].id:
            notification_type = LED_NOTIFICATION_TYPES.get(
                args.notification_type, "unknown"
            )
            action = f"led_effect_complete_{notification_type}"
            event_args = {
                NOTIFICATION_TYPE: notification_type,
                COMMAND_ID: hdr.command_id,
            }
            self.listener_event(ZHA_SEND_EVENT, action, event_args)
            return


INOVELLI_AUTOMATION_TRIGGERS = {
    (COMMAND_PRESS, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_PRESS}"},
    (COMMAND_PRESS, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_PRESS}"},
    (COMMAND_PRESS, CONFIG): {COMMAND: f"{BUTTON_3}_{COMMAND_PRESS}"},
    (COMMAND_HOLD, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_HOLD}"},
    (COMMAND_HOLD, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_HOLD}"},
    (DOUBLE_PRESS, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_DOUBLE}"},
    (DOUBLE_PRESS, CONFIG): {COMMAND: f"{BUTTON_3}_{COMMAND_DOUBLE}"},
    (DOUBLE_PRESS, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_DOUBLE}"},
    (TRIPLE_PRESS, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_TRIPLE}"},
    (TRIPLE_PRESS, CONFIG): {COMMAND: f"{BUTTON_3}_{COMMAND_TRIPLE}"},
    (TRIPLE_PRESS, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_TRIPLE}"},
    (QUADRUPLE_PRESS, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_QUAD}"},
    (QUADRUPLE_PRESS, CONFIG): {COMMAND: f"{BUTTON_3}_{COMMAND_QUAD}"},
    (QUADRUPLE_PRESS, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_QUAD}"},
    (QUINTUPLE_PRESS, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_QUINTUPLE}"},
    (QUINTUPLE_PRESS, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_QUINTUPLE}"},
    (QUINTUPLE_PRESS, CONFIG): {COMMAND: f"{BUTTON_3}_{COMMAND_QUINTUPLE}"},
    (COMMAND_RELEASE, ON): {COMMAND: f"{BUTTON_2}_{COMMAND_RELEASE}"},
    (COMMAND_RELEASE, OFF): {COMMAND: f"{BUTTON_1}_{COMMAND_RELEASE}"},
}

After this, restart Home Assistant and you should have the ability to use endpoint 1 for group binding.

If for some reason this doesn’t work, feel free to reach out and I can walk you through any part of it.

Edit - had to fix the init file name in the creation line vs the dropdown, was hiding the underscores…

5 Likes

Sorry if this is obvious (I don’t really know how ZHA or Z2M works), but would zigbee2mqtt require similar changes in order for the blue switches to be able to bind a group?

Thanks for your help!

1 Like

Not to my knowledge, ZHA and Z2M have separate handlers, so you should be good to go there if you’re using Z2M (just different specifics for how you handle the device and group binding).

2 Likes

this is working, had to perform the bind action 2 times but second time it picked up!

thank you!

only thing happening now is when i dim the lights, it seems to change the color of the bulbs to a warmer shade of white. I just tested this by setting them to cool white, and as i dim it resets to very warm.

2 Likes

Having the same issue, and I tried the quirk. I can now see endpoint 1, but binding doesn’t seem to work. It just spins.

I have the switch in smart mode, and it appears to be working as expected. I rebooted (2x actually) after adding the code shown above. I’m planning to repair the lights and to recreate the group later, as it existed before I installed the new switch.

Also, fyi, I love the feel of this switch! It’s much more satisfying to press and better looking than those hue switches. Great Job!

1 Like

The Bind Group button will spin but it should still work. That’s an issue that’s hopefully going to be fixed in 2022.11.0.

2 Likes

As you said, the group binding did work, despite the lack of any indicator! It’s amazing you all came up with a workaround so fast. Thanks!

2 Likes

I also noticed this problem too although I’m using zigbee2mqtt. It seems like Endpoint 1 is supposed to have LevelCtrl and OnOff clusters but only Ota is showing up. Endpoint 2 has LevelCtrl and OnOff but doesn’t seem to do anything when something is bound.

The fix mentioned in this thread is specifically for ZHA. I’m guessing there will need to be a similar change in this file in zigbee2mqtt.

1 Like

It looks like from what I can tell that the Z2M file has the LevelCtrl and OnOff clusters for endpoint 1? From the handler -

        configure: async (device, coordinatorEndpoint, logger) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, [
                'genOnOff',
                'genLevelCtrl',
            ]);

@nathanfiscus can you confirm that should be the case?

Yea, those lines are Z2M binding those clusters to the “Coordinator” (guessing this is how it gets instant status updates?). I can even see in the UI that those are bound but when I select Endpoint 1 to do another bind, it only shows checkboxes for Ota.

1 Like