1 """Support for Hue groups (room/zone)."""
3 from __future__
import annotations
8 from aiohue.v2
import HueBridgeV2
9 from aiohue.v2.controllers.events
import EventType
10 from aiohue.v2.controllers.groups
import GroupedLight, Room, Zone
11 from aiohue.v2.models.feature
import DynamicStatus
22 LightEntityDescription,
31 from ..bridge
import HueBridge
32 from ..const
import DOMAIN
33 from .entity
import HueBaseEntity
34 from .helpers
import (
35 normalize_hue_brightness,
36 normalize_hue_colortemp,
37 normalize_hue_transition,
43 config_entry: ConfigEntry,
44 async_add_entities: AddEntitiesCallback,
46 """Set up Hue groups on light platform."""
47 bridge: HueBridge = hass.data[DOMAIN][config_entry.entry_id]
48 api: HueBridgeV2 = bridge.api
50 async
def async_add_light(event_type: EventType, resource: GroupedLight) ->
None:
51 """Add Grouped Light for Hue Room/Zone."""
57 and (group := api.groups.grouped_light.get_zone(resource.id))
is None
60 await asyncio.sleep(0.5)
68 for item
in api.groups.grouped_light.items:
69 await async_add_light(EventType.RESOURCE_ADDED, item)
72 config_entry.async_on_unload(
73 api.groups.grouped_light.subscribe(
74 async_add_light, event_filter=EventType.RESOURCE_ADDED
81 """Representation of a Grouped Hue light."""
84 key=
"hue_grouped_light",
85 icon=
"mdi:lightbulb-group",
91 self, bridge: HueBridge, resource: GroupedLight, group: Room | Zone
93 """Initialize the light."""
94 controller = bridge.api.groups.grouped_light
95 super().
__init__(bridge, controller, resource)
99 self.api: HueBridgeV2 = bridge.api
100 self._attr_supported_features |= LightEntityFeature.FLASH
101 self._attr_supported_features |= LightEntityFeature.TRANSITION
107 identifiers={(DOMAIN, self.
groupgroup.id)},
113 """Call when entity is added."""
127 self.api.lights.subscribe(self.
_handle_event_handle_event, light_ids)
132 """Return true if light is on."""
137 """Return the optional state attributes."""
139 x.metadata.name
for x
in self.api.scenes
if x.group.rid == self.
groupgroup.id
141 light_resource_ids =
tuple(
148 "is_hue_group":
True,
149 "hue_scenes": scenes,
150 "hue_type": self.
groupgroup.type.value,
151 "lights": light_names,
152 "entity_id": light_entities,
157 """Turn the grouped_light on."""
159 xy_color = kwargs.get(ATTR_XY_COLOR)
162 flash = kwargs.get(ATTR_FLASH)
176 if flash
is not None:
180 await self.
bridgebridge.async_request_call(
184 brightness=brightness,
186 color_temp=color_temp,
187 transition_time=transition,
191 """Turn the light off."""
193 if transition
is not None:
195 flash = kwargs.get(ATTR_FLASH)
197 if flash
is not None:
202 await self.
bridgebridge.async_request_call(
206 transition_time=transition,
210 """Send flash command to light."""
211 await self.
bridgebridge.async_request_call(
214 short=flash == FLASH_SHORT,
219 """Call on update event."""
224 """Set base values from underlying lights of a group."""
225 supported_color_modes: set[ColorMode | str] = set()
226 lights_with_color_support = 0
227 lights_with_color_temp_support = 0
228 lights_with_dimming_support = 0
231 lights_in_colortemp_mode = 0
232 lights_in_dynamic_mode = 0
234 for light
in all_lights:
235 if color_temp := light.color_temperature:
236 lights_with_color_temp_support += 1
241 if color_temp.mirek
is not None and color_temp.mirek_valid:
242 lights_in_colortemp_mode += 1
243 if color := light.color:
244 lights_with_color_support += 1
247 if dimming := light.dimming:
248 lights_with_dimming_support += 1
249 total_brightness += dimming.brightness
252 and light.dynamics.status == DynamicStatus.DYNAMIC_PALETTE
254 lights_in_dynamic_mode += 1
261 if lights_with_color_support > 0:
262 supported_color_modes.add(ColorMode.XY)
263 if lights_with_color_temp_support > 0:
264 supported_color_modes.add(ColorMode.COLOR_TEMP)
265 if lights_with_dimming_support > 0:
266 if len(supported_color_modes) == 0:
268 supported_color_modes.add(ColorMode.BRIGHTNESS)
271 ((total_brightness / lights_with_dimming_support) / 100) * 255
274 supported_color_modes.add(ColorMode.ONOFF)
278 if lights_with_color_temp_support > 0
and lights_in_colortemp_mode > 0:
280 elif lights_with_color_support > 0:
282 elif lights_with_dimming_support > 0:
289 self, resource_ids: tuple[str]
290 ) -> tuple[set[str], set[str]]:
291 """Return the names and entity ids for the given Hue (light) resource IDs."""
292 ent_reg = er.async_get(self.
hasshass)
293 light_names: set[str] = set()
294 light_entities: set[str] = set()
295 for resource_id
in resource_ids:
297 if entity_id := ent_reg.async_get_entity_id(
298 self.
platformplatform.domain, DOMAIN, resource_id
300 light_entities.add(entity_id)
301 return light_names, light_entities
None _handle_event(self, EventType event_type, HueResource resource)
None async_turn_on(self, **Any kwargs)
None _update_values(self)
None async_turn_off(self, **Any kwargs)
None __init__(self, HueBridge bridge, GroupedLight resource, Room|Zone group)
None async_added_to_hass(self)
dict[str, Any]|None extra_state_attributes(self)
_attr_supported_color_modes
tuple[set[str], set[str]] _get_names_and_entity_ids_for_resource_ids(self, tuple[str] resource_ids)
None async_set_flash(self, str flash)
None async_on_remove(self, CALLBACK_TYPE func)
DeviceEntry get_device(HomeAssistant hass, str unique_id)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
float|None normalize_hue_brightness(float|None brightness)
float|None normalize_hue_transition(float|None transition)
int|None normalize_hue_colortemp(int|None colortemp)