From bbfc2456ec07b56c49320b6fd104e999eb25bd6a Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 17 May 2024 08:44:09 +0200 Subject: [PATCH] Improve syncing light states to deCONZ groups (#117588) --- homeassistant/components/deconz/light.py | 34 ++++++++++++++++++------ tests/components/deconz/test_light.py | 2 +- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/deconz/light.py b/homeassistant/components/deconz/light.py index dc6cee39785..9e932b46fec 100644 --- a/homeassistant/components/deconz/light.py +++ b/homeassistant/components/deconz/light.py @@ -2,12 +2,12 @@ from __future__ import annotations -from typing import Any, TypedDict, TypeVar +from typing import Any, TypedDict, TypeVar, cast from pydeconz.interfaces.groups import GroupHandler from pydeconz.interfaces.lights import LightHandler from pydeconz.models.event import EventType -from pydeconz.models.group import Group +from pydeconz.models.group import Group, TypedGroupAction from pydeconz.models.light.light import Light, LightAlert, LightColorMode, LightEffect from homeassistant.components.light import ( @@ -103,6 +103,23 @@ class SetStateAttributes(TypedDict, total=False): xy: tuple[float, float] +def update_color_state( + group: Group, lights: list[Light], override: bool = False +) -> None: + """Sync group color state with light.""" + data = { + attribute: light_attribute + for light in lights + for attribute in ("bri", "ct", "hue", "sat", "xy", "colormode", "effect") + if (light_attribute := light.raw["state"].get(attribute)) is not None + } + + if override: + group.raw["action"] = cast(TypedGroupAction, data) + else: + group.update(cast(dict[str, dict[str, Any]], {"action": data})) + + async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, @@ -135,11 +152,12 @@ async def async_setup_entry( if (group := hub.api.groups[group_id]) and not group.lights: return - first = True - for light_id in group.lights: - if (light := hub.api.lights.lights.get(light_id)) and light.reachable: - group.update_color_state(light, update_all_attributes=first) - first = False + lights = [ + light + for light_id in group.lights + if (light := hub.api.lights.lights.get(light_id)) and light.reachable + ] + update_color_state(group, lights, True) async_add_entities([DeconzGroup(group, hub)]) @@ -313,7 +331,7 @@ class DeconzLight(DeconzBaseLight[Light]): if self._device.reachable and "attr" not in self._device.changed_keys: for group in self.hub.api.groups.values(): if self._device.resource_id in group.lights: - group.update_color_state(self._device) + update_color_state(group, [self._device]) class DeconzGroup(DeconzBaseLight[Group]): diff --git a/tests/components/deconz/test_light.py b/tests/components/deconz/test_light.py index 5144f222484..d964361df57 100644 --- a/tests/components/deconz/test_light.py +++ b/tests/components/deconz/test_light.py @@ -1522,4 +1522,4 @@ async def test_verify_group_color_mode_fallback( ) group_state = hass.states.get("light.opbergruimte") assert group_state.state == STATE_ON - assert group_state.attributes[ATTR_COLOR_MODE] is ColorMode.UNKNOWN + assert group_state.attributes[ATTR_COLOR_MODE] is ColorMode.BRIGHTNESS