2021-12-08 08:30:22 +00:00
|
|
|
"""Support for Magic Home lights."""
|
2021-10-02 17:19:36 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import ast
|
2016-07-20 02:32:10 +00:00
|
|
|
import logging
|
2021-12-02 09:55:06 +00:00
|
|
|
from typing import Any, Final
|
2016-09-12 13:52:22 +00:00
|
|
|
|
2021-12-20 12:45:34 +00:00
|
|
|
from flux_led.const import MultiColorEffects
|
2021-12-21 11:09:41 +00:00
|
|
|
from flux_led.protocol import MusicMode
|
2022-01-12 23:03:09 +00:00
|
|
|
from flux_led.utils import rgbcw_brightness, rgbcw_to_rgbwc, rgbw_brightness
|
2016-07-20 02:32:10 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
from homeassistant import config_entries
|
2016-09-12 13:52:22 +00:00
|
|
|
from homeassistant.components.light import (
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_BRIGHTNESS,
|
2019-12-09 13:14:40 +00:00
|
|
|
ATTR_COLOR_TEMP,
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_EFFECT,
|
2021-10-10 19:18:15 +00:00
|
|
|
ATTR_RGB_COLOR,
|
|
|
|
ATTR_RGBW_COLOR,
|
|
|
|
ATTR_RGBWW_COLOR,
|
2021-10-26 02:53:13 +00:00
|
|
|
ATTR_WHITE,
|
2020-04-26 16:49:41 +00:00
|
|
|
LightEntity,
|
2022-04-06 08:55:25 +00:00
|
|
|
LightEntityFeature,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2021-12-19 21:24:04 +00:00
|
|
|
from homeassistant.const import CONF_NAME
|
2021-11-24 18:55:00 +00:00
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2021-10-11 17:20:11 +00:00
|
|
|
from homeassistant.helpers import entity_platform
|
2016-07-20 02:32:10 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2021-10-02 17:19:36 +00:00
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
2021-10-10 19:18:15 +00:00
|
|
|
from homeassistant.util.color import (
|
|
|
|
color_temperature_kelvin_to_mired,
|
|
|
|
color_temperature_mired_to_kelvin,
|
|
|
|
)
|
2016-07-20 02:32:10 +00:00
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
from .const import (
|
|
|
|
CONF_COLORS,
|
|
|
|
CONF_CUSTOM_EFFECT_COLORS,
|
|
|
|
CONF_CUSTOM_EFFECT_SPEED_PCT,
|
|
|
|
CONF_CUSTOM_EFFECT_TRANSITION,
|
2021-12-20 12:45:34 +00:00
|
|
|
CONF_EFFECT,
|
2021-10-02 17:19:36 +00:00
|
|
|
CONF_SPEED_PCT,
|
|
|
|
CONF_TRANSITION,
|
|
|
|
DEFAULT_EFFECT_SPEED,
|
|
|
|
DOMAIN,
|
2022-01-24 06:53:17 +00:00
|
|
|
MIN_CCT_BRIGHTNESS,
|
|
|
|
MIN_RGB_BRIGHTNESS,
|
2022-01-12 23:03:09 +00:00
|
|
|
MULTI_BRIGHTNESS_COLOR_MODES,
|
2021-10-02 17:19:36 +00:00
|
|
|
TRANSITION_GRADUAL,
|
|
|
|
TRANSITION_JUMP,
|
|
|
|
TRANSITION_STROBE,
|
|
|
|
)
|
2021-12-19 16:52:48 +00:00
|
|
|
from .coordinator import FluxLedUpdateCoordinator
|
2021-11-23 00:52:06 +00:00
|
|
|
from .entity import FluxOnOffEntity
|
2021-12-20 12:45:34 +00:00
|
|
|
from .util import (
|
|
|
|
_effect_brightness,
|
|
|
|
_flux_color_mode_to_hass,
|
|
|
|
_hass_color_modes,
|
2022-01-14 23:14:02 +00:00
|
|
|
_min_rgb_brightness,
|
|
|
|
_min_rgbw_brightness,
|
|
|
|
_min_rgbwc_brightness,
|
2021-12-20 12:45:34 +00:00
|
|
|
_str_to_multi_color_effect,
|
|
|
|
)
|
2016-07-20 02:32:10 +00:00
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2016-08-16 06:07:07 +00:00
|
|
|
|
2021-11-24 18:55:00 +00:00
|
|
|
MODE_ATTRS = {
|
|
|
|
ATTR_EFFECT,
|
|
|
|
ATTR_COLOR_TEMP,
|
|
|
|
ATTR_RGB_COLOR,
|
|
|
|
ATTR_RGBW_COLOR,
|
|
|
|
ATTR_RGBWW_COLOR,
|
|
|
|
ATTR_WHITE,
|
|
|
|
}
|
|
|
|
|
2021-12-21 11:09:41 +00:00
|
|
|
ATTR_FOREGROUND_COLOR: Final = "foreground_color"
|
|
|
|
ATTR_BACKGROUND_COLOR: Final = "background_color"
|
|
|
|
ATTR_SENSITIVITY: Final = "sensitivity"
|
|
|
|
ATTR_LIGHT_SCREEN: Final = "light_screen"
|
|
|
|
|
2019-10-31 23:15:20 +00:00
|
|
|
# Constant color temp values for 2 flux_led special modes
|
|
|
|
# Warm-white and Cool-white modes
|
2021-10-02 17:19:36 +00:00
|
|
|
COLOR_TEMP_WARM_VS_COLD_WHITE_CUT_OFF: Final = 285
|
2019-10-31 23:15:20 +00:00
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
EFFECT_CUSTOM: Final = "custom"
|
|
|
|
|
|
|
|
SERVICE_CUSTOM_EFFECT: Final = "set_custom_effect"
|
2021-12-20 12:45:34 +00:00
|
|
|
SERVICE_SET_ZONES: Final = "set_zones"
|
2021-12-21 11:09:41 +00:00
|
|
|
SERVICE_SET_MUSIC_MODE: Final = "set_music_mode"
|
2021-10-02 17:19:36 +00:00
|
|
|
|
|
|
|
CUSTOM_EFFECT_DICT: Final = {
|
|
|
|
vol.Required(CONF_COLORS): vol.All(
|
|
|
|
cv.ensure_list,
|
|
|
|
vol.Length(min=1, max=16),
|
2021-10-30 14:50:24 +00:00
|
|
|
[vol.All(vol.Coerce(tuple), vol.ExactSequence((cv.byte, cv.byte, cv.byte)))],
|
2021-10-02 17:19:36 +00:00
|
|
|
),
|
|
|
|
vol.Optional(CONF_SPEED_PCT, default=50): vol.All(
|
2021-12-21 21:14:44 +00:00
|
|
|
vol.Coerce(int), vol.Range(min=0, max=100)
|
2021-10-02 17:19:36 +00:00
|
|
|
),
|
|
|
|
vol.Optional(CONF_TRANSITION, default=TRANSITION_GRADUAL): vol.All(
|
|
|
|
cv.string, vol.In([TRANSITION_GRADUAL, TRANSITION_JUMP, TRANSITION_STROBE])
|
|
|
|
),
|
|
|
|
}
|
2019-02-06 10:40:57 +00:00
|
|
|
|
2021-12-21 11:09:41 +00:00
|
|
|
SET_MUSIC_MODE_DICT: Final = {
|
|
|
|
vol.Optional(ATTR_SENSITIVITY, default=100): vol.All(
|
2021-12-21 21:14:44 +00:00
|
|
|
vol.Coerce(int), vol.Range(min=0, max=100)
|
2021-12-21 11:09:41 +00:00
|
|
|
),
|
|
|
|
vol.Optional(ATTR_BRIGHTNESS, default=100): vol.All(
|
2021-12-21 21:14:44 +00:00
|
|
|
vol.Coerce(int), vol.Range(min=0, max=100)
|
2021-12-21 11:09:41 +00:00
|
|
|
),
|
|
|
|
vol.Optional(ATTR_EFFECT, default=1): vol.All(
|
2022-01-22 07:16:24 +00:00
|
|
|
vol.Coerce(int), vol.Range(min=0, max=16)
|
2021-12-21 11:09:41 +00:00
|
|
|
),
|
|
|
|
vol.Optional(ATTR_LIGHT_SCREEN, default=False): bool,
|
|
|
|
vol.Optional(ATTR_FOREGROUND_COLOR): vol.All(
|
|
|
|
vol.Coerce(tuple), vol.ExactSequence((cv.byte,) * 3)
|
|
|
|
),
|
|
|
|
vol.Optional(ATTR_BACKGROUND_COLOR): vol.All(
|
|
|
|
vol.Coerce(tuple), vol.ExactSequence((cv.byte,) * 3)
|
|
|
|
),
|
|
|
|
}
|
|
|
|
|
2021-12-20 12:45:34 +00:00
|
|
|
SET_ZONES_DICT: Final = {
|
|
|
|
vol.Required(CONF_COLORS): vol.All(
|
|
|
|
cv.ensure_list,
|
|
|
|
vol.Length(min=1, max=2048),
|
|
|
|
[vol.All(vol.Coerce(tuple), vol.ExactSequence((cv.byte, cv.byte, cv.byte)))],
|
|
|
|
),
|
|
|
|
vol.Optional(CONF_SPEED_PCT, default=50): vol.All(
|
2021-12-21 21:14:44 +00:00
|
|
|
vol.Coerce(int), vol.Range(min=0, max=100)
|
2021-12-20 12:45:34 +00:00
|
|
|
),
|
|
|
|
vol.Optional(CONF_EFFECT, default=MultiColorEffects.STATIC.name.lower()): vol.All(
|
|
|
|
cv.string, vol.In([effect.name.lower() for effect in MultiColorEffects])
|
|
|
|
),
|
|
|
|
}
|
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
|
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
entry: config_entries.ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
2017-05-01 03:10:08 +00:00
|
|
|
"""Set up the Flux lights."""
|
2021-10-02 17:19:36 +00:00
|
|
|
coordinator: FluxLedUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
|
|
|
|
|
|
|
platform = entity_platform.async_get_current_platform()
|
|
|
|
platform.async_register_entity_service(
|
|
|
|
SERVICE_CUSTOM_EFFECT,
|
|
|
|
CUSTOM_EFFECT_DICT,
|
2021-10-11 01:12:54 +00:00
|
|
|
"async_set_custom_effect",
|
2021-10-02 17:19:36 +00:00
|
|
|
)
|
2021-12-20 12:45:34 +00:00
|
|
|
platform.async_register_entity_service(
|
|
|
|
SERVICE_SET_ZONES,
|
|
|
|
SET_ZONES_DICT,
|
|
|
|
"async_set_zones",
|
|
|
|
)
|
2021-12-21 11:09:41 +00:00
|
|
|
platform.async_register_entity_service(
|
|
|
|
SERVICE_SET_MUSIC_MODE,
|
|
|
|
SET_MUSIC_MODE_DICT,
|
|
|
|
"async_set_music_mode",
|
|
|
|
)
|
2021-10-02 17:19:36 +00:00
|
|
|
options = entry.options
|
|
|
|
|
|
|
|
try:
|
|
|
|
custom_effect_colors = ast.literal_eval(
|
|
|
|
options.get(CONF_CUSTOM_EFFECT_COLORS) or "[]"
|
|
|
|
)
|
|
|
|
except (ValueError, TypeError, SyntaxError, MemoryError) as ex:
|
|
|
|
_LOGGER.warning(
|
|
|
|
"Could not parse custom effect colors for %s: %s", entry.unique_id, ex
|
|
|
|
)
|
|
|
|
custom_effect_colors = []
|
|
|
|
|
|
|
|
async_add_entities(
|
|
|
|
[
|
|
|
|
FluxLight(
|
|
|
|
coordinator,
|
2022-01-31 04:17:19 +00:00
|
|
|
entry.unique_id or entry.entry_id,
|
2022-02-15 21:44:35 +00:00
|
|
|
entry.data.get(CONF_NAME, entry.title),
|
2021-10-02 17:19:36 +00:00
|
|
|
list(custom_effect_colors),
|
|
|
|
options.get(CONF_CUSTOM_EFFECT_SPEED_PCT, DEFAULT_EFFECT_SPEED),
|
|
|
|
options.get(CONF_CUSTOM_EFFECT_TRANSITION, TRANSITION_GRADUAL),
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-03-21 13:13:16 +00:00
|
|
|
class FluxLight(
|
|
|
|
FluxOnOffEntity, CoordinatorEntity[FluxLedUpdateCoordinator], LightEntity
|
|
|
|
):
|
2016-07-20 02:32:10 +00:00
|
|
|
"""Representation of a Flux light."""
|
|
|
|
|
2022-04-06 08:55:25 +00:00
|
|
|
_attr_supported_features = LightEntityFeature.TRANSITION | LightEntityFeature.EFFECT
|
2021-11-25 01:34:19 +00:00
|
|
|
|
2021-10-02 17:19:36 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
coordinator: FluxLedUpdateCoordinator,
|
2022-01-31 04:17:19 +00:00
|
|
|
base_unique_id: str,
|
2021-10-02 17:19:36 +00:00
|
|
|
name: str,
|
|
|
|
custom_effect_colors: list[tuple[int, int, int]],
|
|
|
|
custom_effect_speed_pct: int,
|
|
|
|
custom_effect_transition: str,
|
|
|
|
) -> None:
|
2016-07-20 02:32:10 +00:00
|
|
|
"""Initialize the light."""
|
2022-01-31 04:17:19 +00:00
|
|
|
super().__init__(coordinator, base_unique_id, name, None)
|
2022-01-12 23:03:09 +00:00
|
|
|
self._attr_min_mireds = color_temperature_kelvin_to_mired(self._device.max_temp)
|
2021-10-11 01:12:54 +00:00
|
|
|
self._attr_max_mireds = color_temperature_kelvin_to_mired(self._device.min_temp)
|
2021-11-23 00:52:06 +00:00
|
|
|
self._attr_supported_color_modes = _hass_color_modes(self._device)
|
2021-11-25 01:34:19 +00:00
|
|
|
custom_effects: list[str] = []
|
|
|
|
if custom_effect_colors:
|
|
|
|
custom_effects.append(EFFECT_CUSTOM)
|
|
|
|
self._attr_effect_list = [*self._device.effect_list, *custom_effects]
|
2021-10-02 17:19:36 +00:00
|
|
|
self._custom_effect_colors = custom_effect_colors
|
|
|
|
self._custom_effect_speed_pct = custom_effect_speed_pct
|
|
|
|
self._custom_effect_transition = custom_effect_transition
|
2016-07-20 02:32:10 +00:00
|
|
|
|
2016-08-08 15:47:02 +00:00
|
|
|
@property
|
2021-10-02 17:19:36 +00:00
|
|
|
def brightness(self) -> int:
|
2016-08-08 15:47:02 +00:00
|
|
|
"""Return the brightness of this light between 0..255."""
|
2021-12-02 09:55:06 +00:00
|
|
|
return self._device.brightness
|
2016-08-08 15:47:02 +00:00
|
|
|
|
|
|
|
@property
|
2021-10-10 19:18:15 +00:00
|
|
|
def color_temp(self) -> int:
|
|
|
|
"""Return the kelvin value of this light in mired."""
|
2021-10-11 01:12:54 +00:00
|
|
|
return color_temperature_kelvin_to_mired(self._device.color_temp)
|
2021-10-10 19:18:15 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def rgb_color(self) -> tuple[int, int, int]:
|
|
|
|
"""Return the rgb color value."""
|
2021-12-02 09:55:06 +00:00
|
|
|
return self._device.rgb_unscaled
|
2016-08-08 15:47:02 +00:00
|
|
|
|
2016-08-16 06:07:07 +00:00
|
|
|
@property
|
2021-10-10 19:18:15 +00:00
|
|
|
def rgbw_color(self) -> tuple[int, int, int, int]:
|
|
|
|
"""Return the rgbw color value."""
|
2021-12-02 09:55:06 +00:00
|
|
|
return self._device.rgbw
|
2016-08-16 06:07:07 +00:00
|
|
|
|
2018-05-01 19:38:45 +00:00
|
|
|
@property
|
2021-10-10 19:18:15 +00:00
|
|
|
def rgbww_color(self) -> tuple[int, int, int, int, int]:
|
|
|
|
"""Return the rgbww aka rgbcw color value."""
|
2021-12-02 09:55:06 +00:00
|
|
|
return self._device.rgbcw
|
2018-05-01 19:38:45 +00:00
|
|
|
|
2021-10-10 19:18:15 +00:00
|
|
|
@property
|
|
|
|
def color_mode(self) -> str:
|
|
|
|
"""Return the color mode of the light."""
|
2021-10-26 02:53:13 +00:00
|
|
|
return _flux_color_mode_to_hass(
|
|
|
|
self._device.color_mode, self._device.color_modes
|
|
|
|
)
|
2017-02-18 23:45:21 +00:00
|
|
|
|
2019-02-06 10:40:57 +00:00
|
|
|
@property
|
2021-10-02 17:19:36 +00:00
|
|
|
def effect(self) -> str | None:
|
2019-02-06 10:40:57 +00:00
|
|
|
"""Return the current effect."""
|
2021-12-02 09:55:06 +00:00
|
|
|
return self._device.effect
|
2019-02-06 10:40:57 +00:00
|
|
|
|
2021-10-11 01:12:54 +00:00
|
|
|
async def _async_turn_on(self, **kwargs: Any) -> None:
|
2016-07-20 02:32:10 +00:00
|
|
|
"""Turn the specified or all lights on."""
|
2021-12-06 07:56:59 +00:00
|
|
|
if self._device.requires_turn_on or not kwargs:
|
|
|
|
if not self.is_on:
|
|
|
|
await self._device.async_turn_on()
|
|
|
|
if not kwargs:
|
|
|
|
return
|
2021-11-24 18:55:00 +00:00
|
|
|
|
|
|
|
if MODE_ATTRS.intersection(kwargs):
|
|
|
|
await self._async_set_mode(**kwargs)
|
2021-11-23 21:23:38 +00:00
|
|
|
return
|
2021-11-25 11:41:32 +00:00
|
|
|
await self._device.async_set_brightness(self._async_brightness(**kwargs))
|
2021-11-23 21:23:38 +00:00
|
|
|
|
2021-11-24 18:55:00 +00:00
|
|
|
async def _async_set_effect(self, effect: str, brightness: int) -> None:
|
2021-11-23 21:23:38 +00:00
|
|
|
"""Set an effect."""
|
|
|
|
# Custom effect
|
|
|
|
if effect == EFFECT_CUSTOM:
|
|
|
|
if self._custom_effect_colors:
|
|
|
|
await self._device.async_set_custom_pattern(
|
|
|
|
self._custom_effect_colors,
|
|
|
|
self._custom_effect_speed_pct,
|
|
|
|
self._custom_effect_transition,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
await self._device.async_set_effect(
|
2021-11-25 11:41:32 +00:00
|
|
|
effect,
|
|
|
|
self._device.speed or DEFAULT_EFFECT_SPEED,
|
|
|
|
_effect_brightness(brightness),
|
2021-11-23 21:23:38 +00:00
|
|
|
)
|
|
|
|
|
2021-11-24 18:55:00 +00:00
|
|
|
@callback
|
|
|
|
def _async_brightness(self, **kwargs: Any) -> int:
|
|
|
|
"""Determine brightness from kwargs or current value."""
|
2021-11-23 21:23:38 +00:00
|
|
|
if (brightness := kwargs.get(ATTR_BRIGHTNESS)) is None:
|
|
|
|
brightness = self.brightness
|
2022-01-14 23:14:02 +00:00
|
|
|
# If the brightness was previously 0, the light
|
|
|
|
# will not turn on unless brightness is at least 1
|
|
|
|
#
|
|
|
|
# We previously had a problem with the brightness
|
|
|
|
# sometimes reporting as 0 when an effect was in progress,
|
|
|
|
# however this has since been resolved in the upstream library
|
2022-01-24 06:53:17 +00:00
|
|
|
return max(MIN_RGB_BRIGHTNESS, brightness)
|
2019-08-02 15:00:22 +00:00
|
|
|
|
2021-11-24 18:55:00 +00:00
|
|
|
async def _async_set_mode(self, **kwargs: Any) -> None:
|
|
|
|
"""Set an effect or color mode."""
|
|
|
|
brightness = self._async_brightness(**kwargs)
|
|
|
|
# Handle switch to Effect Mode
|
|
|
|
if effect := kwargs.get(ATTR_EFFECT):
|
|
|
|
await self._async_set_effect(effect, brightness)
|
|
|
|
return
|
2021-10-10 19:18:15 +00:00
|
|
|
# Handle switch to CCT Color Mode
|
2021-11-25 01:34:19 +00:00
|
|
|
if color_temp_mired := kwargs.get(ATTR_COLOR_TEMP):
|
2021-10-10 19:18:15 +00:00
|
|
|
color_temp_kelvin = color_temperature_mired_to_kelvin(color_temp_mired)
|
2022-01-12 23:03:09 +00:00
|
|
|
if (
|
|
|
|
ATTR_BRIGHTNESS not in kwargs
|
|
|
|
and self.color_mode in MULTI_BRIGHTNESS_COLOR_MODES
|
|
|
|
):
|
|
|
|
# When switching to color temp from RGBWW or RGB&W mode,
|
|
|
|
# we do not want the overall brightness of the RGB channels
|
2022-01-24 06:53:17 +00:00
|
|
|
brightness = max(MIN_CCT_BRIGHTNESS, *self._device.rgb)
|
2022-01-12 23:03:09 +00:00
|
|
|
await self._device.async_set_white_temp(color_temp_kelvin, brightness)
|
2019-02-06 10:40:57 +00:00
|
|
|
return
|
2021-10-11 01:12:54 +00:00
|
|
|
# Handle switch to RGB Color Mode
|
2021-11-25 01:34:19 +00:00
|
|
|
if rgb := kwargs.get(ATTR_RGB_COLOR):
|
2022-01-14 23:14:02 +00:00
|
|
|
if not self._device.requires_turn_on:
|
|
|
|
rgb = _min_rgb_brightness(rgb)
|
2021-12-02 09:55:06 +00:00
|
|
|
red, green, blue = rgb
|
|
|
|
await self._device.async_set_levels(red, green, blue, brightness=brightness)
|
2021-10-10 19:18:15 +00:00
|
|
|
return
|
|
|
|
# Handle switch to RGBW Color Mode
|
2021-11-25 01:34:19 +00:00
|
|
|
if rgbw := kwargs.get(ATTR_RGBW_COLOR):
|
2021-10-10 19:18:15 +00:00
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
2021-11-25 01:34:19 +00:00
|
|
|
rgbw = rgbw_brightness(rgbw, brightness)
|
2022-01-24 06:53:17 +00:00
|
|
|
rgbw = _min_rgbw_brightness(rgbw, self._device.rgbw)
|
2021-10-11 01:12:54 +00:00
|
|
|
await self._device.async_set_levels(*rgbw)
|
2021-10-10 19:18:15 +00:00
|
|
|
return
|
|
|
|
# Handle switch to RGBWW Color Mode
|
2021-11-25 01:34:19 +00:00
|
|
|
if rgbcw := kwargs.get(ATTR_RGBWW_COLOR):
|
2021-10-10 19:18:15 +00:00
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
|
|
|
rgbcw = rgbcw_brightness(kwargs[ATTR_RGBWW_COLOR], brightness)
|
2022-01-14 23:14:02 +00:00
|
|
|
rgbwc = rgbcw_to_rgbwc(rgbcw)
|
2022-01-24 06:53:17 +00:00
|
|
|
rgbwc = _min_rgbwc_brightness(rgbwc, self._device.rgbww)
|
2022-01-14 23:14:02 +00:00
|
|
|
await self._device.async_set_levels(*rgbwc)
|
2021-10-10 19:18:15 +00:00
|
|
|
return
|
2021-11-25 01:34:19 +00:00
|
|
|
if (white := kwargs.get(ATTR_WHITE)) is not None:
|
|
|
|
await self._device.async_set_levels(w=white)
|
2021-10-26 02:53:13 +00:00
|
|
|
return
|
2021-11-08 03:13:42 +00:00
|
|
|
|
2021-10-11 01:12:54 +00:00
|
|
|
async def async_set_custom_effect(
|
2021-10-02 17:19:36 +00:00
|
|
|
self, colors: list[tuple[int, int, int]], speed_pct: int, transition: str
|
|
|
|
) -> None:
|
|
|
|
"""Set a custom effect on the bulb."""
|
2021-10-11 01:12:54 +00:00
|
|
|
await self._device.async_set_custom_pattern(
|
2021-10-02 17:19:36 +00:00
|
|
|
colors,
|
|
|
|
speed_pct,
|
|
|
|
transition,
|
|
|
|
)
|
2021-12-20 12:45:34 +00:00
|
|
|
|
|
|
|
async def async_set_zones(
|
|
|
|
self, colors: list[tuple[int, int, int]], speed_pct: int, effect: str
|
|
|
|
) -> None:
|
|
|
|
"""Set a colors for zones."""
|
|
|
|
await self._device.async_set_zones(
|
|
|
|
colors,
|
|
|
|
speed_pct,
|
|
|
|
_str_to_multi_color_effect(effect),
|
|
|
|
)
|
2021-12-21 11:09:41 +00:00
|
|
|
|
|
|
|
async def async_set_music_mode(
|
|
|
|
self,
|
|
|
|
sensitivity: int,
|
|
|
|
brightness: int,
|
|
|
|
effect: int,
|
|
|
|
light_screen: bool,
|
|
|
|
foreground_color: tuple[int, int, int] | None = None,
|
|
|
|
background_color: tuple[int, int, int] | None = None,
|
|
|
|
) -> None:
|
|
|
|
"""Configure music mode."""
|
|
|
|
await self._async_ensure_device_on()
|
|
|
|
await self._device.async_set_music_mode(
|
|
|
|
sensitivity=sensitivity,
|
|
|
|
brightness=brightness,
|
|
|
|
mode=MusicMode.LIGHT_SCREEN.value if light_screen else None,
|
|
|
|
effect=effect,
|
|
|
|
foreground_color=foreground_color,
|
|
|
|
background_color=background_color,
|
|
|
|
)
|