mirror of
https://github.com/home-assistant/core.git
synced 2025-04-27 10:47:51 +00:00
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:
parent
3b0f67acd1
commit
dad7a597ae
@ -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."""
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user