1 """Platform allowing several lights to be grouped into one light."""
3 from __future__
import annotations
5 from collections
import Counter
8 from typing
import Any, cast
10 import voluptuous
as vol
16 ATTR_COLOR_TEMP_KELVIN,
21 ATTR_MAX_COLOR_TEMP_KELVIN,
22 ATTR_MIN_COLOR_TEMP_KELVIN,
26 ATTR_SUPPORTED_COLOR_MODES,
30 PLATFORM_SCHEMA
as LIGHT_PLATFORM_SCHEMA,
34 filter_supported_color_modes,
39 ATTR_SUPPORTED_FEATURES,
54 from .entity
import GroupEntity
55 from .util
import find_state_attributes, mean_tuple, reduce_attribute
57 DEFAULT_NAME =
"Light Group"
63 PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
65 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
66 vol.Optional(CONF_UNIQUE_ID): cv.string,
67 vol.Required(CONF_ENTITIES): cv.entities_domain(light.DOMAIN),
68 vol.Optional(CONF_ALL): cv.boolean,
72 SUPPORT_GROUP_LIGHT = (
73 LightEntityFeature.EFFECT | LightEntityFeature.FLASH | LightEntityFeature.TRANSITION
76 _LOGGER = logging.getLogger(__name__)
82 async_add_entities: AddEntitiesCallback,
83 discovery_info: DiscoveryInfoType |
None =
None,
85 """Initialize light.group platform."""
89 config.get(CONF_UNIQUE_ID),
91 config[CONF_ENTITIES],
100 config_entry: ConfigEntry,
101 async_add_entities: AddEntitiesCallback,
103 """Initialize Light Group config entry."""
104 registry = er.async_get(hass)
105 entities = er.async_validate_entity_ids(
106 registry, config_entry.options[CONF_ENTITIES]
108 mode = config_entry.options.get(CONF_ALL,
False)
111 [
LightGroup(config_entry.entry_id, config_entry.title, entities, mode)]
117 hass: HomeAssistant, name: str, validated_config: dict[str, Any]
119 """Create a preview sensor."""
123 validated_config[CONF_ENTITIES],
124 validated_config.get(CONF_ALL,
False),
128 FORWARDED_ATTRIBUTES = frozenset(
131 ATTR_COLOR_TEMP_KELVIN,
146 """Representation of a light group."""
148 _attr_available =
False
149 _attr_icon =
"mdi:lightbulb-group"
150 _attr_max_color_temp_kelvin = 6500
151 _attr_min_color_temp_kelvin = 2000
152 _attr_should_poll =
False
155 self, unique_id: str |
None, name: str, entity_ids: list[str], mode: bool |
None
157 """Initialize a light group."""
171 """Forward the turn_on command to all lights in the light group."""
173 key: value
for key, value
in kwargs.items()
if key
in FORWARDED_ATTRIBUTES
177 _LOGGER.debug(
"Forwarded turn_on command: %s", data)
179 await self.
hasshass.services.async_call(
188 """Forward the turn_off command to all lights in the light group."""
189 data = {ATTR_ENTITY_ID: self.
_entity_ids_entity_ids}
191 if ATTR_TRANSITION
in kwargs:
192 data[ATTR_TRANSITION] = kwargs[ATTR_TRANSITION]
194 await self.
hasshass.services.async_call(
204 """Query all members and determine the light group state."""
208 if (state := self.
hasshass.states.get(entity_id))
is not None
210 on_states = [state
for state
in states
if state.state == STATE_ON]
212 valid_state = self.
modemode(
213 state.state
not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
for state
in states
221 self.
_attr_is_on_attr_is_on = self.
modemode(state.state == STATE_ON
for state
in states)
227 on_states, ATTR_HS_COLOR, reduce=mean_tuple
230 on_states, ATTR_RGB_COLOR, reduce=mean_tuple
233 on_states, ATTR_RGBW_COLOR, reduce=mean_tuple
236 on_states, ATTR_RGBWW_COLOR, reduce=mean_tuple
239 on_states, ATTR_XY_COLOR, reduce=mean_tuple
243 on_states, ATTR_COLOR_TEMP_KELVIN
246 states, ATTR_MIN_COLOR_TEMP_KELVIN, default=2000, reduce=min
249 states, ATTR_MAX_COLOR_TEMP_KELVIN, default=6500, reduce=max
266 effects_count = Counter(itertools.chain(all_effects))
267 self.
_attr_effect_attr_effect = effects_count.most_common(1)[0][0]
269 supported_color_modes = {ColorMode.ONOFF}
270 all_supported_color_modes =
list(
273 if all_supported_color_modes:
276 cast(set[ColorMode], set().union(*all_supported_color_modes))
284 color_mode_count = Counter(itertools.chain(all_color_modes))
285 if ColorMode.ONOFF
in color_mode_count:
286 if ColorMode.ONOFF
in supported_color_modes:
287 color_mode_count[ColorMode.ONOFF] = -1
289 color_mode_count.pop(ColorMode.ONOFF)
290 if ColorMode.BRIGHTNESS
in color_mode_count:
291 if ColorMode.BRIGHTNESS
in supported_color_modes:
292 color_mode_count[ColorMode.BRIGHTNESS] = 0
294 color_mode_count.pop(ColorMode.BRIGHTNESS)
296 self.
_attr_color_mode_attr_color_mode = color_mode_count.most_common(1)[0][0]
int _attr_max_color_temp_kelvin
None __init__(self, str|None unique_id, str name, list[str] entity_ids, bool|None mode)
None async_update_group_state(self)
_attr_min_color_temp_kelvin
_attr_supported_color_modes
None async_turn_off(self, **Any kwargs)
_attr_max_color_temp_kelvin
int _attr_min_color_temp_kelvin
_attr_extra_state_attributes
None async_turn_on(self, **Any kwargs)
bool remove(self, _T matcher)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
LightGroup async_create_preview_light(HomeAssistant hass, str name, dict[str, Any] validated_config)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Iterator[Any] find_state_attributes(list[State] states, str key)
Any reduce_attribute(list[State] states, str key, Any|None default=None, Callable[..., Any] reduce=mean_int)
set[ColorMode] filter_supported_color_modes(Iterable[ColorMode] color_modes)