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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

KNX: Support for XY-color lights #51306

Merged
merged 2 commits into from Jun 1, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 35 additions & 18 deletions homeassistant/components/knx/light.py
Expand Up @@ -4,19 +4,21 @@
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 (
ATTR_BRIGHTNESS,
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
Expand Down Expand Up @@ -159,6 +161,8 @@ def individual_color_addresses(color: str, feature: str) -> Any | None:
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,
Expand Down Expand Up @@ -253,6 +257,9 @@ def brightness(self) -> int | None:
"""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
Expand All @@ -277,6 +284,14 @@ def rgbw_color(self) -> tuple[int, int, int, int] | None:
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."""
Expand Down Expand Up @@ -309,6 +324,8 @@ def max_mireds(self) -> int:
@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:
Expand All @@ -329,29 +346,19 @@ def supported_color_modes(self) -> set | None:

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
)
Comment on lines -332 to -347
Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed the checks for supported modes because of #51084

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
and brightness is None
and mireds is None
and rgb is None
and rgbw is None
and xy_color is None
):
await self._device.set_on()
return
Expand Down Expand Up @@ -394,12 +401,22 @@ async def set_color(
)
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):
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/knx/schema.py
Expand Up @@ -367,6 +367,8 @@ class LightSchema:
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"

Expand Down Expand Up @@ -425,6 +427,8 @@ class LightSchema:
): 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)
),
Expand Down