KNX: Support for HS-color lights (#53538)
parent
ce663f629c
commit
27d42e0cd8
|
@ -10,11 +10,13 @@ from xknx.telegram.address import parse_device_group_address
|
|||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_HS_COLOR,
|
||||
ATTR_RGB_COLOR,
|
||||
ATTR_RGBW_COLOR,
|
||||
ATTR_XY_COLOR,
|
||||
COLOR_MODE_BRIGHTNESS,
|
||||
COLOR_MODE_COLOR_TEMP,
|
||||
COLOR_MODE_HS,
|
||||
COLOR_MODE_ONOFF,
|
||||
COLOR_MODE_RGB,
|
||||
COLOR_MODE_RGBW,
|
||||
|
@ -158,6 +160,12 @@ 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_hue=config.get(LightSchema.CONF_HUE_ADDRESS),
|
||||
group_address_hue_state=config.get(LightSchema.CONF_HUE_STATE_ADDRESS),
|
||||
group_address_saturation=config.get(LightSchema.CONF_SATURATION_ADDRESS),
|
||||
group_address_saturation_state=config.get(
|
||||
LightSchema.CONF_SATURATION_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,
|
||||
|
@ -283,6 +291,13 @@ class KNXLight(KnxEntity, LightEntity):
|
|||
return (*rgb, white)
|
||||
return None
|
||||
|
||||
@property
|
||||
def hs_color(self) -> tuple[float, float] | None:
|
||||
"""Return the hue and saturation color value [float, float]."""
|
||||
# Hue is scaled 0..360 int encoded in 1 byte in KNX (-> only 256 possible values)
|
||||
# Saturation is scaled 0..100 int
|
||||
return self._device.current_hs_color
|
||||
|
||||
@property
|
||||
def xy_color(self) -> tuple[float, float] | None:
|
||||
"""Return the xy color value [float, float]."""
|
||||
|
@ -315,6 +330,8 @@ class KNXLight(KnxEntity, LightEntity):
|
|||
"""Return the color mode of the light."""
|
||||
if self._device.supports_xyy_color:
|
||||
return COLOR_MODE_XY
|
||||
if self._device.supports_hs_color:
|
||||
return COLOR_MODE_HS
|
||||
if self._device.supports_rgbw:
|
||||
return COLOR_MODE_RGBW
|
||||
if self._device.supports_color:
|
||||
|
@ -339,6 +356,7 @@ class KNXLight(KnxEntity, LightEntity):
|
|||
mireds = kwargs.get(ATTR_COLOR_TEMP)
|
||||
rgb = kwargs.get(ATTR_RGB_COLOR)
|
||||
rgbw = kwargs.get(ATTR_RGBW_COLOR)
|
||||
hs_color = kwargs.get(ATTR_HS_COLOR)
|
||||
xy_color = kwargs.get(ATTR_XY_COLOR)
|
||||
|
||||
if (
|
||||
|
@ -347,6 +365,7 @@ class KNXLight(KnxEntity, LightEntity):
|
|||
and mireds is None
|
||||
and rgb is None
|
||||
and rgbw is None
|
||||
and hs_color is None
|
||||
and xy_color is None
|
||||
):
|
||||
await self._device.set_on()
|
||||
|
@ -396,6 +415,12 @@ class KNXLight(KnxEntity, LightEntity):
|
|||
)
|
||||
return
|
||||
|
||||
if hs_color is not None:
|
||||
# round so only one telegram will be sent if the other matches state
|
||||
hue = round(hs_color[0])
|
||||
sat = round(hs_color[1])
|
||||
await self._device.set_hs_color((hue, sat))
|
||||
|
||||
if brightness is not None:
|
||||
# brightness: 1..255; 0 brightness will call async_turn_off()
|
||||
if self._device.brightness.writable:
|
||||
|
|
|
@ -496,8 +496,12 @@ class LightSchema(KNXPlatformSchema):
|
|||
CONF_COLOR_TEMP_ADDRESS = "color_temperature_address"
|
||||
CONF_COLOR_TEMP_STATE_ADDRESS = "color_temperature_state_address"
|
||||
CONF_COLOR_TEMP_MODE = "color_temperature_mode"
|
||||
CONF_HUE_ADDRESS = "hue_address"
|
||||
CONF_HUE_STATE_ADDRESS = "hue_state_address"
|
||||
CONF_RGBW_ADDRESS = "rgbw_address"
|
||||
CONF_RGBW_STATE_ADDRESS = "rgbw_state_address"
|
||||
CONF_SATURATION_ADDRESS = "saturation_address"
|
||||
CONF_SATURATION_STATE_ADDRESS = "saturation_state_address"
|
||||
CONF_XYY_ADDRESS = "xyy_address"
|
||||
CONF_XYY_STATE_ADDRESS = "xyy_state_address"
|
||||
CONF_MIN_KELVIN = "min_kelvin"
|
||||
|
@ -514,7 +518,18 @@ class LightSchema(KNXPlatformSchema):
|
|||
CONF_BLUE = "blue"
|
||||
CONF_WHITE = "white"
|
||||
|
||||
COLOR_SCHEMA = vol.Schema(
|
||||
_hs_color_inclusion_msg = (
|
||||
"'hue_address', 'saturation_address' and 'brightness_address'"
|
||||
" are required for hs_color configuration"
|
||||
)
|
||||
HS_COLOR_SCHEMA = {
|
||||
vol.Optional(CONF_HUE_ADDRESS): ga_list_validator,
|
||||
vol.Optional(CONF_HUE_STATE_ADDRESS): ga_list_validator,
|
||||
vol.Optional(CONF_SATURATION_ADDRESS): ga_list_validator,
|
||||
vol.Optional(CONF_SATURATION_STATE_ADDRESS): ga_list_validator,
|
||||
}
|
||||
|
||||
INDIVIDUAL_COLOR_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(KNX_ADDRESS): ga_list_validator,
|
||||
vol.Optional(CONF_STATE_ADDRESS): ga_list_validator,
|
||||
|
@ -536,18 +551,18 @@ class LightSchema(KNXPlatformSchema):
|
|||
CONF_RED,
|
||||
"individual_colors",
|
||||
msg="'red', 'green' and 'blue' are required for individual colors configuration",
|
||||
): COLOR_SCHEMA,
|
||||
): INDIVIDUAL_COLOR_SCHEMA,
|
||||
vol.Inclusive(
|
||||
CONF_GREEN,
|
||||
"individual_colors",
|
||||
msg="'red', 'green' and 'blue' are required for individual colors configuration",
|
||||
): COLOR_SCHEMA,
|
||||
): INDIVIDUAL_COLOR_SCHEMA,
|
||||
vol.Inclusive(
|
||||
CONF_BLUE,
|
||||
"individual_colors",
|
||||
msg="'red', 'green' and 'blue' are required for individual colors configuration",
|
||||
): COLOR_SCHEMA,
|
||||
vol.Optional(CONF_WHITE): COLOR_SCHEMA,
|
||||
): INDIVIDUAL_COLOR_SCHEMA,
|
||||
vol.Optional(CONF_WHITE): INDIVIDUAL_COLOR_SCHEMA,
|
||||
},
|
||||
vol.Exclusive(CONF_COLOR_ADDRESS, "color"): ga_list_validator,
|
||||
vol.Optional(CONF_COLOR_STATE_ADDRESS): ga_list_validator,
|
||||
|
@ -556,6 +571,7 @@ class LightSchema(KNXPlatformSchema):
|
|||
vol.Optional(
|
||||
CONF_COLOR_TEMP_MODE, default=DEFAULT_COLOR_TEMP_MODE
|
||||
): vol.All(vol.Upper, cv.enum(ColorTempModes)),
|
||||
**HS_COLOR_SCHEMA,
|
||||
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,
|
||||
|
@ -569,20 +585,39 @@ class LightSchema(KNXPlatformSchema):
|
|||
}
|
||||
),
|
||||
vol.Any(
|
||||
# either global "address" or "individual_colors" is required
|
||||
vol.Schema(
|
||||
{vol.Required(KNX_ADDRESS): object},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
),
|
||||
vol.Schema( # brightness addresses are required in INDIVIDUAL_COLOR_SCHEMA
|
||||
{vol.Required(CONF_INDIVIDUAL_COLORS): object},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
),
|
||||
msg="either 'address' or 'individual_colors' is required",
|
||||
),
|
||||
vol.Any(
|
||||
vol.Schema( # 'brightness' is non-optional for hs-color
|
||||
{
|
||||
# brightness addresses are required in COLOR_SCHEMA
|
||||
vol.Required(CONF_INDIVIDUAL_COLORS): object,
|
||||
vol.Inclusive(
|
||||
CONF_BRIGHTNESS_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg
|
||||
): object,
|
||||
vol.Inclusive(
|
||||
CONF_HUE_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg
|
||||
): object,
|
||||
vol.Inclusive(
|
||||
CONF_SATURATION_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg
|
||||
): object,
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
),
|
||||
vol.Schema(
|
||||
vol.Schema( # hs-colors not used
|
||||
{
|
||||
vol.Required(KNX_ADDRESS): object,
|
||||
vol.Optional(CONF_HUE_ADDRESS): None,
|
||||
vol.Optional(CONF_SATURATION_ADDRESS): None,
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
),
|
||||
msg=_hs_color_inclusion_msg,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue