diff --git a/homeassistant/components/zha/core/channels/manufacturerspecific.py b/homeassistant/components/zha/core/channels/manufacturerspecific.py
index b9f0ec1aaca773cb1ea52ff027b4c80ceeca1582..49f5d1df249d0d294bda1c12312311e2385181b5 100644
--- a/homeassistant/components/zha/core/channels/manufacturerspecific.py
+++ b/homeassistant/components/zha/core/channels/manufacturerspecific.py
@@ -4,6 +4,7 @@ from __future__ import annotations
 import logging
 from typing import TYPE_CHECKING, Any
 
+from zigpy import types
 from zigpy.exceptions import ZigbeeException
 import zigpy.zcl
 
@@ -126,12 +127,135 @@ class SmartThingsAcceleration(ZigbeeChannel):
         )
 
 
-@registries.CHANNEL_ONLY_CLUSTERS.register(0xFC31)
 @registries.CLIENT_CHANNELS_REGISTRY.register(0xFC31)
-class InovelliCluster(ClientChannel):
-    """Inovelli Button Press Event channel."""
+class InovelliNotificationChannel(ClientChannel):
+    """Inovelli Notification channel."""
+
+    @callback
+    def attribute_updated(self, attrid, value):
+        """Handle an attribute updated on this cluster."""
+
+    @callback
+    def cluster_command(self, tsn, command_id, args):
+        """Handle a cluster command received on this cluster."""
+
+
+@registries.ZIGBEE_CHANNEL_REGISTRY.register(0xFC31)
+class InovelliConfigEntityChannel(ZigbeeChannel):
+    """Inovelli Configuration Entity channel."""
+
+    class LEDEffectType(types.enum8):
+        """Effect type for Inovelli Blue Series switch."""
+
+        Off = 0x00
+        Solid = 0x01
+        Fast_Blink = 0x02
+        Slow_Blink = 0x03
+        Pulse = 0x04
+        Chase = 0x05
+        Open_Close = 0x06
+        Small_To_Big = 0x07
+        Clear = 0xFF
 
     REPORT_CONFIG = ()
+    ZCL_INIT_ATTRS = {  # pylint: disable=invalid-name
+        "dimming_speed_up_remote": False,
+        "dimming_speed_up_local": False,
+        "ramp_rate_off_to_on_local": False,
+        "ramp_rate_off_to_on_remote": False,
+        "dimming_speed_down_remote": False,
+        "dimming_speed_down_local": False,
+        "ramp_rate_on_to_off_local": False,
+        "ramp_rate_on_to_off_remote": False,
+        "minimum_level": False,
+        "maximum_level": False,
+        "invert_switch": False,
+        "auto_off_timer": False,
+        "default_level_local": False,
+        "default_level_remote": False,
+        "state_after_power_restored": False,
+        "load_level_indicator_timeout": False,
+        "active_power_reports": False,
+        "periodic_power_and_energy_reports": False,
+        "active_energy_reports": False,
+        "power_type": False,
+        "switch_type": False,
+        "button_delay": False,
+        "device_bind_number": False,
+        "smart_bulb_mode": False,
+        "double_tap_up_for_full_brightness": False,
+        "default_led1_strip_color_when_on": False,
+        "default_led1_strip_color_when_off": False,
+        "default_led1_strip_intensity_when_on": False,
+        "default_led1_strip_intensity_when_off": False,
+        "default_led2_strip_color_when_on": False,
+        "default_led2_strip_color_when_off": False,
+        "default_led2_strip_intensity_when_on": False,
+        "default_led2_strip_intensity_when_off": False,
+        "default_led3_strip_color_when_on": False,
+        "default_led3_strip_color_when_off": False,
+        "default_led3_strip_intensity_when_on": False,
+        "default_led3_strip_intensity_when_off": False,
+        "default_led4_strip_color_when_on": False,
+        "default_led4_strip_color_when_off": False,
+        "default_led4_strip_intensity_when_on": False,
+        "default_led4_strip_intensity_when_off": False,
+        "default_led5_strip_color_when_on": False,
+        "default_led5_strip_color_when_off": False,
+        "default_led5_strip_intensity_when_on": False,
+        "default_led5_strip_intensity_when_off": False,
+        "default_led6_strip_color_when_on": False,
+        "default_led6_strip_color_when_off": False,
+        "default_led6_strip_intensity_when_on": False,
+        "default_led6_strip_intensity_when_off": False,
+        "default_led7_strip_color_when_on": False,
+        "default_led7_strip_color_when_off": False,
+        "default_led7_strip_intensity_when_on": False,
+        "default_led7_strip_intensity_when_off": False,
+        "led_color_when_on": False,
+        "led_color_when_off": False,
+        "led_intensity_when_on": False,
+        "led_intensity_when_off": False,
+        "local_protection": False,
+        "remote_protection": False,
+        "output_mode": False,
+        "on_off_led_mode": False,
+        "firmware_progress_led": False,
+        "relay_click_in_on_off_mode": False,
+    }
+
+    async def issue_all_led_effect(
+        self,
+        effect_type: LEDEffectType | int = LEDEffectType.Fast_Blink,
+        color: int = 200,
+        level: int = 100,
+        duration: int = 3,
+        **kwargs: Any,
+    ) -> None:
+        """Issue all LED effect command.
+
+        This command is used to issue an LED effect to all LEDs on the device.
+        """
+
+        await self.led_effect(effect_type, color, level, duration, expect_reply=False)
+
+    async def issue_individual_led_effect(
+        self,
+        led_number: int = 1,
+        effect_type: LEDEffectType | int = LEDEffectType.Fast_Blink,
+        color: int = 200,
+        level: int = 100,
+        duration: int = 3,
+        **kwargs: Any,
+    ) -> None:
+        """Issue individual LED effect command.
+
+        This command is used to issue an LED effect to the specified LED on the device.
+        """
+
+        await self.individual_led_effect(
+            led_number, effect_type, color, level, duration, expect_reply=False
+        )
 
 
 @registries.CHANNEL_ONLY_CLUSTERS.register(registries.IKEA_AIR_PURIFIER_CLUSTER)
diff --git a/homeassistant/components/zha/core/const.py b/homeassistant/components/zha/core/const.py
index 311d3d48b5b100636d7c98471c2d9a4efbf401c5..0204fb50bed5b5ec14a1f980043f8cc9aed03256 100644
--- a/homeassistant/components/zha/core/const.py
+++ b/homeassistant/components/zha/core/const.py
@@ -95,6 +95,7 @@ CHANNEL_TEMPERATURE = "temperature"
 CHANNEL_THERMOSTAT = "thermostat"
 CHANNEL_ZDO = "zdo"
 CHANNEL_ZONE = ZONE = "ias_zone"
+CHANNEL_INOVELLI = "inovelli_vzm31sn_cluster"
 
 CLUSTER_COMMAND_SERVER = "server"
 CLUSTER_COMMANDS_CLIENT = "client_commands"
diff --git a/homeassistant/components/zha/device_action.py b/homeassistant/components/zha/device_action.py
index 3ee8694b09cbdca18cb6c5a0ef3b8e8f50fc21e1..1cb988b1c1513f57c8e262e9578b3d8eddd386d2 100644
--- a/homeassistant/components/zha/device_action.py
+++ b/homeassistant/components/zha/device_action.py
@@ -5,6 +5,7 @@ from typing import Any
 
 import voluptuous as vol
 
+from homeassistant.components.device_automation import InvalidDeviceAutomationConfig
 from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_TYPE
 from homeassistant.core import Context, HomeAssistant
 from homeassistant.helpers import config_validation as cv
@@ -12,7 +13,8 @@ from homeassistant.helpers.typing import ConfigType, TemplateVarsType
 
 from . import DOMAIN
 from .api import SERVICE_WARNING_DEVICE_SQUAWK, SERVICE_WARNING_DEVICE_WARN
-from .core.const import CHANNEL_IAS_WD
+from .core.channels.manufacturerspecific import InovelliConfigEntityChannel
+from .core.const import CHANNEL_IAS_WD, CHANNEL_INOVELLI
 from .core.helpers import async_get_zha_device
 
 # mypy: disallow-any-generics
@@ -23,21 +25,83 @@ ATTR_DATA = "data"
 ATTR_IEEE = "ieee"
 CONF_ZHA_ACTION_TYPE = "zha_action_type"
 ZHA_ACTION_TYPE_SERVICE_CALL = "service_call"
+ZHA_ACTION_TYPE_CHANNEL_COMMAND = "channel_command"
+INOVELLI_ALL_LED_EFFECT = "issue_all_led_effect"
+INOVELLI_INDIVIDUAL_LED_EFFECT = "issue_individual_led_effect"
+
+DEFAULT_ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
+    {
+        vol.Required(CONF_DOMAIN): DOMAIN,
+        vol.Required(CONF_TYPE): vol.In({ACTION_SQUAWK, ACTION_WARN}),
+    }
+)
+
+INOVELLI_ALL_LED_EFFECT_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
+    {
+        vol.Required(CONF_TYPE): INOVELLI_ALL_LED_EFFECT,
+        vol.Required(CONF_DOMAIN): DOMAIN,
+        vol.Required(
+            "effect_type"
+        ): InovelliConfigEntityChannel.LEDEffectType.__getitem__,
+        vol.Required("color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
+        vol.Required("level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
+        vol.Required("duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
+    }
+)
+
+INOVELLI_INDIVIDUAL_LED_EFFECT_SCHEMA = INOVELLI_ALL_LED_EFFECT_SCHEMA.extend(
+    {
+        vol.Required(CONF_TYPE): INOVELLI_INDIVIDUAL_LED_EFFECT,
+        vol.Required("led_number"): vol.All(vol.Coerce(int), vol.Range(1, 7)),
+    }
+)
 
-ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
-    {vol.Required(CONF_DOMAIN): DOMAIN, vol.Required(CONF_TYPE): str}
+ACTION_SCHEMA = vol.Any(
+    INOVELLI_ALL_LED_EFFECT_SCHEMA,
+    INOVELLI_INDIVIDUAL_LED_EFFECT_SCHEMA,
+    DEFAULT_ACTION_SCHEMA,
 )
 
 DEVICE_ACTIONS = {
     CHANNEL_IAS_WD: [
         {CONF_TYPE: ACTION_SQUAWK, CONF_DOMAIN: DOMAIN},
         {CONF_TYPE: ACTION_WARN, CONF_DOMAIN: DOMAIN},
-    ]
+    ],
+    CHANNEL_INOVELLI: [
+        {CONF_TYPE: INOVELLI_ALL_LED_EFFECT, CONF_DOMAIN: DOMAIN},
+        {CONF_TYPE: INOVELLI_INDIVIDUAL_LED_EFFECT, CONF_DOMAIN: DOMAIN},
+    ],
 }
 
 DEVICE_ACTION_TYPES = {
     ACTION_SQUAWK: ZHA_ACTION_TYPE_SERVICE_CALL,
     ACTION_WARN: ZHA_ACTION_TYPE_SERVICE_CALL,
+    INOVELLI_ALL_LED_EFFECT: ZHA_ACTION_TYPE_CHANNEL_COMMAND,
+    INOVELLI_INDIVIDUAL_LED_EFFECT: ZHA_ACTION_TYPE_CHANNEL_COMMAND,
+}
+
+DEVICE_ACTION_SCHEMAS = {
+    INOVELLI_ALL_LED_EFFECT: vol.Schema(
+        {
+            vol.Required("effect_type"): vol.In(
+                InovelliConfigEntityChannel.LEDEffectType.__members__.keys()
+            ),
+            vol.Required("color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
+            vol.Required("level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
+            vol.Required("duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
+        }
+    ),
+    INOVELLI_INDIVIDUAL_LED_EFFECT: vol.Schema(
+        {
+            vol.Required("led_number"): vol.All(vol.Coerce(int), vol.Range(1, 7)),
+            vol.Required("effect_type"): vol.In(
+                InovelliConfigEntityChannel.LEDEffectType.__members__.keys()
+            ),
+            vol.Required("color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
+            vol.Required("level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
+            vol.Required("duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
+        }
+    ),
 }
 
 SERVICE_NAMES = {
@@ -45,6 +109,11 @@ SERVICE_NAMES = {
     ACTION_WARN: SERVICE_WARNING_DEVICE_WARN,
 }
 
+CHANNEL_MAPPINGS = {
+    INOVELLI_ALL_LED_EFFECT: CHANNEL_INOVELLI,
+    INOVELLI_INDIVIDUAL_LED_EFFECT: CHANNEL_INOVELLI,
+}
+
 
 async def async_call_action_from_config(
     hass: HomeAssistant,
@@ -82,6 +151,14 @@ async def async_get_actions(
     return actions
 
 
+async def async_get_action_capabilities(
+    hass: HomeAssistant, config: ConfigType
+) -> dict[str, vol.Schema]:
+    """List action capabilities."""
+
+    return {"extra_fields": DEVICE_ACTION_SCHEMAS.get(config[CONF_TYPE], {})}
+
+
 async def _execute_service_based_action(
     hass: HomeAssistant,
     config: dict[str, Any],
@@ -102,4 +179,40 @@ async def _execute_service_based_action(
     )
 
 
-ZHA_ACTION_TYPES = {ZHA_ACTION_TYPE_SERVICE_CALL: _execute_service_based_action}
+async def _execute_channel_command_based_action(
+    hass: HomeAssistant,
+    config: dict[str, Any],
+    variables: TemplateVarsType,
+    context: Context | None,
+) -> None:
+    action_type = config[CONF_TYPE]
+    channel_name = CHANNEL_MAPPINGS[action_type]
+    try:
+        zha_device = async_get_zha_device(hass, config[CONF_DEVICE_ID])
+    except (KeyError, AttributeError):
+        return
+
+    action_channel = None
+    for pool in zha_device.channels.pools:
+        for channel in pool.all_channels.values():
+            if channel.name == channel_name:
+                action_channel = channel
+                break
+
+    if action_channel is None:
+        raise InvalidDeviceAutomationConfig(
+            f"Unable to execute channel action - channel: {channel_name} action: {action_type}"
+        )
+
+    if not hasattr(action_channel, action_type):
+        raise InvalidDeviceAutomationConfig(
+            f"Unable to execute channel action - channel: {channel_name} action: {action_type}"
+        )
+
+    await getattr(action_channel, action_type)(**config)
+
+
+ZHA_ACTION_TYPES = {
+    ZHA_ACTION_TYPE_SERVICE_CALL: _execute_service_based_action,
+    ZHA_ACTION_TYPE_CHANNEL_COMMAND: _execute_channel_command_based_action,
+}
diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py
index ae4bc7e5ea41517bf8d0703fc8f6060cf3dfecef..95a15778fe7ed459383c584e061e5c9e8e472960 100644
--- a/homeassistant/components/zha/entity.py
+++ b/homeassistant/components/zha/entity.py
@@ -66,6 +66,8 @@ class BaseZhaEntity(LogMixin, entity.Entity):
     @property
     def name(self) -> str:
         """Return Entity's default name."""
+        if hasattr(self, "_attr_name") and self._attr_name is not None:
+            return self._attr_name
         return self._name
 
     @property
diff --git a/homeassistant/components/zha/number.py b/homeassistant/components/zha/number.py
index 14967c1b91c2f0e5146b8d324b4459559664e275..6fe411abfb37b92e33ff3526edf25bf795b8c672 100644
--- a/homeassistant/components/zha/number.py
+++ b/homeassistant/components/zha/number.py
@@ -19,6 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from .core import discovery
 from .core.const import (
     CHANNEL_ANALOG_OUTPUT,
+    CHANNEL_INOVELLI,
     CHANNEL_LEVEL,
     DATA_ZHA,
     SIGNAL_ADD_ENTITIES,
@@ -251,6 +252,8 @@ ICONS = {
     12: "mdi:counter",
     13: "mdi:thermometer-lines",
     14: "mdi:timer",
+    15: "mdi:palette",
+    16: "mdi:brightness-percent",
 }
 
 
@@ -545,3 +548,252 @@ class FilterLifeTime(ZHANumberConfigurationEntity, id_suffix="filter_life_time")
     _attr_native_max_value: float = 0xFFFFFFFF
     _attr_native_unit_of_measurement: str | None = UNITS[72]
     _zcl_attribute: str = "filter_life_time"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliRemoteDimmingUpSpeed(
+    ZHANumberConfigurationEntity, id_suffix="dimming_speed_up_remote"
+):
+    """Inovelli remote dimming up speed configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 126
+    _zcl_attribute: str = "dimming_speed_up_remote"
+    _attr_name: str = "Remote dimming up speed"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliButtonDelay(ZHANumberConfigurationEntity, id_suffix="button_delay"):
+    """Inovelli button delay configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 9
+    _zcl_attribute: str = "button_delay"
+    _attr_name: str = "Button delay"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliDeviceBindNumber(
+    ZHANumberConfigurationEntity, id_suffix="device_bind_number"
+):
+    """Inovelli device bind number configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 255
+    _zcl_attribute: str = "device_bind_number"
+    _attr_name: str = "Device bind number"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliLocalDimmingUpSpeed(
+    ZHANumberConfigurationEntity, id_suffix="dimming_speed_up_local"
+):
+    """Inovelli local dimming up speed configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "dimming_speed_up_local"
+    _attr_name: str = "Local dimming up speed"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliLocalRampRateOffToOn(
+    ZHANumberConfigurationEntity, id_suffix="ramp_rate_off_to_on_local"
+):
+    """Inovelli off to on local ramp rate configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "ramp_rate_off_to_on_local"
+    _attr_name: str = "Local ramp rate off to on"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliRemoteDimmingSpeedOffToOn(
+    ZHANumberConfigurationEntity, id_suffix="ramp_rate_off_to_on_remote"
+):
+    """Inovelli off to on remote ramp rate configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "ramp_rate_off_to_on_remote"
+    _attr_name: str = "Remote ramp rate off to on"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliRemoteDimmingDownSpeed(
+    ZHANumberConfigurationEntity, id_suffix="dimming_speed_down_remote"
+):
+    """Inovelli remote dimming down speed configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "dimming_speed_down_remote"
+    _attr_name: str = "Remote dimming down speed"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliLocalDimmingDownSpeed(
+    ZHANumberConfigurationEntity, id_suffix="dimming_speed_down_local"
+):
+    """Inovelli local dimming down speed configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "dimming_speed_down_local"
+    _attr_name: str = "Local dimming down speed"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliLocalRampRateOnToOff(
+    ZHANumberConfigurationEntity, id_suffix="ramp_rate_on_to_off_local"
+):
+    """Inovelli local on to off ramp rate configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "ramp_rate_on_to_off_local"
+    _attr_name: str = "Local ramp rate on to off"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliRemoteDimmingSpeedOnToOff(
+    ZHANumberConfigurationEntity, id_suffix="ramp_rate_on_to_off_remote"
+):
+    """Inovelli remote on to off ramp rate configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[3]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 127
+    _zcl_attribute: str = "ramp_rate_on_to_off_remote"
+    _attr_name: str = "Remote ramp rate on to off"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliMinimumLoadDimmingLevel(
+    ZHANumberConfigurationEntity, id_suffix="minimum_level"
+):
+    """Inovelli minimum load dimming level configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[16]
+    _attr_native_min_value: float = 1
+    _attr_native_max_value: float = 254
+    _zcl_attribute: str = "minimum_level"
+    _attr_name: str = "Minimum load dimming level"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliMaximumLoadDimmingLevel(
+    ZHANumberConfigurationEntity, id_suffix="maximum_level"
+):
+    """Inovelli maximum load dimming level configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[16]
+    _attr_native_min_value: float = 2
+    _attr_native_max_value: float = 255
+    _zcl_attribute: str = "maximum_level"
+    _attr_name: str = "Maximum load dimming level"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliAutoShutoffTimer(
+    ZHANumberConfigurationEntity, id_suffix="auto_off_timer"
+):
+    """Inovelli automatic switch shutoff timer configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[14]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 32767
+    _zcl_attribute: str = "auto_off_timer"
+    _attr_name: str = "Automatic switch shutoff timer"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliLoadLevelIndicatorTimeout(
+    ZHANumberConfigurationEntity, id_suffix="load_level_indicator_timeout"
+):
+    """Inovelli load level indicator timeout configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[14]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 11
+    _zcl_attribute: str = "load_level_indicator_timeout"
+    _attr_name: str = "Load level indicator timeout"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliDefaultAllLEDOnColor(
+    ZHANumberConfigurationEntity, id_suffix="led_color_when_on"
+):
+    """Inovelli default all led color when on configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[15]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 255
+    _zcl_attribute: str = "led_color_when_on"
+    _attr_name: str = "Default all LED on color"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliDefaultAllLEDOffColor(
+    ZHANumberConfigurationEntity, id_suffix="led_color_when_off"
+):
+    """Inovelli default all led color when off configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[15]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 255
+    _zcl_attribute: str = "led_color_when_off"
+    _attr_name: str = "Default all LED off color"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliDefaultAllLEDOnIntensity(
+    ZHANumberConfigurationEntity, id_suffix="led_intensity_when_on"
+):
+    """Inovelli default all led intensity when on configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[16]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 100
+    _zcl_attribute: str = "led_intensity_when_on"
+    _attr_name: str = "Default all LED on intensity"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(channel_names=CHANNEL_INOVELLI)
+class InovelliDefaultAllLEDOffIntensity(
+    ZHANumberConfigurationEntity, id_suffix="led_intensity_when_off"
+):
+    """Inovelli default all led intensity when off configuration entity."""
+
+    _attr_entity_category = EntityCategory.CONFIG
+    _attr_icon: str = ICONS[16]
+    _attr_native_min_value: float = 0
+    _attr_native_max_value: float = 100
+    _zcl_attribute: str = "led_intensity_when_off"
+    _attr_name: str = "Default all LED off intensity"
diff --git a/homeassistant/components/zha/select.py b/homeassistant/components/zha/select.py
index 503c5a013a86984c7b40be0a459d6f85a0866385..8b2623b4de1e807c4000cf154a33f8b1731df9ac 100644
--- a/homeassistant/components/zha/select.py
+++ b/homeassistant/components/zha/select.py
@@ -21,6 +21,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from .core import discovery
 from .core.const import (
     CHANNEL_IAS_WD,
+    CHANNEL_INOVELLI,
     CHANNEL_ON_OFF,
     DATA_ZHA,
     SIGNAL_ADD_ENTITIES,
@@ -68,7 +69,7 @@ class ZHAEnumSelectEntity(ZhaEntity, SelectEntity):
     """Representation of a ZHA select entity."""
 
     _attr_entity_category = EntityCategory.CONFIG
-    _attr_name: str
+    _attribute: str
     _enum: type[Enum]
 
     def __init__(
@@ -79,7 +80,7 @@ class ZHAEnumSelectEntity(ZhaEntity, SelectEntity):
         **kwargs: Any,
     ) -> None:
         """Init this select entity."""
-        self._attr_name = self._enum.__name__
+        self._attribute = self._enum.__name__
         self._attr_options = [entry.name.replace("_", " ") for entry in self._enum]
         self._channel: ZigbeeChannel = channels[0]
         super().__init__(unique_id, zha_device, channels, **kwargs)
@@ -87,21 +88,21 @@ class ZHAEnumSelectEntity(ZhaEntity, SelectEntity):
     @property
     def current_option(self) -> str | None:
         """Return the selected entity option to represent the entity state."""
-        option = self._channel.data_cache.get(self._attr_name)
+        option = self._channel.data_cache.get(self._attribute)
         if option is None:
             return None
         return option.name.replace("_", " ")
 
     async def async_select_option(self, option: str) -> None:
         """Change the selected option."""
-        self._channel.data_cache[self._attr_name] = self._enum[option.replace(" ", "_")]
+        self._channel.data_cache[self._attribute] = self._enum[option.replace(" ", "_")]
         self.async_write_ha_state()
 
     @callback
     def async_restore_last_state(self, last_state) -> None:
         """Restore previous state."""
         if last_state.state and last_state.state != STATE_UNKNOWN:
-            self._channel.data_cache[self._attr_name] = self._enum[
+            self._channel.data_cache[self._attribute] = self._enum[
                 last_state.state.replace(" ", "_")
             ]
 
@@ -285,3 +286,40 @@ class AqaraCurtainMode(ZCLEnumSelectEntity, id_suffix="window_covering_mode"):
 
     _select_attr = "window_covering_mode"
     _enum = AqaraE1ReverseDirection
+
+
+class InovelliOutputMode(types.enum1):
+    """Inovelli output mode."""
+
+    Dimmer = 0x00
+    OnOff = 0x01
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliOutputModeEntity(ZCLEnumSelectEntity, id_suffix="output_mode"):
+    """Inovelli output mode control."""
+
+    _select_attr = "output_mode"
+    _enum = InovelliOutputMode
+    _attr_name: str = "Output mode"
+
+
+class InovelliSwitchType(types.enum8):
+    """Inovelli output mode."""
+
+    Load_Only = 0x00
+    Three_Way_Dumb = 0x01
+    Three_Way_AUX = 0x02
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliSwitchTypeEntity(ZCLEnumSelectEntity, id_suffix="switch_type"):
+    """Inovelli switch type control."""
+
+    _select_attr = "switch_type"
+    _enum = InovelliSwitchType
+    _attr_name: str = "Switch type"
diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json
index 1de5e164feeeff21801392bdfc005212ed8ff7b7..3901f9f94399b9b57bab6323b5cd31650a47fd32 100644
--- a/homeassistant/components/zha/strings.json
+++ b/homeassistant/components/zha/strings.json
@@ -160,7 +160,12 @@
     }
   },
   "device_automation": {
-    "action_type": { "squawk": "Squawk", "warn": "Warn" },
+    "action_type": {
+      "squawk": "Squawk",
+      "warn": "Warn",
+      "issue_all_led_effect": "Issue effect for all LEDs",
+      "issue_individual_led_effect": "Issue effect for individual LED"
+    },
     "trigger_type": {
       "remote_button_short_press": "\"{subtype}\" button pressed",
       "remote_button_short_release": "\"{subtype}\" button released",
diff --git a/homeassistant/components/zha/switch.py b/homeassistant/components/zha/switch.py
index 752df6d568e7921d77705ee63c958fdca86597b9..47568648f2ba426aecb456a1895ee68c96df243a 100644
--- a/homeassistant/components/zha/switch.py
+++ b/homeassistant/components/zha/switch.py
@@ -19,6 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
 from .core import discovery
 from .core.const import (
+    CHANNEL_INOVELLI,
     CHANNEL_ON_OFF,
     DATA_ZHA,
     SIGNAL_ADD_ENTITIES,
@@ -309,3 +310,81 @@ class DisableLed(ZHASwitchConfigurationEntity, id_suffix="disable_led"):
     """ZHA BinarySensor."""
 
     _zcl_attribute: str = "disable_led"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliInvertSwitch(ZHASwitchConfigurationEntity, id_suffix="invert_switch"):
+    """Inovelli invert switch control."""
+
+    _zcl_attribute: str = "invert_switch"
+    _attr_name: str = "Invert switch"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliSmartBulbMode(ZHASwitchConfigurationEntity, id_suffix="smart_bulb_mode"):
+    """Inovelli smart bulb mode control."""
+
+    _zcl_attribute: str = "smart_bulb_mode"
+    _attr_name: str = "Smart bulb mode"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliDoubleTapForFullBrightness(
+    ZHASwitchConfigurationEntity, id_suffix="double_tap_up_for_full_brightness"
+):
+    """Inovelli double tap for full brightness control."""
+
+    _zcl_attribute: str = "double_tap_up_for_full_brightness"
+    _attr_name: str = "Double tap full brightness"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliLocalProtection(
+    ZHASwitchConfigurationEntity, id_suffix="local_protection"
+):
+    """Inovelli local protection control."""
+
+    _zcl_attribute: str = "local_protection"
+    _attr_name: str = "Local protection"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliOnOffLEDMode(ZHASwitchConfigurationEntity, id_suffix="on_off_led_mode"):
+    """Inovelli only 1 LED mode control."""
+
+    _zcl_attribute: str = "on_off_led_mode"
+    _attr_name: str = "Only 1 LED mode"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliFirmwareProgressLED(
+    ZHASwitchConfigurationEntity, id_suffix="firmware_progress_led"
+):
+    """Inovelli firmware progress LED control."""
+
+    _zcl_attribute: str = "firmware_progress_led"
+    _attr_name: str = "Firmware progress LED"
+
+
+@CONFIG_DIAGNOSTIC_MATCH(
+    channel_names=CHANNEL_INOVELLI,
+)
+class InovelliRelayClickInOnOffMode(
+    ZHASwitchConfigurationEntity, id_suffix="relay_click_in_on_off_mode"
+):
+    """Inovelli relay click in on off mode control."""
+
+    _zcl_attribute: str = "relay_click_in_on_off_mode"
+    _attr_name: str = "Disable relay click in on off mode"
diff --git a/homeassistant/components/zha/translations/en.json b/homeassistant/components/zha/translations/en.json
index 1ba19bc0f9ebb87a885165298946fe5277537ab1..adf89983256695bf18b276d0e5efa56562abb7fd 100644
--- a/homeassistant/components/zha/translations/en.json
+++ b/homeassistant/components/zha/translations/en.json
@@ -117,7 +117,9 @@
     "device_automation": {
         "action_type": {
             "squawk": "Squawk",
-            "warn": "Warn"
+            "warn": "Warn",
+            "issue_all_led_effect": "Issue effect for all LEDs",
+            "issue_individual_led_effect": "Issue effect for individual LED"
         },
         "trigger_subtype": {
             "both_buttons": "Both buttons",
diff --git a/tests/components/zha/test_device_action.py b/tests/components/zha/test_device_action.py
index f24ec054c0b7fbd1c5ddce1ea9ed303c2653d135..e745856c34200a26590710c98fe9d891b2028216 100644
--- a/tests/components/zha/test_device_action.py
+++ b/tests/components/zha/test_device_action.py
@@ -1,7 +1,8 @@
 """The test for zha device automation actions."""
-from unittest.mock import patch
+from unittest.mock import call, patch
 
 import pytest
+from zhaquirks.inovelli.VZM31SN import InovelliVZM31SNv11
 import zigpy.profiles.zha
 import zigpy.zcl.clusters.general as general
 import zigpy.zcl.clusters.security as security
@@ -16,7 +17,12 @@ from homeassistant.setup import async_setup_component
 
 from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_TYPE
 
-from tests.common import async_get_device_automations, async_mock_service, mock_coro
+from tests.common import (
+    assert_lists_same,
+    async_get_device_automations,
+    async_mock_service,
+    mock_coro,
+)
 from tests.components.blueprint.conftest import stub_blueprint_populate  # noqa: F401
 
 SHORT_PRESS = "remote_button_short_press"
@@ -31,10 +37,13 @@ def required_platforms_only():
         "homeassistant.components.zha.PLATFORMS",
         (
             Platform.BINARY_SENSOR,
+            Platform.BUTTON,
             Platform.DEVICE_TRACKER,
+            Platform.LIGHT,
             Platform.NUMBER,
             Platform.SELECT,
             Platform.SENSOR,
+            Platform.SWITCH,
             Platform.SIREN,
         ),
     ):
@@ -62,6 +71,36 @@ async def device_ias(hass, zigpy_device_mock, zha_device_joined_restored):
     return zigpy_device, zha_device
 
 
+@pytest.fixture
+async def device_inovelli(hass, zigpy_device_mock, zha_device_joined):
+    """Inovelli device fixture."""
+
+    zigpy_device = zigpy_device_mock(
+        {
+            1: {
+                SIG_EP_INPUT: [
+                    general.Basic.cluster_id,
+                    general.Identify.cluster_id,
+                    general.OnOff.cluster_id,
+                    general.LevelControl.cluster_id,
+                    0xFC31,
+                ],
+                SIG_EP_OUTPUT: [],
+                SIG_EP_TYPE: zigpy.profiles.zha.DeviceType.DIMMABLE_LIGHT,
+            }
+        },
+        ieee="00:1d:8f:08:0c:90:69:6b",
+        manufacturer="Inovelli",
+        model="VZM31-SN",
+        quirk=InovelliVZM31SNv11,
+    )
+
+    zha_device = await zha_device_joined(zigpy_device)
+    zha_device.update_available(True)
+    await hass.async_block_till_done()
+    return zigpy_device, zha_device
+
+
 async def test_get_actions(hass, device_ias):
     """Test we get the expected actions from a zha device."""
 
@@ -112,21 +151,108 @@ async def test_get_actions(hass, device_ias):
         },
     ]
 
-    assert actions == expected_actions
+    assert_lists_same(actions, expected_actions)
 
 
-async def test_action(hass, device_ias):
+async def test_get_inovelli_actions(hass, device_inovelli):
+    """Test we get the expected actions from a zha device."""
+
+    inovelli_ieee_address = str(device_inovelli[0].ieee)
+    ha_device_registry = dr.async_get(hass)
+    inovelli_reg_device = ha_device_registry.async_get_device(
+        {(DOMAIN, inovelli_ieee_address)}
+    )
+
+    actions = await async_get_device_automations(
+        hass, DeviceAutomationType.ACTION, inovelli_reg_device.id
+    )
+
+    expected_actions = [
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": DOMAIN,
+            "metadata": {},
+            "type": "issue_all_led_effect",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": DOMAIN,
+            "metadata": {},
+            "type": "issue_individual_led_effect",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.BUTTON,
+            "entity_id": "button.inovelli_vzm31_sn_identifybutton",
+            "metadata": {"secondary": True},
+            "type": "press",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "turn_off",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "turn_on",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "toggle",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "brightness_increase",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "brightness_decrease",
+        },
+        {
+            "device_id": inovelli_reg_device.id,
+            "domain": Platform.LIGHT,
+            "entity_id": "light.inovelli_vzm31_sn_light",
+            "metadata": {"secondary": False},
+            "type": "flash",
+        },
+    ]
+
+    assert_lists_same(actions, expected_actions)
+
+
+async def test_action(hass, device_ias, device_inovelli):
     """Test for executing a zha device action."""
     zigpy_device, zha_device = device_ias
+    inovelli_zigpy_device, inovelli_zha_device = device_inovelli
 
     zigpy_device.device_automation_triggers = {
         (SHORT_PRESS, SHORT_PRESS): {COMMAND: COMMAND_SINGLE}
     }
 
     ieee_address = str(zha_device.ieee)
+    inovelli_ieee_address = str(inovelli_zha_device.ieee)
 
     ha_device_registry = dr.async_get(hass)
     reg_device = ha_device_registry.async_get_device({(DOMAIN, ieee_address)})
+    inovelli_reg_device = ha_device_registry.async_get_device(
+        {(DOMAIN, inovelli_ieee_address)}
+    )
+
+    cluster = inovelli_zigpy_device.endpoints[1].in_clusters[0xFC31]
 
     with patch(
         "zigpy.zcl.Cluster.request",
@@ -145,11 +271,32 @@ async def test_action(hass, device_ias):
                             "type": SHORT_PRESS,
                             "subtype": SHORT_PRESS,
                         },
-                        "action": {
-                            "domain": DOMAIN,
-                            "device_id": reg_device.id,
-                            "type": "warn",
-                        },
+                        "action": [
+                            {
+                                "domain": DOMAIN,
+                                "device_id": reg_device.id,
+                                "type": "warn",
+                            },
+                            {
+                                "domain": DOMAIN,
+                                "device_id": inovelli_reg_device.id,
+                                "type": "issue_all_led_effect",
+                                "effect_type": "Open_Close",
+                                "duration": 5,
+                                "level": 10,
+                                "color": 41,
+                            },
+                            {
+                                "domain": DOMAIN,
+                                "device_id": inovelli_reg_device.id,
+                                "type": "issue_individual_led_effect",
+                                "effect_type": "Open_Close",
+                                "led_number": 1,
+                                "duration": 5,
+                                "level": 10,
+                                "color": 41,
+                            },
+                        ],
                     }
                 ]
             },
@@ -167,6 +314,41 @@ async def test_action(hass, device_ias):
         assert calls[0].service == "warning_device_warn"
         assert calls[0].data["ieee"] == ieee_address
 
+        assert len(cluster.request.mock_calls) == 2
+        assert (
+            call(
+                False,
+                cluster.commands_by_name["led_effect"].id,
+                cluster.commands_by_name["led_effect"].schema,
+                6,
+                41,
+                10,
+                5,
+                expect_reply=False,
+                manufacturer=4151,
+                tries=1,
+                tsn=None,
+            )
+            in cluster.request.call_args_list
+        )
+        assert (
+            call(
+                False,
+                cluster.commands_by_name["individual_led_effect"].id,
+                cluster.commands_by_name["individual_led_effect"].schema,
+                1,
+                6,
+                41,
+                10,
+                5,
+                expect_reply=False,
+                manufacturer=4151,
+                tries=1,
+                tsn=None,
+            )
+            in cluster.request.call_args_list
+        )
+
 
 async def test_invalid_zha_event_type(hass, device_ias):
     """Test that unexpected types are not passed to `zha_send_event`."""