KNX: Support for XY-color lights (#51306)

* support for xy-color

* replace invalid name
This commit is contained in:
Matthias Alphart 2021-06-01 08:59:51 +02:00 committed by GitHub
parent 164e45f0a7
commit 549b0b0727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 18 deletions

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from typing import Any, Tuple, cast from typing import Any, Tuple, cast
from xknx import XKNX 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 xknx.telegram.address import parse_device_group_address
from homeassistant.components.light import ( from homeassistant.components.light import (
@ -12,11 +12,13 @@ from homeassistant.components.light import (
ATTR_COLOR_TEMP, ATTR_COLOR_TEMP,
ATTR_RGB_COLOR, ATTR_RGB_COLOR,
ATTR_RGBW_COLOR, ATTR_RGBW_COLOR,
ATTR_XY_COLOR,
COLOR_MODE_BRIGHTNESS, COLOR_MODE_BRIGHTNESS,
COLOR_MODE_COLOR_TEMP, COLOR_MODE_COLOR_TEMP,
COLOR_MODE_ONOFF, COLOR_MODE_ONOFF,
COLOR_MODE_RGB, COLOR_MODE_RGB,
COLOR_MODE_RGBW, COLOR_MODE_RGBW,
COLOR_MODE_XY,
LightEntity, LightEntity,
) )
from homeassistant.const import CONF_NAME 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_color_state=config.get(LightSchema.CONF_COLOR_STATE_ADDRESS),
group_address_rgbw=config.get(LightSchema.CONF_RGBW_ADDRESS), group_address_rgbw=config.get(LightSchema.CONF_RGBW_ADDRESS),
group_address_rgbw_state=config.get(LightSchema.CONF_RGBW_STATE_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=group_address_tunable_white,
group_address_tunable_white_state=group_address_tunable_white_state, group_address_tunable_white_state=group_address_tunable_white_state,
group_address_color_temperature=group_address_color_temp, 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.""" """Return the brightness of this light between 0..255."""
if self._device.supports_brightness: if self._device.supports_brightness:
return self._device.current_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: if (rgb := self.rgb_color) is not None:
return max(rgb) return max(rgb)
return None return None
@ -277,6 +284,14 @@ class KNXLight(KnxEntity, LightEntity):
return (*rgb, white) return (*rgb, white)
return None 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 @property
def color_temp(self) -> int | None: def color_temp(self) -> int | None:
"""Return the color temperature in mireds.""" """Return the color temperature in mireds."""
@ -309,6 +324,8 @@ class KNXLight(KnxEntity, LightEntity):
@property @property
def color_mode(self) -> str | None: def color_mode(self) -> str | None:
"""Return the color mode of the light.""" """Return the color mode of the light."""
if self._device.supports_xyy_color:
return COLOR_MODE_XY
if self._device.supports_rgbw: if self._device.supports_rgbw:
return COLOR_MODE_RGBW return COLOR_MODE_RGBW
if self._device.supports_color: if self._device.supports_color:
@ -329,22 +346,11 @@ class KNXLight(KnxEntity, LightEntity):
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on.""" """Turn the light on."""
# ignore arguments if not supported to fall back to set_on() brightness = kwargs.get(ATTR_BRIGHTNESS)
brightness = ( mireds = kwargs.get(ATTR_COLOR_TEMP)
kwargs.get(ATTR_BRIGHTNESS) rgb = kwargs.get(ATTR_RGB_COLOR)
if self._device.supports_brightness rgbw = kwargs.get(ATTR_RGBW_COLOR)
or self.color_mode in (COLOR_MODE_RGB, COLOR_MODE_RGBW) xy_color = kwargs.get(ATTR_XY_COLOR)
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
)
if ( if (
not self.is_on not self.is_on
@ -352,6 +358,7 @@ class KNXLight(KnxEntity, LightEntity):
and mireds is None and mireds is None
and rgb is None and rgb is None
and rgbw is None and rgbw is None
and xy_color is None
): ):
await self._device.set_on() await self._device.set_on()
return return
@ -394,12 +401,22 @@ class KNXLight(KnxEntity, LightEntity):
) )
await self._device.set_tunable_white(relative_ct) 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: if brightness is not None:
# brightness: 1..255; 0 brightness will call async_turn_off() # brightness: 1..255; 0 brightness will call async_turn_off()
if self._device.brightness.writable: if self._device.brightness.writable:
await self._device.set_brightness(brightness) await self._device.set_brightness(brightness)
return 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: if self.color_mode == COLOR_MODE_RGBW:
rgbw = self.rgbw_color rgbw = self.rgbw_color
if not rgbw or not any(rgbw): if not rgbw or not any(rgbw):

View File

@ -421,6 +421,8 @@ class LightSchema(KNXPlatformSchema):
CONF_COLOR_TEMP_MODE = "color_temperature_mode" CONF_COLOR_TEMP_MODE = "color_temperature_mode"
CONF_RGBW_ADDRESS = "rgbw_address" CONF_RGBW_ADDRESS = "rgbw_address"
CONF_RGBW_STATE_ADDRESS = "rgbw_state_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_MIN_KELVIN = "min_kelvin"
CONF_MAX_KELVIN = "max_kelvin" CONF_MAX_KELVIN = "max_kelvin"
@ -479,6 +481,8 @@ class LightSchema(KNXPlatformSchema):
): vol.All(vol.Upper, cv.enum(ColorTempModes)), ): vol.All(vol.Upper, cv.enum(ColorTempModes)),
vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_list_validator, vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_list_validator,
vol.Optional(CONF_RGBW_STATE_ADDRESS): 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.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All(
vol.Coerce(int), vol.Range(min=1) vol.Coerce(int), vol.Range(min=1)
), ),