mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-11 22:34:04 +02:00
Compare commits
7 commits
main
...
1.0/accent
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af2790a8db |
||
|
|
105a378e0f | ||
|
|
a21b7af89d | ||
|
|
cf29d5084f | ||
|
|
94e7e1a6d3 | ||
|
|
08aa27f044 | ||
|
|
c552702d36 |
2 changed files with 195 additions and 6 deletions
|
|
@ -37,20 +37,34 @@ CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", 0
|
|||
CONF_SUNSET_TIME = "sunset_time"
|
||||
CONF_TAKE_OVER_CONTROL, DEFAULT_TAKE_OVER_CONTROL = "take_over_control", True
|
||||
CONF_TRANSITION, DEFAULT_TRANSITION = "transition", 45
|
||||
CONF_ACCENT_COLOR, DEFAULT_ACCENT_COLOR = "accent_color", None
|
||||
CONF_ACCENT_COLOR_RGB, DEFAULT_ACCENT_COLOR_RGB = "accent_color_rgb", None
|
||||
CONF_ACCENT_COLOR_XY, DEFAULT_ACCENT_COLOR_XY = "accent_color_xy", None
|
||||
CONF_ACCENT_COLOR_HS, DEFAULT_ACCENT_COLOR_HS = "accent_color_hs", None
|
||||
CONF_ACCENT_COLOR_MIX_MIN, DEFAULT_ACCENT_COLOR_MIX_MIN = "accent_color_mix_min", -50
|
||||
CONF_ACCENT_COLOR_MIX_MAX, DEFAULT_ACCENT_COLOR_MIX_MAX = "accent_color_mix_max", 100
|
||||
|
||||
ATTR_SWITCH_ACCENT_COLOR = "accent_color"
|
||||
|
||||
SLEEP_MODE_SWITCH = "sleep_mode_switch"
|
||||
ADAPT_COLOR_SWITCH = "adapt_color_switch"
|
||||
ADAPT_BRIGHTNESS_SWITCH = "adapt_brightness_switch"
|
||||
ENABLE_ACCENT_COLOR_SWITCH = "enable_accent_color_switch"
|
||||
ATTR_TURN_ON_OFF_LISTENER = "turn_on_off_listener"
|
||||
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
||||
NONE_STR = "None"
|
||||
ATTR_ADAPT_COLOR = "adapt_color"
|
||||
ATTR_ADAPT_BRIGHTNESS = "adapt_brightness"
|
||||
ATTR_USE_ACCENT_COLOR = "use_accent_color"
|
||||
|
||||
SERVICE_SET_MANUAL_CONTROL = "set_manual_control"
|
||||
CONF_MANUAL_CONTROL = "manual_control"
|
||||
SERVICE_APPLY = "apply"
|
||||
CONF_TURN_ON_LIGHTS = "turn_on_lights"
|
||||
SERVICE_SET_ACCENT_COLOR = "set_accent_color"
|
||||
CONF_ACCENT_RGB = "rgb"
|
||||
CONF_ACCENT_HS = "hs"
|
||||
CONF_ACCENT_XY = "xy"
|
||||
|
||||
TURNING_OFF_DELAY = 5
|
||||
|
||||
|
|
@ -71,6 +85,11 @@ VALIDATION_TUPLES = [
|
|||
(CONF_MAX_BRIGHTNESS, DEFAULT_MAX_BRIGHTNESS, int_between(1, 100)),
|
||||
(CONF_MIN_COLOR_TEMP, DEFAULT_MIN_COLOR_TEMP, int_between(1000, 10000)),
|
||||
(CONF_MAX_COLOR_TEMP, DEFAULT_MAX_COLOR_TEMP, int_between(1000, 10000)),
|
||||
(CONF_ACCENT_COLOR_RGB, DEFAULT_ACCENT_COLOR_RGB, vol.Any(None,[int])),
|
||||
(CONF_ACCENT_COLOR_XY, DEFAULT_ACCENT_COLOR_XY, vol.Any(None,[float])),
|
||||
(CONF_ACCENT_COLOR_HS, DEFAULT_ACCENT_COLOR_HS, vol.Any(None,[float])),
|
||||
(CONF_ACCENT_COLOR_MIX_MIN, DEFAULT_ACCENT_COLOR_MIX_MIN, int_between(-100, 100)),
|
||||
(CONF_ACCENT_COLOR_MIX_MAX, DEFAULT_ACCENT_COLOR_MIX_MAX, int_between(-100, 100)),
|
||||
(CONF_SLEEP_BRIGHTNESS, DEFAULT_SLEEP_BRIGHTNESS, int_between(1, 100)),
|
||||
(CONF_SLEEP_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP, int_between(1000, 10000)),
|
||||
(CONF_SUNRISE_TIME, NONE_STR, str),
|
||||
|
|
|
|||
|
|
@ -84,10 +84,14 @@ from homeassistant.helpers.restore_state import RestoreEntity
|
|||
from homeassistant.helpers.sun import get_astral_location
|
||||
from homeassistant.util import slugify
|
||||
from homeassistant.util.color import (
|
||||
color_hs_to_RGB,
|
||||
color_RGB_to_xy,
|
||||
color_RGB_to_xy_brightness,
|
||||
color_temperature_kelvin_to_mired,
|
||||
color_temperature_to_rgb,
|
||||
color_xy_brightness_to_RGB,
|
||||
color_xy_to_hs,
|
||||
color_xy_to_RGB,
|
||||
)
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
|
|
@ -97,6 +101,17 @@ from .const import (
|
|||
ATTR_ADAPT_BRIGHTNESS,
|
||||
ATTR_ADAPT_COLOR,
|
||||
ATTR_TURN_ON_OFF_LISTENER,
|
||||
ATTR_USE_ACCENT_COLOR,
|
||||
ATTR_SWITCH_ACCENT_COLOR,
|
||||
CONF_ACCENT_COLOR,
|
||||
CONF_ACCENT_COLOR_HS,
|
||||
CONF_ACCENT_COLOR_MIX_MAX,
|
||||
CONF_ACCENT_COLOR_MIX_MIN,
|
||||
CONF_ACCENT_COLOR_RGB,
|
||||
CONF_ACCENT_COLOR_XY,
|
||||
CONF_ACCENT_HS,
|
||||
CONF_ACCENT_RGB,
|
||||
CONF_ACCENT_XY,
|
||||
CONF_DETECT_NON_HA_CHANGES,
|
||||
CONF_INITIAL_TRANSITION,
|
||||
CONF_SLEEP_TRANSITION,
|
||||
|
|
@ -121,8 +136,10 @@ from .const import (
|
|||
CONF_TURN_ON_LIGHTS,
|
||||
DOMAIN,
|
||||
EXTRA_VALIDATION,
|
||||
ENABLE_ACCENT_COLOR_SWITCH,
|
||||
ICON,
|
||||
SERVICE_APPLY,
|
||||
SERVICE_SET_ACCENT_COLOR,
|
||||
SERVICE_SET_MANUAL_CONTROL,
|
||||
SLEEP_MODE_SWITCH,
|
||||
SUN_EVENT_MIDNIGHT,
|
||||
|
|
@ -238,11 +255,30 @@ async def handle_apply(switch: AdaptiveSwitch, service_call: ServiceCall):
|
|||
data[CONF_TRANSITION],
|
||||
data[ATTR_ADAPT_BRIGHTNESS],
|
||||
data[ATTR_ADAPT_COLOR],
|
||||
data[ATTR_USE_ACCENT_COLOR],
|
||||
data[CONF_PREFER_RGB_COLOR],
|
||||
force=True,
|
||||
context=switch.create_context("service", parent=service_call.context),
|
||||
)
|
||||
|
||||
async def handle_set_accent_color(switch: AdaptiveSwitch, service_call: ServiceCall):
|
||||
_LOGGER.debug(
|
||||
"Called 'adaptive_lighting.set_accent_color' service with '%s'",
|
||||
service_call.data,
|
||||
)
|
||||
data = service_call.data
|
||||
switch._sun_light_settings.set_accent_color(
|
||||
get_rgb_from_any_form(
|
||||
data[CONF_ACCENT_RGB] if CONF_ACCENT_RGB in data else None,
|
||||
data[CONF_ACCENT_HS] if CONF_ACCENT_HS in data else None,
|
||||
data[CONF_ACCENT_XY] if CONF_ACCENT_XY in data else None
|
||||
)
|
||||
)
|
||||
if switch.is_on:
|
||||
await switch._update_attrs_and_maybe_adapt_lights(
|
||||
force=True,
|
||||
context=switch.create_context("accent"),
|
||||
)
|
||||
|
||||
async def handle_set_manual_control(switch: AdaptiveSwitch, service_call: ServiceCall):
|
||||
"""Set or unset lights as 'manually controlled'."""
|
||||
|
|
@ -304,6 +340,7 @@ async def async_setup_entry(
|
|||
sleep_mode_switch = SimpleSwitch("Sleep Mode", False, hass, config_entry)
|
||||
adapt_color_switch = SimpleSwitch("Adapt Color", True, hass, config_entry)
|
||||
adapt_brightness_switch = SimpleSwitch("Adapt Brightness", True, hass, config_entry)
|
||||
accent_color_switch = SimpleSwitch("Enable Accent Color", False, hass, config_entry)
|
||||
switch = AdaptiveSwitch(
|
||||
hass,
|
||||
config_entry,
|
||||
|
|
@ -311,15 +348,17 @@ async def async_setup_entry(
|
|||
sleep_mode_switch,
|
||||
adapt_color_switch,
|
||||
adapt_brightness_switch,
|
||||
accent_color_switch,
|
||||
)
|
||||
|
||||
data[config_entry.entry_id][SLEEP_MODE_SWITCH] = sleep_mode_switch
|
||||
data[config_entry.entry_id][ADAPT_COLOR_SWITCH] = adapt_color_switch
|
||||
data[config_entry.entry_id][ADAPT_BRIGHTNESS_SWITCH] = adapt_brightness_switch
|
||||
data[config_entry.entry_id][ENABLE_ACCENT_COLOR_SWITCH] = accent_color_switch
|
||||
data[config_entry.entry_id][SWITCH_DOMAIN] = switch
|
||||
|
||||
async_add_entities(
|
||||
[switch, sleep_mode_switch, adapt_color_switch, adapt_brightness_switch],
|
||||
[switch, sleep_mode_switch, adapt_color_switch, adapt_brightness_switch, accent_color_switch],
|
||||
update_before_add=True,
|
||||
)
|
||||
|
||||
|
|
@ -341,6 +380,16 @@ async def async_setup_entry(
|
|||
handle_apply,
|
||||
)
|
||||
|
||||
platform.async_register_entity_service(
|
||||
SERVICE_SET_ACCENT_COLOR,
|
||||
{
|
||||
vol.Optional(CONF_ACCENT_RGB, default=None): vol.Any(None, [int]),
|
||||
vol.Optional(CONF_ACCENT_HS, default=None): vol.Any(None, [float]),
|
||||
vol.Optional(CONF_ACCENT_XY, default=None): vol.Any(None, [float]),
|
||||
},
|
||||
handle_set_accent_color,
|
||||
)
|
||||
|
||||
platform.async_register_entity_service(
|
||||
SERVICE_SET_MANUAL_CONTROL,
|
||||
{
|
||||
|
|
@ -362,8 +411,23 @@ def validate(config_entry: ConfigEntry):
|
|||
value = data.get(key)
|
||||
if value is not None:
|
||||
data[key] = validate_value(value) # Fix the types of the inputs
|
||||
data[CONF_ACCENT_COLOR] = get_rgb_from_any_form(
|
||||
config_entry.data[CONF_ACCENT_COLOR_RGB] if CONF_ACCENT_COLOR_RGB in data else None,
|
||||
config_entry.data[CONF_ACCENT_COLOR_HS] if CONF_ACCENT_COLOR_HS in data else None,
|
||||
config_entry.data[CONF_ACCENT_COLOR_XY] if CONF_ACCENT_COLOR_XY in data else None
|
||||
)
|
||||
return data
|
||||
|
||||
def get_rgb_from_any_form(
|
||||
rgb: Tuple[float, float, float] = None, hs: Tuple[float, float] = None, xy: Tuple[float, float] = None
|
||||
) -> Union[Tuple[float, float, float], None]:
|
||||
if rgb is not None:
|
||||
return rgb
|
||||
if hs is not None:
|
||||
return color_hs_to_RGB(hs[0], hs[1])
|
||||
if xy is not None:
|
||||
return color_xy_to_RGB(xy[0], xy[1])
|
||||
return None
|
||||
|
||||
def match_switch_state_event(event: Event, from_or_to_state: List[str]):
|
||||
"""Match state event when either 'from_state' or 'to_state' matches."""
|
||||
|
|
@ -442,6 +506,14 @@ def color_difference_redmean(
|
|||
blue_term = (2 + (255 - r_hat) / 256) * delta_b ** 2
|
||||
return math.sqrt(red_term + green_term + blue_term)
|
||||
|
||||
def interpolate_colors_xyb(
|
||||
xyb1: Tuple[float, float, float], xyb: Tuple[float, float, float], weight: float
|
||||
) -> Tuple[float, float, float]:
|
||||
"""Interpolate between two HSV colors."""
|
||||
x = xyb1[0] + (xyb[0] - xyb1[0]) * weight
|
||||
y = xyb1[1] + (xyb[1] - xyb1[1]) * weight
|
||||
b = xyb1[2] + (xyb[2] - xyb1[2]) * weight
|
||||
return (x, y, b)
|
||||
|
||||
def _attributes_have_changed(
|
||||
light: str,
|
||||
|
|
@ -551,6 +623,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
sleep_mode_switch: SimpleSwitch,
|
||||
adapt_color_switch: SimpleSwitch,
|
||||
adapt_brightness_switch: SimpleSwitch,
|
||||
accent_color_switch: SimpleSwitch,
|
||||
):
|
||||
"""Initialize the Adaptive Lighting switch."""
|
||||
self.hass = hass
|
||||
|
|
@ -558,6 +631,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
self.sleep_mode_switch = sleep_mode_switch
|
||||
self.adapt_color_switch = adapt_color_switch
|
||||
self.adapt_brightness_switch = adapt_brightness_switch
|
||||
self.accent_color_switch = accent_color_switch
|
||||
|
||||
data = validate(config_entry)
|
||||
self._name = data[CONF_NAME]
|
||||
|
|
@ -594,8 +668,12 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
sunset_offset=data[CONF_SUNSET_OFFSET],
|
||||
sunset_time=data[CONF_SUNSET_TIME],
|
||||
time_zone=self.hass.config.time_zone,
|
||||
accent_color=data[CONF_ACCENT_COLOR],
|
||||
accent_color_lower_bound=float(data[CONF_ACCENT_COLOR_MIX_MIN])/100.0,
|
||||
accent_color_upper_bound=float(data[CONF_ACCENT_COLOR_MIX_MAX])/100.0,
|
||||
transition=data[CONF_TRANSITION],
|
||||
)
|
||||
self._sun_light_settings.set_accent_color(data[CONF_ACCENT_COLOR])
|
||||
|
||||
# Set other attributes
|
||||
self._icon = ICON
|
||||
|
|
@ -651,6 +729,20 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
)
|
||||
last_state = await self.async_get_last_state()
|
||||
is_new_entry = last_state is None # newly added to HA
|
||||
if (not is_new_entry
|
||||
and self._sun_light_settings.accent_color is None
|
||||
and ATTR_SWITCH_ACCENT_COLOR in last_state.attributes
|
||||
and last_state.attributes[ATTR_SWITCH_ACCENT_COLOR] is not None
|
||||
and len(last_state.attributes[ATTR_SWITCH_ACCENT_COLOR]) == 3
|
||||
):
|
||||
# restore previous accent_color as the entry is available
|
||||
# and the color is not set by the configuration
|
||||
last_accent_color = last_state.attributes[ATTR_SWITCH_ACCENT_COLOR]
|
||||
self._sun_light_settings.accent_color = (
|
||||
float(last_accent_color[0]),
|
||||
float(last_accent_color[1]),
|
||||
float(last_accent_color[2]),
|
||||
)
|
||||
if is_new_entry or last_state.state == STATE_ON:
|
||||
await self.async_turn_on(adapt_lights=not self._only_once)
|
||||
else:
|
||||
|
|
@ -682,8 +774,13 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
self.sleep_mode_switch.entity_id,
|
||||
self._sleep_mode_switch_state_event,
|
||||
)
|
||||
remove_accent_color = async_track_state_change_event(
|
||||
self.hass,
|
||||
self.accent_color_switch.entity_id,
|
||||
self._accent_color_switch_state_event,
|
||||
)
|
||||
|
||||
self.remove_listeners.extend([remove_interval, remove_sleep])
|
||||
self.remove_listeners.extend([remove_interval, remove_sleep, remove_accent_color])
|
||||
|
||||
if self._lights:
|
||||
self._expand_light_groups()
|
||||
|
|
@ -768,6 +865,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
transition: Optional[int] = None,
|
||||
adapt_brightness: Optional[bool] = None,
|
||||
adapt_color: Optional[bool] = None,
|
||||
use_accent_color: Optional[bool] = None,
|
||||
prefer_rgb_color: Optional[bool] = None,
|
||||
force: bool = False,
|
||||
context: Optional[Context] = None,
|
||||
|
|
@ -785,6 +883,8 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
adapt_brightness = self.adapt_brightness_switch.is_on
|
||||
if adapt_color is None:
|
||||
adapt_color = self.adapt_color_switch.is_on
|
||||
if use_accent_color is None:
|
||||
use_accent_color = self.accent_color_switch.is_on
|
||||
if prefer_rgb_color is None:
|
||||
prefer_rgb_color = self._prefer_rgb_color
|
||||
|
||||
|
|
@ -802,7 +902,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
if (
|
||||
"color_temp" in features
|
||||
and adapt_color
|
||||
and not (prefer_rgb_color and "color" in features)
|
||||
and not ((prefer_rgb_color or use_accent_color) and "color" in features)
|
||||
):
|
||||
attributes = self.hass.states.get(light).attributes
|
||||
min_mireds, max_mireds = attributes["min_mireds"], attributes["max_mireds"]
|
||||
|
|
@ -872,7 +972,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
)
|
||||
assert self.is_on
|
||||
self._settings = self._sun_light_settings.get_settings(
|
||||
self.sleep_mode_switch.is_on, transition
|
||||
self.sleep_mode_switch.is_on, self.accent_color_switch.is_on, transition
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
if lights is None:
|
||||
|
|
@ -933,6 +1033,20 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
context=self.create_context("sleep", parent=event.context),
|
||||
)
|
||||
|
||||
async def _accent_color_switch_state_event(self, event: Event) -> None:
|
||||
if not match_switch_state_event(event, (STATE_ON, STATE_OFF)):
|
||||
return
|
||||
_LOGGER.debug(
|
||||
"%s: _accent_color_switch_state_event, event: '%s'", self._name, event
|
||||
)
|
||||
# Reset the manually controlled status when the "sleep mode" changes
|
||||
self.turn_on_off_listener.reset(*self._lights)
|
||||
await self._update_attrs_and_maybe_adapt_lights(
|
||||
transition=self._initial_transition,
|
||||
force=True,
|
||||
context=self.create_context("accent"),
|
||||
)
|
||||
|
||||
async def _light_event(self, event: Event) -> None:
|
||||
old_state = event.data.get("old_state")
|
||||
new_state = event.data.get("new_state")
|
||||
|
|
@ -1041,7 +1155,7 @@ class SimpleSwitch(SwitchEntity, RestoreEntity):
|
|||
self._state = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@dataclass
|
||||
class SunLightSettings:
|
||||
"""Track the state of the sun and associated light settings."""
|
||||
|
||||
|
|
@ -1059,6 +1173,25 @@ class SunLightSettings:
|
|||
sunset_time: Optional[datetime.time]
|
||||
time_zone: datetime.tzinfo
|
||||
transition: int
|
||||
accent_color: Optional[Tuple[float, float, float]]
|
||||
accent_color_lower_bound: Optional[float]
|
||||
accent_color_upper_bound: Optional[float]
|
||||
|
||||
_accent_color_xyb: Tuple[float, float, float] = None
|
||||
_bezier_point_xyb: Tuple[float, float, float] = None
|
||||
|
||||
def set_accent_color(self, accent_color: Tuple[float, float, float]):
|
||||
self.accent_color = accent_color
|
||||
if accent_color is not None:
|
||||
self._accent_color_xyb = color_RGB_to_xy_brightness(*accent_color)
|
||||
color_upper_temp: float = self.calc_color_temp_kelvin(self.accent_color_upper_bound, False)
|
||||
color_upper_rgb: Tuple[float, float, float] = color_temperature_to_rgb(
|
||||
color_upper_temp
|
||||
)
|
||||
self._bezier_point_xyb = color_RGB_to_xy_brightness(*color_upper_rgb)
|
||||
else:
|
||||
self._accent_color_xyb = None
|
||||
self._bezier_point_xyb = None
|
||||
|
||||
def get_sun_events(self, date: datetime.datetime) -> Dict[str, float]:
|
||||
"""Get the four sun event's timestamps at 'date'."""
|
||||
|
|
@ -1176,8 +1309,42 @@ class SunLightSettings:
|
|||
return (delta * percent) + self.min_color_temp
|
||||
return self.min_color_temp
|
||||
|
||||
def calc_accented_color_interpolation(
|
||||
self, rgb_color: Tuple[float, float, float], accent_percent: float
|
||||
) -> Tuple[float, float, float]:
|
||||
if self.accent_color is None:
|
||||
return None
|
||||
if self._bezier_point_xyb is None or self._accent_color_xyb is None:
|
||||
self.set_accent_color(self.accent_color)
|
||||
control_point1 = color_RGB_to_xy_brightness(*rgb_color)
|
||||
control_point2 = interpolate_colors_xyb(
|
||||
self._bezier_point_xyb,
|
||||
self._accent_color_xyb,
|
||||
accent_percent
|
||||
)
|
||||
xyb_color = interpolate_colors_xyb(
|
||||
control_point1,
|
||||
control_point2,
|
||||
accent_percent
|
||||
)
|
||||
return color_xy_brightness_to_RGB(*xyb_color)
|
||||
|
||||
def calc_accented_color(
|
||||
self, percent: float, rgb_color: Tuple[float, float, float]
|
||||
) -> Tuple[float, float, float]:
|
||||
if self.accent_color is None:
|
||||
return rgb_color
|
||||
if percent <= self.accent_color_lower_bound:
|
||||
return rgb_color
|
||||
elif percent < self.accent_color_upper_bound:
|
||||
accent_percent = (percent - self.accent_color_lower_bound) \
|
||||
/ (self.accent_color_upper_bound - self.accent_color_lower_bound)
|
||||
return self.calc_accented_color_interpolation(rgb_color, accent_percent)
|
||||
else:
|
||||
return self.accent_color
|
||||
|
||||
def get_settings(
|
||||
self, is_sleep, transition
|
||||
self, is_sleep, use_accent, transition
|
||||
) -> Dict[str, Union[float, Tuple[float, float], Tuple[float, float, float]]]:
|
||||
"""Get all light settings.
|
||||
|
||||
|
|
@ -1190,6 +1357,8 @@ class SunLightSettings:
|
|||
rgb_color: Tuple[float, float, float] = color_temperature_to_rgb(
|
||||
color_temp_kelvin
|
||||
)
|
||||
if use_accent and self.accent_color is not None and not is_sleep:
|
||||
rgb_color = self.calc_accented_color(percent, rgb_color)
|
||||
xy_color: Tuple[float, float] = color_RGB_to_xy(*rgb_color)
|
||||
hs_color: Tuple[float, float] = color_xy_to_hs(*xy_color)
|
||||
return {
|
||||
|
|
@ -1200,6 +1369,7 @@ class SunLightSettings:
|
|||
"xy_color": xy_color,
|
||||
"hs_color": hs_color,
|
||||
"sun_position": percent,
|
||||
ATTR_SWITCH_ACCENT_COLOR: self.accent_color
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue