From 73e26b71b1d4d2ee8707952e46eff04836bc404f Mon Sep 17 00:00:00 2001
From: puddly <32534428+puddly@users.noreply.github.com>
Date: Thu, 1 Sep 2022 15:32:32 -0400
Subject: [PATCH] Migrate ZHA lighting to use newer zigpy ZCL request syntax
 (#77676)

* Migrate unit test to use more command definition constants

* Use keyword argument syntax for sending ZCL requests

* Ensure all ZHA unit tests pass
---
 homeassistant/components/zha/core/const.py  |   6 -
 homeassistant/components/zha/core/device.py |   7 +-
 homeassistant/components/zha/light.py       |  96 +++++++------
 tests/components/zha/test_discover.py       |   8 +-
 tests/components/zha/test_light.py          | 152 ++++++++++----------
 5 files changed, 132 insertions(+), 137 deletions(-)

diff --git a/homeassistant/components/zha/core/const.py b/homeassistant/components/zha/core/const.py
index a1c5a55bd76..311d3d48b5b 100644
--- a/homeassistant/components/zha/core/const.py
+++ b/homeassistant/components/zha/core/const.py
@@ -396,12 +396,6 @@ ZHA_GW_MSG_LOG_OUTPUT = "log_output"
 ZHA_GW_MSG_RAW_INIT = "raw_device_initialized"
 ZHA_DEVICES_LOADED_EVENT = "zha_devices_loaded_event"
 
-EFFECT_BLINK = 0x00
-EFFECT_BREATHE = 0x01
-EFFECT_OKAY = 0x02
-
-EFFECT_DEFAULT_VARIANT = 0x00
-
 
 class Strobe(t.enum8):
     """Strobe enum."""
diff --git a/homeassistant/components/zha/core/device.py b/homeassistant/components/zha/core/device.py
index 150241a091b..a0a4521e19d 100644
--- a/homeassistant/components/zha/core/device.py
+++ b/homeassistant/components/zha/core/device.py
@@ -17,7 +17,7 @@ import zigpy.exceptions
 from zigpy.profiles import PROFILES
 import zigpy.quirks
 from zigpy.types.named import EUI64, NWK
-from zigpy.zcl.clusters.general import Groups
+from zigpy.zcl.clusters.general import Groups, Identify
 import zigpy.zdo.types as zdo_types
 
 from homeassistant.const import ATTR_COMMAND, ATTR_NAME
@@ -65,8 +65,6 @@ from .const import (
     CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY,
     CONF_DEFAULT_CONSIDER_UNAVAILABLE_MAINS,
     CONF_ENABLE_IDENTIFY_ON_JOIN,
-    EFFECT_DEFAULT_VARIANT,
-    EFFECT_OKAY,
     POWER_BATTERY_OR_UNKNOWN,
     POWER_MAINS_POWERED,
     SIGNAL_AVAILABLE,
@@ -488,7 +486,8 @@ class ZHADevice(LogMixin):
             and not self.skip_configuration
         ):
             await self._channels.identify_ch.trigger_effect(
-                EFFECT_OKAY, EFFECT_DEFAULT_VARIANT
+                effect_id=Identify.EffectIdentifier.Okay,
+                effect_variant=Identify.EffectVariant.Default,
             )
 
     async def async_initialize(self, from_cache: bool = False) -> None:
diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py
index 5a8011e2386..dbb250a5d33 100644
--- a/homeassistant/components/zha/light.py
+++ b/homeassistant/components/zha/light.py
@@ -47,9 +47,6 @@ from .core.const import (
     CONF_ENABLE_ENHANCED_LIGHT_TRANSITION,
     CONF_ENABLE_LIGHT_TRANSITIONING_FLAG,
     DATA_ZHA,
-    EFFECT_BLINK,
-    EFFECT_BREATHE,
-    EFFECT_DEFAULT_VARIANT,
     SIGNAL_ADD_ENTITIES,
     SIGNAL_ATTR_UPDATED,
     SIGNAL_SET_LEVEL,
@@ -70,14 +67,11 @@ DEFAULT_EXTRA_TRANSITION_DELAY_LONG = 2.0
 DEFAULT_LONG_TRANSITION_TIME = 10
 DEFAULT_MIN_BRIGHTNESS = 2
 
-UPDATE_COLORLOOP_ACTION = 0x1
-UPDATE_COLORLOOP_DIRECTION = 0x2
-UPDATE_COLORLOOP_TIME = 0x4
-UPDATE_COLORLOOP_HUE = 0x8
+FLASH_EFFECTS = {
+    light.FLASH_SHORT: Identify.EffectIdentifier.Blink,
+    light.FLASH_LONG: Identify.EffectIdentifier.Breathe,
+}
 
-FLASH_EFFECTS = {light.FLASH_SHORT: EFFECT_BLINK, light.FLASH_LONG: EFFECT_BREATHE}
-
-UNSUPPORTED_ATTRIBUTE = 0x86
 STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, Platform.LIGHT)
 GROUP_MATCH = functools.partial(ZHA_ENTITIES.group_match, Platform.LIGHT)
 PARALLEL_UPDATES = 0
@@ -157,7 +151,7 @@ class BaseLight(LogMixin, light.LightEntity):
         return self._attr_state
 
     @callback
-    def set_level(self, value):
+    def set_level(self, value: int) -> None:
         """Set the brightness of this light between 0..254.
 
         brightness level 255 is a special value instructing the device to come
@@ -275,7 +269,8 @@ class BaseLight(LogMixin, light.LightEntity):
             # If the light is currently off, we first need to turn it on at a low brightness level with no transition.
             # After that, we set it to the desired color/temperature with no transition.
             result = await self._level_channel.move_to_level_with_on_off(
-                DEFAULT_MIN_BRIGHTNESS, self._DEFAULT_MIN_TRANSITION_TIME
+                level=DEFAULT_MIN_BRIGHTNESS,
+                transition_time=self._DEFAULT_MIN_TRANSITION_TIME,
             )
             t_log["move_to_level_with_on_off"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@@ -294,7 +289,8 @@ class BaseLight(LogMixin, light.LightEntity):
             and brightness_supported(self._attr_supported_color_modes)
         ):
             result = await self._level_channel.move_to_level_with_on_off(
-                level, duration
+                level=level,
+                transition_time=duration,
             )
             t_log["move_to_level_with_on_off"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@@ -340,7 +336,9 @@ class BaseLight(LogMixin, light.LightEntity):
 
         if new_color_provided_while_off:
             # The light is has the correct color, so we can now transition it to the correct brightness level.
-            result = await self._level_channel.move_to_level(level, duration)
+            result = await self._level_channel.move_to_level(
+                level=level, transition_time=duration
+            )
             t_log["move_to_level_if_color"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
                 self.debug("turned on: %s", t_log)
@@ -355,13 +353,15 @@ class BaseLight(LogMixin, light.LightEntity):
 
         if effect == light.EFFECT_COLORLOOP:
             result = await self._color_channel.color_loop_set(
-                UPDATE_COLORLOOP_ACTION
-                | UPDATE_COLORLOOP_DIRECTION
-                | UPDATE_COLORLOOP_TIME,
-                0x2,  # start from current hue
-                0x1,  # only support up
-                transition if transition else 7,  # transition
-                0,  # no hue
+                update_flags=(
+                    Color.ColorLoopUpdateFlags.Action
+                    | Color.ColorLoopUpdateFlags.Direction
+                    | Color.ColorLoopUpdateFlags.Time
+                ),
+                action=Color.ColorLoopAction.Activate_from_current_hue,
+                direction=Color.ColorLoopDirection.Increment,
+                time=transition if transition else 7,
+                start_hue=0,
             )
             t_log["color_loop_set"] = result
             self._attr_effect = light.EFFECT_COLORLOOP
@@ -370,18 +370,19 @@ class BaseLight(LogMixin, light.LightEntity):
             and effect != light.EFFECT_COLORLOOP
         ):
             result = await self._color_channel.color_loop_set(
-                UPDATE_COLORLOOP_ACTION,
-                0x0,
-                0x0,
-                0x0,
-                0x0,  # update action only, action off, no dir, time, hue
+                update_flags=Color.ColorLoopUpdateFlags.Action,
+                action=Color.ColorLoopAction.Deactivate,
+                direction=Color.ColorLoopDirection.Decrement,
+                time=0,
+                start_hue=0,
             )
             t_log["color_loop_set"] = result
             self._attr_effect = None
 
         if flash is not None:
             result = await self._identify_channel.trigger_effect(
-                FLASH_EFFECTS[flash], EFFECT_DEFAULT_VARIANT
+                effect_id=FLASH_EFFECTS[flash],
+                effect_variant=Identify.EffectVariant.Default,
             )
             t_log["trigger_effect"] = result
 
@@ -400,6 +401,7 @@ class BaseLight(LogMixin, light.LightEntity):
             if transition is not None
             else DEFAULT_ON_OFF_TRANSITION
         ) + DEFAULT_EXTRA_TRANSITION_DELAY_SHORT
+
         # Start pausing attribute report parsing
         if self._zha_config_enable_light_transitioning_flag:
             self.async_transition_set_flag()
@@ -407,7 +409,8 @@ class BaseLight(LogMixin, light.LightEntity):
         # is not none looks odd here but it will override built in bulb transition times if we pass 0 in here
         if transition is not None and supports_level:
             result = await self._level_channel.move_to_level_with_on_off(
-                0, transition * 10 or self._DEFAULT_MIN_TRANSITION_TIME
+                level=0,
+                transition_time=(transition * 10 or self._DEFAULT_MIN_TRANSITION_TIME),
             )
         else:
             result = await self._on_off_channel.off()
@@ -437,12 +440,17 @@ class BaseLight(LogMixin, light.LightEntity):
         t_log,
     ):
         """Process ZCL color commands."""
+
+        transition_time = (
+            self._DEFAULT_MIN_TRANSITION_TIME
+            if new_color_provided_while_off
+            else duration
+        )
+
         if temperature is not None:
             result = await self._color_channel.move_to_color_temp(
-                temperature,
-                self._DEFAULT_MIN_TRANSITION_TIME
-                if new_color_provided_while_off
-                else duration,
+                color_temp_mireds=temperature,
+                transition_time=transition_time,
             )
             t_log["move_to_color_temp"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@@ -458,20 +466,16 @@ class BaseLight(LogMixin, light.LightEntity):
                 and self._color_channel.enhanced_hue_supported
             ):
                 result = await self._color_channel.enhanced_move_to_hue_and_saturation(
-                    int(hs_color[0] * 65535 / 360),
-                    int(hs_color[1] * 2.54),
-                    self._DEFAULT_MIN_TRANSITION_TIME
-                    if new_color_provided_while_off
-                    else duration,
+                    enhanced_hue=int(hs_color[0] * 65535 / 360),
+                    saturation=int(hs_color[1] * 2.54),
+                    transition_time=transition_time,
                 )
                 t_log["enhanced_move_to_hue_and_saturation"] = result
             else:
                 result = await self._color_channel.move_to_hue_and_saturation(
-                    int(hs_color[0] * 254 / 360),
-                    int(hs_color[1] * 2.54),
-                    self._DEFAULT_MIN_TRANSITION_TIME
-                    if new_color_provided_while_off
-                    else duration,
+                    hue=int(hs_color[0] * 254 / 360),
+                    saturation=int(hs_color[1] * 2.54),
+                    transition_time=transition_time,
                 )
                 t_log["move_to_hue_and_saturation"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@@ -484,11 +488,9 @@ class BaseLight(LogMixin, light.LightEntity):
 
         if xy_color is not None:
             result = await self._color_channel.move_to_color(
-                int(xy_color[0] * 65535),
-                int(xy_color[1] * 65535),
-                self._DEFAULT_MIN_TRANSITION_TIME
-                if new_color_provided_while_off
-                else duration,
+                color_x=int(xy_color[0] * 65535),
+                color_y=int(xy_color[1] * 65535),
+                transition_time=transition_time,
             )
             t_log["move_to_color"] = result
             if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
diff --git a/tests/components/zha/test_discover.py b/tests/components/zha/test_discover.py
index 0f51141ec5d..e3cb53efcd4 100644
--- a/tests/components/zha/test_discover.py
+++ b/tests/components/zha/test_discover.py
@@ -137,10 +137,12 @@ async def test_devices(
         if called:
             assert cluster_identify.request.call_args == mock.call(
                 False,
-                64,
+                cluster_identify.commands_by_name["trigger_effect"].id,
                 cluster_identify.commands_by_name["trigger_effect"].schema,
-                2,
-                0,
+                effect_id=zigpy.zcl.clusters.general.Identify.EffectIdentifier.Okay,
+                effect_variant=(
+                    zigpy.zcl.clusters.general.Identify.EffectVariant.Default
+                ),
                 expect_reply=True,
                 manufacturer=None,
                 tries=1,
diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py
index 156f692aa14..5f5e7ab2e38 100644
--- a/tests/components/zha/test_light.py
+++ b/tests/components/zha/test_light.py
@@ -33,8 +33,6 @@ from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE
 from tests.common import async_fire_time_changed
 from tests.components.zha.common import async_wait_for_updates
 
-ON = 1
-OFF = 0
 IEEE_GROUPABLE_DEVICE = "01:2d:6f:00:0a:90:69:e8"
 IEEE_GROUPABLE_DEVICE2 = "02:2d:6f:00:0a:90:69:e9"
 IEEE_GROUPABLE_DEVICE3 = "03:2d:6f:00:0a:90:69:e7"
@@ -463,10 +461,10 @@ async def test_transitions(
     assert dev1_cluster_level.request.await_count == 1
     assert dev1_cluster_level.request.call_args == call(
         False,
-        4,
+        dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        50,  # brightness (level in ZCL)
-        0,  # transition time
+        level=50,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -499,10 +497,10 @@ async def test_transitions(
     assert dev1_cluster_level.request.await_count == 1
     assert dev1_cluster_level.request.call_args == call(
         False,
-        4,
+        dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        18,  # brightness (level in ZCL)
-        30,  # transition time (ZCL time in 10ths of a second)
+        level=18,
+        transition_time=30,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -510,10 +508,10 @@ async def test_transitions(
     )
     assert dev1_cluster_color.request.call_args == call(
         False,
-        10,
+        dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        432,  # color temp mireds
-        30.0,  # transition time (ZCL time in 10ths of a second)
+        color_temp_mireds=432,
+        transition_time=30.0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -547,10 +545,10 @@ async def test_transitions(
     assert dev1_cluster_level.request.await_count == 1
     assert dev1_cluster_level.request.call_args == call(
         False,
-        4,
+        dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        0,  # brightness (level in ZCL)
-        0,  # transition time (ZCL time in 10ths of a second)
+        level=0,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -584,10 +582,10 @@ async def test_transitions(
     # first it comes on with no transition at 2 brightness
     assert dev1_cluster_level.request.call_args_list[0] == call(
         False,
-        4,
+        dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        2,  # brightness (level in ZCL)
-        0,  # transition time (ZCL time in 10ths of a second)
+        level=2,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -595,10 +593,10 @@ async def test_transitions(
     )
     assert dev1_cluster_color.request.call_args == call(
         False,
-        10,
+        dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        235,  # color temp mireds
-        0,  # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off
+        color_temp_mireds=235,
+        transition_time=0,  # no transition when new_color_provided_while_off
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -606,10 +604,10 @@ async def test_transitions(
     )
     assert dev1_cluster_level.request.call_args_list[1] == call(
         False,
-        0,
+        dev1_cluster_level.commands_by_name["move_to_level"].id,
         dev1_cluster_level.commands_by_name["move_to_level"].schema,
-        25,  # brightness (level in ZCL)
-        10.0,  # transition time (ZCL time in 10ths of a second)
+        level=25,
+        transition_time=10,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -668,10 +666,10 @@ async def test_transitions(
     # first it comes on with no transition at 2 brightness
     assert dev1_cluster_level.request.call_args_list[0] == call(
         False,
-        4,
+        dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        2,  # brightness (level in ZCL)
-        0,  # transition time (ZCL time in 10ths of a second)
+        level=2,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -679,10 +677,10 @@ async def test_transitions(
     )
     assert dev1_cluster_color.request.call_args == call(
         False,
-        10,
+        dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        236,  # color temp mireds
-        0,  # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off
+        color_temp_mireds=236,
+        transition_time=0,  # no transition when new_color_provided_while_off
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -690,10 +688,10 @@ async def test_transitions(
     )
     assert dev1_cluster_level.request.call_args_list[1] == call(
         False,
-        0,
+        dev1_cluster_level.commands_by_name["move_to_level"].id,
         dev1_cluster_level.commands_by_name["move_to_level"].schema,
-        25,  # brightness (level in ZCL)
-        0,  # transition time (ZCL time in 10ths of a second)
+        level=25,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -750,7 +748,7 @@ async def test_transitions(
 
     assert dev1_cluster_on_off.request.call_args == call(
         False,
-        1,
+        dev1_cluster_on_off.commands_by_name["on"].id,
         dev1_cluster_on_off.commands_by_name["on"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -760,10 +758,10 @@ async def test_transitions(
 
     assert dev1_cluster_color.request.call_args == call(
         False,
-        10,
+        dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        236,  # color temp mireds
-        0,  # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off
+        color_temp_mireds=236,
+        transition_time=0,  # no transition when new_color_provided_while_off
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -820,10 +818,10 @@ async def test_transitions(
     assert dev2_cluster_level.request.await_count == 1
     assert dev2_cluster_level.request.call_args == call(
         False,
-        4,
+        dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        100,  # brightness (level in ZCL)
-        1,  # transition time - sengled light uses default minimum
+        level=100,
+        transition_time=1,  # transition time - sengled light uses default minimum
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -878,10 +876,10 @@ async def test_transitions(
     # first it comes on with no transition at 2 brightness
     assert dev2_cluster_level.request.call_args_list[0] == call(
         False,
-        4,
+        dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        2,  # brightness (level in ZCL)
-        1,  # transition time (ZCL time in 10ths of a second)
+        level=2,
+        transition_time=1,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -889,10 +887,10 @@ async def test_transitions(
     )
     assert dev2_cluster_color.request.call_args == call(
         False,
-        10,
+        dev2_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev2_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        235,  # color temp mireds
-        1,  # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when new_color_provided_while_off
+        color_temp_mireds=235,
+        transition_time=1,  # sengled transition == 1 when new_color_provided_while_off
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -900,10 +898,10 @@ async def test_transitions(
     )
     assert dev2_cluster_level.request.call_args_list[1] == call(
         False,
-        0,
+        dev2_cluster_level.commands_by_name["move_to_level"].id,
         dev2_cluster_level.commands_by_name["move_to_level"].schema,
-        25,  # brightness (level in ZCL)
-        10.0,  # transition time (ZCL time in 10ths of a second)
+        level=25,
+        transition_time=10,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -965,10 +963,10 @@ async def test_transitions(
     # groups are omitted from the 3 call dance for new_color_provided_while_off
     assert group_color_channel.request.call_args == call(
         False,
-        10,
+        dev2_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev2_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        235,  # color temp mireds
-        10.0,  # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when new_color_provided_while_off
+        color_temp_mireds=235,
+        transition_time=10,  # sengled transition == 1 when new_color_provided_while_off
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -976,10 +974,10 @@ async def test_transitions(
     )
     assert group_level_channel.request.call_args == call(
         False,
-        4,
+        dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        25,  # brightness (level in ZCL)
-        10.0,  # transition time (ZCL time in 10ths of a second)
+        level=25,
+        transition_time=10,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1031,10 +1029,10 @@ async def test_transitions(
     assert dev2_cluster_level.request.await_count == 1
     assert dev2_cluster_level.request.call_args == call(
         False,
-        4,
+        dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        0,  # brightness (level in ZCL)
-        20,  # transition time
+        level=0,
+        transition_time=20,  # transition time
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1061,10 +1059,10 @@ async def test_transitions(
     assert dev2_cluster_level.request.await_count == 1
     assert dev2_cluster_level.request.call_args == call(
         False,
-        4,
+        dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].id,
         dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
-        25,  # brightness (level in ZCL) - this is the last brightness we set a few tests above
-        1,  # transition time - sengled light uses default minimum
+        level=25,
+        transition_time=1,  # transition time - sengled light uses default minimum
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1096,7 +1094,7 @@ async def test_transitions(
     # first it comes on
     assert eWeLink_cluster_on_off.request.call_args_list[0] == call(
         False,
-        1,
+        eWeLink_cluster_on_off.commands_by_name["on"].id,
         eWeLink_cluster_on_off.commands_by_name["on"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -1105,10 +1103,10 @@ async def test_transitions(
     )
     assert dev1_cluster_color.request.call_args == call(
         False,
-        10,
+        dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
         dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
-        235,  # color temp mireds
-        0,  # transition time (ZCL time in 10ths of a second)
+        color_temp_mireds=235,
+        transition_time=0,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1153,7 +1151,7 @@ async def async_test_on_off_from_hass(hass, cluster, entity_id):
     assert cluster.request.await_count == 1
     assert cluster.request.call_args == call(
         False,
-        ON,
+        cluster.commands_by_name["on"].id,
         cluster.commands_by_name["on"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -1176,7 +1174,7 @@ async def async_test_off_from_hass(hass, cluster, entity_id):
     assert cluster.request.await_count == 1
     assert cluster.request.call_args == call(
         False,
-        OFF,
+        cluster.commands_by_name["off"].id,
         cluster.commands_by_name["off"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -1204,7 +1202,7 @@ async def async_test_level_on_off_from_hass(
     assert level_cluster.request.await_count == 0
     assert on_off_cluster.request.call_args == call(
         False,
-        ON,
+        on_off_cluster.commands_by_name["on"].id,
         on_off_cluster.commands_by_name["on"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -1228,7 +1226,7 @@ async def async_test_level_on_off_from_hass(
     assert level_cluster.request.await_count == 1
     assert on_off_cluster.request.call_args == call(
         False,
-        ON,
+        on_off_cluster.commands_by_name["on"].id,
         on_off_cluster.commands_by_name["on"].schema,
         expect_reply=True,
         manufacturer=None,
@@ -1237,10 +1235,10 @@ async def async_test_level_on_off_from_hass(
     )
     assert level_cluster.request.call_args == call(
         False,
-        4,
+        level_cluster.commands_by_name["move_to_level_with_on_off"].id,
         level_cluster.commands_by_name["move_to_level_with_on_off"].schema,
-        254,
-        100.0,
+        level=254,
+        transition_time=100,
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1262,10 +1260,10 @@ async def async_test_level_on_off_from_hass(
     assert level_cluster.request.await_count == 1
     assert level_cluster.request.call_args == call(
         False,
-        4,
+        level_cluster.commands_by_name["move_to_level_with_on_off"].id,
         level_cluster.commands_by_name["move_to_level_with_on_off"].schema,
-        10,
-        expected_default_transition,
+        level=10,
+        transition_time=int(expected_default_transition),
         expect_reply=True,
         manufacturer=None,
         tries=1,
@@ -1305,10 +1303,10 @@ async def async_test_flash_from_hass(hass, cluster, entity_id, flash):
     assert cluster.request.await_count == 1
     assert cluster.request.call_args == call(
         False,
-        64,
+        cluster.commands_by_name["trigger_effect"].id,
         cluster.commands_by_name["trigger_effect"].schema,
-        FLASH_EFFECTS[flash],
-        0,
+        effect_id=FLASH_EFFECTS[flash],
+        effect_variant=general.Identify.EffectVariant.Default,
         expect_reply=True,
         manufacturer=None,
         tries=1,
-- 
GitLab