Add color_mode support to yeelight light (#51973)

* Add color_mode support to yeelight light

* Satisfy pylint

* Address review comment

* Improve test coverage

* Improve test coverage
This commit is contained in:
Erik Montnemery 2021-06-25 17:37:15 +02:00 committed by GitHub
parent 3b0f67acd1
commit dad7a597ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 350 additions and 61 deletions

View File

@ -18,11 +18,14 @@ from homeassistant.components.light import (
ATTR_KELVIN, ATTR_KELVIN,
ATTR_RGB_COLOR, ATTR_RGB_COLOR,
ATTR_TRANSITION, ATTR_TRANSITION,
COLOR_MODE_BRIGHTNESS,
COLOR_MODE_COLOR_TEMP,
COLOR_MODE_HS,
COLOR_MODE_ONOFF,
COLOR_MODE_RGB,
COLOR_MODE_UNKNOWN,
FLASH_LONG, FLASH_LONG,
FLASH_SHORT, FLASH_SHORT,
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
SUPPORT_EFFECT, SUPPORT_EFFECT,
SUPPORT_FLASH, SUPPORT_FLASH,
SUPPORT_TRANSITION, SUPPORT_TRANSITION,
@ -62,13 +65,7 @@ from . import (
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_YEELIGHT = ( SUPPORT_YEELIGHT = SUPPORT_TRANSITION | SUPPORT_FLASH | SUPPORT_EFFECT
SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION | SUPPORT_FLASH | SUPPORT_EFFECT
)
SUPPORT_YEELIGHT_WHITE_TEMP = SUPPORT_YEELIGHT | SUPPORT_COLOR_TEMP
SUPPORT_YEELIGHT_RGB = SUPPORT_YEELIGHT_WHITE_TEMP | SUPPORT_COLOR
ATTR_MINUTES = "minutes" ATTR_MINUTES = "minutes"
@ -273,7 +270,7 @@ async def async_setup_entry(
elif device_type == BulbType.Color: elif device_type == BulbType.Color:
if nl_switch_light and device.is_nightlight_supported: if nl_switch_light and device.is_nightlight_supported:
_lights_setup_helper(YeelightColorLightWithNightlightSwitch) _lights_setup_helper(YeelightColorLightWithNightlightSwitch)
_lights_setup_helper(YeelightNightLightModeWithWithoutBrightnessControl) _lights_setup_helper(YeelightNightLightModeWithoutBrightnessControl)
else: else:
_lights_setup_helper(YeelightColorLightWithoutNightlightSwitch) _lights_setup_helper(YeelightColorLightWithoutNightlightSwitch)
elif device_type == BulbType.WhiteTemp: elif device_type == BulbType.WhiteTemp:
@ -398,6 +395,9 @@ def _async_setup_services(hass: HomeAssistant):
class YeelightGenericLight(YeelightEntity, LightEntity): class YeelightGenericLight(YeelightEntity, LightEntity):
"""Representation of a Yeelight generic light.""" """Representation of a Yeelight generic light."""
_attr_color_mode = COLOR_MODE_BRIGHTNESS
_attr_supported_color_modes = {COLOR_MODE_BRIGHTNESS}
def __init__(self, device, entry, custom_effects=None): def __init__(self, device, entry, custom_effects=None):
"""Initialize the Yeelight light.""" """Initialize the Yeelight light."""
super().__init__(device, entry) super().__init__(device, entry)
@ -406,6 +406,7 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
self._color_temp = None self._color_temp = None
self._hs = None self._hs = None
self._rgb = None
self._effect = None self._effect = None
model_specs = self._bulb.get_model_specs() model_specs = self._bulb.get_model_specs()
@ -503,6 +504,11 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
"""Return the color property.""" """Return the color property."""
return self._hs return self._hs
@property
def rgb_color(self) -> tuple:
"""Return the color property."""
return self._rgb
@property @property
def effect(self): def effect(self):
"""Return the current effect.""" """Return the current effect."""
@ -558,32 +564,30 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
def update(self): def update(self):
"""Update light properties.""" """Update light properties."""
self._hs = self._get_hs_from_properties() self._hs = self._get_hs_from_properties()
self._rgb = self._get_rgb_from_properties()
if not self.device.is_color_flow_enabled: if not self.device.is_color_flow_enabled:
self._effect = None self._effect = None
def _get_hs_from_properties(self): def _get_hs_from_properties(self):
rgb = self._get_property("rgb") hue = self._get_property("hue")
color_mode = self._get_property("color_mode") sat = self._get_property("sat")
if hue is None or sat is None:
if not rgb or not color_mode:
return None return None
color_mode = int(color_mode) return (int(hue), int(sat))
if color_mode == 2: # color temperature
temp_in_k = mired_to_kelvin(self.color_temp)
return color_util.color_temperature_to_hs(temp_in_k)
if color_mode == 3: # hsv
hue = int(self._get_property("hue"))
sat = int(self._get_property("sat"))
return (hue / 360 * 65536, sat / 100 * 255) def _get_rgb_from_properties(self):
rgb = self._get_property("rgb")
if rgb is None:
return None
rgb = int(rgb) rgb = int(rgb)
blue = rgb & 0xFF blue = rgb & 0xFF
green = (rgb >> 8) & 0xFF green = (rgb >> 8) & 0xFF
red = (rgb >> 16) & 0xFF red = (rgb >> 16) & 0xFF
return color_util.color_RGB_to_hs(red, green, blue) return (red, green, blue)
def set_music_mode(self, music_mode) -> None: def set_music_mode(self, music_mode) -> None:
"""Set the music mode on or off.""" """Set the music mode on or off."""
@ -606,10 +610,19 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
brightness / 255 * 100, duration=duration, light_type=self.light_type brightness / 255 * 100, duration=duration, light_type=self.light_type
) )
@_cmd
def set_hs(self, hs_color, duration) -> None:
"""Set bulb's color."""
if hs_color and COLOR_MODE_HS in self.supported_color_modes:
_LOGGER.debug("Setting HS: %s", hs_color)
self._bulb.set_hsv(
hs_color[0], hs_color[1], duration=duration, light_type=self.light_type
)
@_cmd @_cmd
def set_rgb(self, rgb, duration) -> None: def set_rgb(self, rgb, duration) -> None:
"""Set bulb's color.""" """Set bulb's color."""
if rgb and self.supported_features & SUPPORT_COLOR: if rgb and COLOR_MODE_RGB in self.supported_color_modes:
_LOGGER.debug("Setting RGB: %s", rgb) _LOGGER.debug("Setting RGB: %s", rgb)
self._bulb.set_rgb( self._bulb.set_rgb(
rgb[0], rgb[1], rgb[2], duration=duration, light_type=self.light_type rgb[0], rgb[1], rgb[2], duration=duration, light_type=self.light_type
@ -618,7 +631,7 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
@_cmd @_cmd
def set_colortemp(self, colortemp, duration) -> None: def set_colortemp(self, colortemp, duration) -> None:
"""Set bulb's color temperature.""" """Set bulb's color temperature."""
if colortemp and self.supported_features & SUPPORT_COLOR_TEMP: if colortemp and COLOR_MODE_COLOR_TEMP in self.supported_color_modes:
temp_in_k = mired_to_kelvin(colortemp) temp_in_k = mired_to_kelvin(colortemp)
_LOGGER.debug("Setting color temp: %s K", temp_in_k) _LOGGER.debug("Setting color temp: %s K", temp_in_k)
@ -702,7 +715,7 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)
colortemp = kwargs.get(ATTR_COLOR_TEMP) colortemp = kwargs.get(ATTR_COLOR_TEMP)
hs_color = kwargs.get(ATTR_HS_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
rgb = color_util.color_hs_to_RGB(*hs_color) if hs_color else None rgb = kwargs.get(ATTR_RGB_COLOR)
flash = kwargs.get(ATTR_FLASH) flash = kwargs.get(ATTR_FLASH)
effect = kwargs.get(ATTR_EFFECT) effect = kwargs.get(ATTR_EFFECT)
@ -726,6 +739,7 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
try: try:
# values checked for none in methods # values checked for none in methods
self.set_hs(hs_color, duration)
self.set_rgb(rgb, duration) self.set_rgb(rgb, duration)
self.set_colortemp(colortemp, duration) self.set_colortemp(colortemp, duration)
self.set_brightness(brightness, duration) self.set_brightness(brightness, duration)
@ -786,13 +800,23 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
_LOGGER.error("Unable to set scene: %s", ex) _LOGGER.error("Unable to set scene: %s", ex)
class YeelightColorLightSupport: class YeelightColorLightSupport(YeelightGenericLight):
"""Representation of a Color Yeelight light support.""" """Representation of a Color Yeelight light support."""
_attr_supported_color_modes = {COLOR_MODE_COLOR_TEMP, COLOR_MODE_HS, COLOR_MODE_RGB}
@property @property
def supported_features(self) -> int: def color_mode(self):
"""Flag supported features.""" """Return the color mode."""
return SUPPORT_YEELIGHT_RGB color_mode = int(self._get_property("color_mode"))
if color_mode == 1: # RGB
return COLOR_MODE_RGB
if color_mode == 2: # color temperature
return COLOR_MODE_COLOR_TEMP
if color_mode == 3: # hsv
return COLOR_MODE_HS
_LOGGER.debug("Light reported unknown color mode: %s", color_mode)
return COLOR_MODE_UNKNOWN
@property @property
def _predefined_effects(self): def _predefined_effects(self):
@ -800,12 +824,10 @@ class YeelightColorLightSupport:
class YeelightWhiteTempLightSupport: class YeelightWhiteTempLightSupport:
"""Representation of a Color Yeelight light.""" """Representation of a White temp Yeelight light."""
@property _attr_color_mode = COLOR_MODE_COLOR_TEMP
def supported_features(self) -> int: _attr_supported_color_modes = {COLOR_MODE_COLOR_TEMP}
"""Flag supported features."""
return SUPPORT_YEELIGHT_WHITE_TEMP
@property @property
def _predefined_effects(self): def _predefined_effects(self):
@ -913,12 +935,15 @@ class YeelightNightLightModeWithAmbientSupport(YeelightNightLightMode):
return "main_power" return "main_power"
class YeelightNightLightModeWithWithoutBrightnessControl(YeelightNightLightMode): class YeelightNightLightModeWithoutBrightnessControl(YeelightNightLightMode):
"""Representation of a Yeelight, when in nightlight mode. """Representation of a Yeelight, when in nightlight mode.
It represents case when nightlight mode brightness control is not supported. It represents case when nightlight mode brightness control is not supported.
""" """
_attr_color_mode = COLOR_MODE_ONOFF
_attr_supported_color_modes = {COLOR_MODE_ONOFF}
@property @property
def supported_features(self): def supported_features(self):
"""Flag no supported features.""" """Flag no supported features."""

View File

@ -49,7 +49,9 @@ PROPERTIES = {
"bg_flowing": "0", "bg_flowing": "0",
"bg_ct": "5000", "bg_ct": "5000",
"bg_bright": "80", "bg_bright": "80",
"bg_rgb": "16711680", "bg_rgb": "65280",
"bg_hue": "200",
"bg_sat": "70",
"nl_br": "23", "nl_br": "23",
"active_mode": "0", "active_mode": "0",
"current_brightness": "30", "current_brightness": "30",

View File

@ -77,8 +77,6 @@ from homeassistant.components.yeelight.light import (
SERVICE_SET_MUSIC_MODE, SERVICE_SET_MUSIC_MODE,
SERVICE_START_FLOW, SERVICE_START_FLOW,
SUPPORT_YEELIGHT, SUPPORT_YEELIGHT,
SUPPORT_YEELIGHT_RGB,
SUPPORT_YEELIGHT_WHITE_TEMP,
YEELIGHT_COLOR_EFFECT_LIST, YEELIGHT_COLOR_EFFECT_LIST,
YEELIGHT_MONO_EFFECT_LIST, YEELIGHT_MONO_EFFECT_LIST,
YEELIGHT_TEMP_ONLY_EFFECT_LIST, YEELIGHT_TEMP_ONLY_EFFECT_LIST,
@ -171,7 +169,91 @@ async def test_services(hass: HomeAssistant, caplog):
== err_count + 1 == err_count + 1
) )
# turn_on # turn_on rgb_color
brightness = 100
rgb_color = (0, 128, 255)
transition = 2
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: ENTITY_LIGHT,
ATTR_BRIGHTNESS: brightness,
ATTR_RGB_COLOR: rgb_color,
ATTR_FLASH: FLASH_LONG,
ATTR_EFFECT: EFFECT_STOP,
ATTR_TRANSITION: transition,
},
blocking=True,
)
mocked_bulb.turn_on.assert_called_once_with(
duration=transition * 1000,
light_type=LightType.Main,
power_mode=PowerMode.NORMAL,
)
mocked_bulb.turn_on.reset_mock()
mocked_bulb.start_music.assert_called_once()
mocked_bulb.start_music.reset_mock()
mocked_bulb.set_brightness.assert_called_once_with(
brightness / 255 * 100, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_brightness.reset_mock()
mocked_bulb.set_color_temp.assert_not_called()
mocked_bulb.set_color_temp.reset_mock()
mocked_bulb.set_hsv.assert_not_called()
mocked_bulb.set_hsv.reset_mock()
mocked_bulb.set_rgb.assert_called_once_with(
*rgb_color, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_rgb.reset_mock()
mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.start_flow.reset_mock()
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.stop_flow.reset_mock()
# turn_on hs_color
brightness = 100
hs_color = (180, 100)
transition = 2
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: ENTITY_LIGHT,
ATTR_BRIGHTNESS: brightness,
ATTR_HS_COLOR: hs_color,
ATTR_FLASH: FLASH_LONG,
ATTR_EFFECT: EFFECT_STOP,
ATTR_TRANSITION: transition,
},
blocking=True,
)
mocked_bulb.turn_on.assert_called_once_with(
duration=transition * 1000,
light_type=LightType.Main,
power_mode=PowerMode.NORMAL,
)
mocked_bulb.turn_on.reset_mock()
mocked_bulb.start_music.assert_called_once()
mocked_bulb.start_music.reset_mock()
mocked_bulb.set_brightness.assert_called_once_with(
brightness / 255 * 100, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_brightness.reset_mock()
mocked_bulb.set_color_temp.assert_not_called()
mocked_bulb.set_color_temp.reset_mock()
mocked_bulb.set_hsv.assert_called_once_with(
*hs_color, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_hsv.reset_mock()
mocked_bulb.set_rgb.assert_not_called()
mocked_bulb.set_rgb.reset_mock()
mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.start_flow.reset_mock()
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.stop_flow.reset_mock()
# turn_on color_temp
brightness = 100 brightness = 100
color_temp = 200 color_temp = 200
transition = 1 transition = 1
@ -203,6 +285,8 @@ async def test_services(hass: HomeAssistant, caplog):
duration=transition * 1000, duration=transition * 1000,
light_type=LightType.Main, light_type=LightType.Main,
) )
mocked_bulb.set_hsv.assert_not_called()
mocked_bulb.set_rgb.assert_not_called()
mocked_bulb.start_flow.assert_called_once() # flash mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main) mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
@ -331,12 +415,12 @@ async def test_services(hass: HomeAssistant, caplog):
) )
async def test_device_types(hass: HomeAssistant): async def test_device_types(hass: HomeAssistant, caplog):
"""Test different device types.""" """Test different device types."""
mocked_bulb = _mocked_bulb() mocked_bulb = _mocked_bulb()
properties = {**PROPERTIES} properties = {**PROPERTIES}
properties.pop("active_mode") properties.pop("active_mode")
properties["color_mode"] = "3" properties["color_mode"] = "3" # HSV
mocked_bulb.last_properties = properties mocked_bulb.last_properties = properties
async def _async_setup(config_entry): async def _async_setup(config_entry):
@ -403,15 +487,16 @@ async def test_device_types(hass: HomeAssistant):
ct = color_temperature_kelvin_to_mired(int(PROPERTIES["ct"])) ct = color_temperature_kelvin_to_mired(int(PROPERTIES["ct"]))
hue = int(PROPERTIES["hue"]) hue = int(PROPERTIES["hue"])
sat = int(PROPERTIES["sat"]) sat = int(PROPERTIES["sat"])
hs_color = (round(hue / 360 * 65536, 3), round(sat / 100 * 255, 3)) rgb = int(PROPERTIES["rgb"])
rgb_color = color_hs_to_RGB(*hs_color) rgb_color = ((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF)
xy_color = color_hs_to_xy(*hs_color) hs_color = (hue, sat)
bg_bright = round(255 * int(PROPERTIES["bg_bright"]) / 100) bg_bright = round(255 * int(PROPERTIES["bg_bright"]) / 100)
bg_ct = color_temperature_kelvin_to_mired(int(PROPERTIES["bg_ct"])) bg_ct = color_temperature_kelvin_to_mired(int(PROPERTIES["bg_ct"]))
bg_hue = int(PROPERTIES["bg_hue"])
bg_sat = int(PROPERTIES["bg_sat"])
bg_rgb = int(PROPERTIES["bg_rgb"]) bg_rgb = int(PROPERTIES["bg_rgb"])
bg_hs_color = (bg_hue, bg_sat)
bg_rgb_color = ((bg_rgb >> 16) & 0xFF, (bg_rgb >> 8) & 0xFF, bg_rgb & 0xFF) bg_rgb_color = ((bg_rgb >> 16) & 0xFF, (bg_rgb >> 8) & 0xFF, bg_rgb & 0xFF)
bg_hs_color = color_RGB_to_hs(*bg_rgb_color)
bg_xy_color = color_RGB_to_xy(*bg_rgb_color)
nl_br = round(255 * int(PROPERTIES["nl_br"]) / 100) nl_br = round(255 * int(PROPERTIES["nl_br"]) / 100)
# Default # Default
@ -440,14 +525,15 @@ async def test_device_types(hass: HomeAssistant):
}, },
) )
# Color # Color - color mode CT
mocked_bulb.last_properties["color_mode"] = "2" # CT
model_specs = _MODEL_SPECS["color"] model_specs = _MODEL_SPECS["color"]
await _async_test( await _async_test(
BulbType.Color, BulbType.Color,
"color", "color",
{ {
"effect_list": YEELIGHT_COLOR_EFFECT_LIST, "effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT_RGB, "supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired( "min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"] model_specs["color_temp"]["max"]
), ),
@ -456,11 +542,8 @@ async def test_device_types(hass: HomeAssistant):
), ),
"brightness": current_brightness, "brightness": current_brightness,
"color_temp": ct, "color_temp": ct,
"hs_color": hs_color, "color_mode": "color_temp",
"rgb_color": rgb_color, "supported_color_modes": ["color_temp", "hs", "rgb"],
"xy_color": xy_color,
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs"],
}, },
{ {
"supported_features": 0, "supported_features": 0,
@ -469,6 +552,144 @@ async def test_device_types(hass: HomeAssistant):
}, },
) )
# Color - color mode HS
mocked_bulb.last_properties["color_mode"] = "3" # HSV
model_specs = _MODEL_SPECS["color"]
await _async_test(
BulbType.Color,
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"]
),
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"brightness": current_brightness,
"hs_color": hs_color,
"rgb_color": color_hs_to_RGB(*hs_color),
"xy_color": color_hs_to_xy(*hs_color),
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
{
"supported_features": 0,
"color_mode": "onoff",
"supported_color_modes": ["onoff"],
},
)
# Color - color mode RGB
mocked_bulb.last_properties["color_mode"] = "1" # RGB
model_specs = _MODEL_SPECS["color"]
await _async_test(
BulbType.Color,
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"]
),
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"brightness": current_brightness,
"hs_color": color_RGB_to_hs(*rgb_color),
"rgb_color": rgb_color,
"xy_color": color_RGB_to_xy(*rgb_color),
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
{
"supported_features": 0,
"color_mode": "onoff",
"supported_color_modes": ["onoff"],
},
)
# Color - color mode HS but no hue
mocked_bulb.last_properties["color_mode"] = "3" # HSV
mocked_bulb.last_properties["hue"] = None
model_specs = _MODEL_SPECS["color"]
await _async_test(
BulbType.Color,
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"]
),
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"brightness": current_brightness,
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
{
"supported_features": 0,
"color_mode": "onoff",
"supported_color_modes": ["onoff"],
},
)
# Color - color mode RGB but no color
mocked_bulb.last_properties["color_mode"] = "1" # RGB
mocked_bulb.last_properties["rgb"] = None
model_specs = _MODEL_SPECS["color"]
await _async_test(
BulbType.Color,
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"]
),
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"brightness": current_brightness,
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
{
"supported_features": 0,
"color_mode": "onoff",
"supported_color_modes": ["onoff"],
},
)
# Color - unsupported color_mode
mocked_bulb.last_properties["color_mode"] = 4 # Unsupported
model_specs = _MODEL_SPECS["color"]
await _async_test(
BulbType.Color,
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"]
),
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"color_mode": "unknown",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
{
"supported_features": 0,
"color_mode": "onoff",
"supported_color_modes": ["onoff"],
},
)
assert "Light reported unknown color mode: 4" in caplog.text
# WhiteTemp # WhiteTemp
model_specs = _MODEL_SPECS["ceiling1"] model_specs = _MODEL_SPECS["ceiling1"]
await _async_test( await _async_test(
@ -476,7 +697,7 @@ async def test_device_types(hass: HomeAssistant):
"ceiling1", "ceiling1",
{ {
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT_WHITE_TEMP, "supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired( "min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"] model_specs["color_temp"]["max"]
), ),
@ -509,7 +730,7 @@ async def test_device_types(hass: HomeAssistant):
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"flowing": False, "flowing": False,
"night_light": True, "night_light": True,
"supported_features": SUPPORT_YEELIGHT_WHITE_TEMP, "supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired( "min_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["max"] model_specs["color_temp"]["max"]
), ),
@ -529,21 +750,62 @@ async def test_device_types(hass: HomeAssistant):
"supported_color_modes": ["brightness"], "supported_color_modes": ["brightness"],
}, },
) )
# Background light - color mode CT
mocked_bulb.last_properties["bg_lmode"] = "2" # CT
await _async_test( await _async_test(
BulbType.WhiteTempMood, BulbType.WhiteTempMood,
"ceiling4", "ceiling4",
{ {
"effect_list": YEELIGHT_COLOR_EFFECT_LIST, "effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT_RGB, "supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(6500), "min_mireds": color_temperature_kelvin_to_mired(6500),
"max_mireds": color_temperature_kelvin_to_mired(1700), "max_mireds": color_temperature_kelvin_to_mired(1700),
"brightness": bg_bright, "brightness": bg_bright,
"color_temp": bg_ct, "color_temp": bg_ct,
"color_mode": "color_temp",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
name=f"{UNIQUE_NAME} ambilight",
entity_id=f"{ENTITY_LIGHT}_ambilight",
)
# Background light - color mode HS
mocked_bulb.last_properties["bg_lmode"] = "3" # HS
await _async_test(
BulbType.WhiteTempMood,
"ceiling4",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(6500),
"max_mireds": color_temperature_kelvin_to_mired(1700),
"brightness": bg_bright,
"hs_color": bg_hs_color, "hs_color": bg_hs_color,
"rgb_color": bg_rgb_color, "rgb_color": color_hs_to_RGB(*bg_hs_color),
"xy_color": bg_xy_color, "xy_color": color_hs_to_xy(*bg_hs_color),
"color_mode": "hs", "color_mode": "hs",
"supported_color_modes": ["color_temp", "hs"], "supported_color_modes": ["color_temp", "hs", "rgb"],
},
name=f"{UNIQUE_NAME} ambilight",
entity_id=f"{ENTITY_LIGHT}_ambilight",
)
# Background light - color mode RGB
mocked_bulb.last_properties["bg_lmode"] = "1" # RGB
await _async_test(
BulbType.WhiteTempMood,
"ceiling4",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"min_mireds": color_temperature_kelvin_to_mired(6500),
"max_mireds": color_temperature_kelvin_to_mired(1700),
"brightness": bg_bright,
"hs_color": color_RGB_to_hs(*bg_rgb_color),
"rgb_color": bg_rgb_color,
"xy_color": color_RGB_to_xy(*bg_rgb_color),
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
}, },
name=f"{UNIQUE_NAME} ambilight", name=f"{UNIQUE_NAME} ambilight",
entity_id=f"{ENTITY_LIGHT}_ambilight", entity_id=f"{ENTITY_LIGHT}_ambilight",