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
This commit is contained in:
parent
57c766c03c
commit
73e26b71b1
5 changed files with 132 additions and 137 deletions
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue