Allow the ZHA default light transition time to be configured as a float (#92075)

This commit is contained in:
puddly 2023-04-26 15:24:06 -04:00 committed by GitHub
parent 3c44c7416f
commit 4f660cc5f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 27 deletions

View File

@ -151,7 +151,9 @@ CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY = 60 * 60 * 6 # 6 hours
CONF_ZHA_OPTIONS_SCHEMA = vol.Schema(
{
vol.Optional(CONF_DEFAULT_LIGHT_TRANSITION, default=0): cv.positive_int,
vol.Optional(CONF_DEFAULT_LIGHT_TRANSITION, default=0): vol.All(
vol.Coerce(float), vol.Range(min=0, max=2**16 / 10)
),
vol.Required(CONF_ENABLE_ENHANCED_LIGHT_TRANSITION, default=False): cv.boolean,
vol.Required(CONF_ENABLE_LIGHT_TRANSITIONING_FLAG, default=True): cv.boolean,
vol.Required(CONF_ALWAYS_PREFER_XY_COLOR_MODE, default=True): cv.boolean,

View File

@ -113,7 +113,7 @@ class BaseLight(LogMixin, light.LightEntity):
"""Operations common to all light entities."""
_FORCE_ON = False
_DEFAULT_MIN_TRANSITION_TIME = 0
_DEFAULT_MIN_TRANSITION_TIME: float = 0
def __init__(self, *args, **kwargs):
"""Initialize the light."""
@ -181,9 +181,7 @@ class BaseLight(LogMixin, light.LightEntity):
"""Turn the entity on."""
transition = kwargs.get(light.ATTR_TRANSITION)
duration = (
transition * 10
if transition is not None
else self._zha_config_transition * 10
transition if transition is not None else self._zha_config_transition
) or (
# if 0 is passed in some devices still need the minimum default
self._DEFAULT_MIN_TRANSITION_TIME
@ -210,7 +208,7 @@ class BaseLight(LogMixin, light.LightEntity):
) and self._zha_config_enable_light_transitioning_flag
transition_time = (
(
duration / 10 + DEFAULT_EXTRA_TRANSITION_DELAY_SHORT
duration + DEFAULT_EXTRA_TRANSITION_DELAY_SHORT
if (
(brightness is not None or transition is not None)
and brightness_supported(self._attr_supported_color_modes)
@ -297,7 +295,7 @@ class BaseLight(LogMixin, light.LightEntity):
# After that, we set it to the desired color/temperature with no transition.
result = await self._level_cluster_handler.move_to_level_with_on_off(
level=DEFAULT_MIN_BRIGHTNESS,
transition_time=self._DEFAULT_MIN_TRANSITION_TIME,
transition_time=int(10 * 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:
@ -337,7 +335,7 @@ class BaseLight(LogMixin, light.LightEntity):
):
result = await self._level_cluster_handler.move_to_level_with_on_off(
level=level,
transition_time=duration,
transition_time=int(10 * duration),
)
t_log["move_to_level_with_on_off"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@ -390,7 +388,7 @@ class BaseLight(LogMixin, light.LightEntity):
# The light is has the correct color, so we can now transition
# it to the correct brightness level.
result = await self._level_cluster_handler.move_to_level(
level=level, transition_time=duration
level=level, transition_time=int(10 * duration)
)
t_log["move_to_level_if_color"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@ -465,7 +463,9 @@ class BaseLight(LogMixin, light.LightEntity):
if transition is not None and supports_level:
result = await self._level_cluster_handler.move_to_level_with_on_off(
level=0,
transition_time=(transition * 10 or self._DEFAULT_MIN_TRANSITION_TIME),
transition_time=int(
10 * (transition or self._DEFAULT_MIN_TRANSITION_TIME)
),
)
else:
result = await self._on_off_cluster_handler.off()
@ -511,7 +511,7 @@ class BaseLight(LogMixin, light.LightEntity):
if temperature is not None:
result = await self._color_cluster_handler.move_to_color_temp(
color_temp_mireds=temperature,
transition_time=transition_time,
transition_time=int(10 * transition_time),
)
t_log["move_to_color_temp"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@ -529,14 +529,14 @@ class BaseLight(LogMixin, light.LightEntity):
result = await self._color_cluster_handler.enhanced_move_to_hue_and_saturation(
enhanced_hue=int(hs_color[0] * 65535 / 360),
saturation=int(hs_color[1] * 2.54),
transition_time=transition_time,
transition_time=int(10 * transition_time),
)
t_log["enhanced_move_to_hue_and_saturation"] = result
else:
result = await self._color_cluster_handler.move_to_hue_and_saturation(
hue=int(hs_color[0] * 254 / 360),
saturation=int(hs_color[1] * 2.54),
transition_time=transition_time,
transition_time=int(10 * transition_time),
)
t_log["move_to_hue_and_saturation"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@ -551,7 +551,7 @@ class BaseLight(LogMixin, light.LightEntity):
result = await self._color_cluster_handler.move_to_color(
color_x=int(xy_color[0] * 65535),
color_y=int(xy_color[1] * 65535),
transition_time=transition_time,
transition_time=int(10 * transition_time),
)
t_log["move_to_color"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
@ -1091,7 +1091,9 @@ class MinTransitionLight(Light):
"""Representation of a light which does not react to any "move to" calls with 0 as a transition."""
_attr_name: str = "Light"
_DEFAULT_MIN_TRANSITION_TIME = 1
# Transitions are counted in 1/10th of a second increments, so this is the smallest
_DEFAULT_MIN_TRANSITION_TIME = 0.1
@GROUP_MATCH()
@ -1111,10 +1113,18 @@ class LightGroup(BaseLight, ZhaGroupEntity):
group = self.zha_device.gateway.get_group(self._group_id)
self._GROUP_SUPPORTS_EXECUTE_IF_OFF = True # pylint: disable=invalid-name
# Check all group members to see if they support execute_if_off.
# If at least one member has a color cluster and doesn't support it,
# it's not used.
for member in group.members:
# Ensure we do not send group commands that violate the minimum transition
# time of any members.
if member.device.manufacturer in DEFAULT_MIN_TRANSITION_MANUFACTURERS:
self._DEFAULT_MIN_TRANSITION_TIME = ( # pylint: disable=invalid-name
MinTransitionLight._DEFAULT_MIN_TRANSITION_TIME
)
# Check all group members to see if they support execute_if_off.
# If at least one member has a color cluster and doesn't support it,
# it's not used.
for endpoint in member.device._endpoints.values():
for cluster_handler in endpoint.all_cluster_handlers.values():
if (
@ -1124,10 +1134,6 @@ class LightGroup(BaseLight, ZhaGroupEntity):
self._GROUP_SUPPORTS_EXECUTE_IF_OFF = False
break
self._DEFAULT_MIN_TRANSITION_TIME = any( # pylint: disable=invalid-name
member.device.manufacturer in DEFAULT_MIN_TRANSITION_MANUFACTURERS
for member in group.members
)
self._on_off_cluster_handler = group.endpoint[OnOff.cluster_id]
self._level_cluster_handler = group.endpoint[LevelControl.cluster_id]
self._color_cluster_handler = group.endpoint[Color.cluster_id]

View File

@ -4,8 +4,9 @@ BASE_CUSTOM_CONFIGURATION = {
"schemas": {
"zha_options": [
{
"type": "integer",
"type": "float",
"valueMin": 0,
"valueMax": 6553.6,
"name": "default_light_transition",
"optional": True,
"default": 0,
@ -74,8 +75,9 @@ CONFIG_WITH_ALARM_OPTIONS = {
"schemas": {
"zha_options": [
{
"type": "integer",
"type": "float",
"valueMin": 0,
"valueMax": 6553.6,
"name": "default_light_transition",
"optional": True,
"default": 0,

View File

@ -569,7 +569,7 @@ async def test_transitions(
"turn_on",
{
"entity_id": device_1_entity_id,
"transition": 3,
"transition": 3.5,
"brightness": 18,
"color_temp": 432,
},
@ -586,7 +586,7 @@ async def test_transitions(
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,
level=18,
transition_time=30,
transition_time=35,
expect_reply=True,
manufacturer=None,
tries=1,
@ -597,7 +597,7 @@ async def test_transitions(
dev1_cluster_color.commands_by_name["move_to_color_temp"].id,
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
color_temp_mireds=432,
transition_time=30.0,
transition_time=35,
expect_reply=True,
manufacturer=None,
tries=1,