Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve syncing light states to deCONZ groups #117588

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions homeassistant/components/deconz/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

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 import ResourceType
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 (
Expand Down Expand Up @@ -105,6 +105,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 = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this mean that last brightness, last CT etc wins ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is true, but that hasn't changed from before (except it was part of the library) behaviour hasn't changed, the real change here is group.raw["action"] = cast(TypedGroupAction, data) where all data from all lights have been considered and then overriding any existing data in the group.

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,
Expand Down Expand Up @@ -148,11 +165,12 @@ def async_add_group(_: EventType, group_id: str) -> None:
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)])

Expand Down Expand Up @@ -326,7 +344,7 @@ def async_update_callback(self) -> None:
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]):
Expand Down
2 changes: 1 addition & 1 deletion tests/components/deconz/test_light.py
Original file line number Diff line number Diff line change
Expand Up @@ -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