diff --git a/homeassistant/components/knx/light.py b/homeassistant/components/knx/light.py index ed4abac63b5..d8697a26d7f 100644 --- a/homeassistant/components/knx/light.py +++ b/homeassistant/components/knx/light.py @@ -4,7 +4,7 @@ from __future__ import annotations from typing import Any, Tuple, cast from xknx import XKNX -from xknx.devices import Light as XknxLight +from xknx.devices.light import Light as XknxLight, XYYColor from xknx.telegram.address import parse_device_group_address from homeassistant.components.light import ( @@ -12,11 +12,13 @@ from homeassistant.components.light import ( ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_RGBW_COLOR, + ATTR_XY_COLOR, COLOR_MODE_BRIGHTNESS, COLOR_MODE_COLOR_TEMP, COLOR_MODE_ONOFF, COLOR_MODE_RGB, COLOR_MODE_RGBW, + COLOR_MODE_XY, LightEntity, ) from homeassistant.const import CONF_NAME @@ -159,6 +161,8 @@ def _create_light(xknx: XKNX, config: ConfigType) -> XknxLight: group_address_color_state=config.get(LightSchema.CONF_COLOR_STATE_ADDRESS), group_address_rgbw=config.get(LightSchema.CONF_RGBW_ADDRESS), group_address_rgbw_state=config.get(LightSchema.CONF_RGBW_STATE_ADDRESS), + group_address_xyy_color=config.get(LightSchema.CONF_XYY_ADDRESS), + group_address_xyy_color_state=config.get(LightSchema.CONF_XYY_STATE_ADDRESS), group_address_tunable_white=group_address_tunable_white, group_address_tunable_white_state=group_address_tunable_white_state, group_address_color_temperature=group_address_color_temp, @@ -253,6 +257,9 @@ class KNXLight(KnxEntity, LightEntity): """Return the brightness of this light between 0..255.""" if self._device.supports_brightness: return self._device.current_brightness + if self._device.current_xyy_color is not None: + _, brightness = self._device.current_xyy_color + return brightness if (rgb := self.rgb_color) is not None: return max(rgb) return None @@ -277,6 +284,14 @@ class KNXLight(KnxEntity, LightEntity): return (*rgb, white) return None + @property + def xy_color(self) -> tuple[float, float] | None: + """Return the xy color value [float, float].""" + if self._device.current_xyy_color is not None: + xy_color, _ = self._device.current_xyy_color + return xy_color + return None + @property def color_temp(self) -> int | None: """Return the color temperature in mireds.""" @@ -309,6 +324,8 @@ class KNXLight(KnxEntity, LightEntity): @property def color_mode(self) -> str | None: """Return the color mode of the light.""" + if self._device.supports_xyy_color: + return COLOR_MODE_XY if self._device.supports_rgbw: return COLOR_MODE_RGBW if self._device.supports_color: @@ -329,22 +346,11 @@ class KNXLight(KnxEntity, LightEntity): async def async_turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" - # ignore arguments if not supported to fall back to set_on() - brightness = ( - kwargs.get(ATTR_BRIGHTNESS) - if self._device.supports_brightness - or self.color_mode in (COLOR_MODE_RGB, COLOR_MODE_RGBW) - else None - ) - mireds = ( - kwargs.get(ATTR_COLOR_TEMP) - if self.color_mode == COLOR_MODE_COLOR_TEMP - else None - ) - rgb = kwargs.get(ATTR_RGB_COLOR) if self.color_mode == COLOR_MODE_RGB else None - rgbw = ( - kwargs.get(ATTR_RGBW_COLOR) if self.color_mode == COLOR_MODE_RGBW else None - ) + brightness = kwargs.get(ATTR_BRIGHTNESS) + mireds = kwargs.get(ATTR_COLOR_TEMP) + rgb = kwargs.get(ATTR_RGB_COLOR) + rgbw = kwargs.get(ATTR_RGBW_COLOR) + xy_color = kwargs.get(ATTR_XY_COLOR) if ( not self.is_on @@ -352,6 +358,7 @@ class KNXLight(KnxEntity, LightEntity): and mireds is None and rgb is None and rgbw is None + and xy_color is None ): await self._device.set_on() return @@ -394,12 +401,22 @@ class KNXLight(KnxEntity, LightEntity): ) await self._device.set_tunable_white(relative_ct) + if xy_color is not None: + await self._device.set_xyy_color( + XYYColor(color=xy_color, brightness=brightness) + ) + return + if brightness is not None: # brightness: 1..255; 0 brightness will call async_turn_off() if self._device.brightness.writable: await self._device.set_brightness(brightness) return - # brightness without color in kwargs; set via color - default to white + # brightness without color in kwargs; set via color + if self.color_mode == COLOR_MODE_XY: + await self._device.set_xyy_color(XYYColor(brightness=brightness)) + return + # default to white if color not known for RGB(W) if self.color_mode == COLOR_MODE_RGBW: rgbw = self.rgbw_color if not rgbw or not any(rgbw): diff --git a/homeassistant/components/knx/schema.py b/homeassistant/components/knx/schema.py index fa94f503d7e..0715b68d575 100644 --- a/homeassistant/components/knx/schema.py +++ b/homeassistant/components/knx/schema.py @@ -421,6 +421,8 @@ class LightSchema(KNXPlatformSchema): CONF_COLOR_TEMP_MODE = "color_temperature_mode" CONF_RGBW_ADDRESS = "rgbw_address" CONF_RGBW_STATE_ADDRESS = "rgbw_state_address" + CONF_XYY_ADDRESS = "xyy_address" + CONF_XYY_STATE_ADDRESS = "xyy_state_address" CONF_MIN_KELVIN = "min_kelvin" CONF_MAX_KELVIN = "max_kelvin" @@ -479,6 +481,8 @@ class LightSchema(KNXPlatformSchema): ): vol.All(vol.Upper, cv.enum(ColorTempModes)), vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_RGBW_STATE_ADDRESS): ga_list_validator, + vol.Exclusive(CONF_XYY_ADDRESS, "color"): ga_list_validator, + vol.Optional(CONF_XYY_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All( vol.Coerce(int), vol.Range(min=1) ),