mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-27 12:24:19 +02:00
Add adapt_only_on_bare_turn_on which instantly triggers manual_control when turning on with brightness or color (#709)
This commit is contained in:
parent
3f17738bd1
commit
d44cb66148
6 changed files with 131 additions and 53 deletions
|
|
@ -77,6 +77,18 @@ DOCS[CONF_ONLY_ONCE] = (
|
|||
"(`false`). 🔄"
|
||||
)
|
||||
|
||||
CONF_ADAPT_ONLY_ON_BARE_TURN_ON, DEFAULT_ADAPT_ONLY_ON_BARE_TURN_ON = (
|
||||
"adapt_only_on_bare_turn_on",
|
||||
False,
|
||||
)
|
||||
DOCS[CONF_ADAPT_ONLY_ON_BARE_TURN_ON] = (
|
||||
"When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is "
|
||||
"invoked without specifying color or brightness. ❌🌈 "
|
||||
"This e.g., prevents adaptation when activating a scene. "
|
||||
"If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. "
|
||||
"Needs `take_over_control` enabled. 🕵️ "
|
||||
)
|
||||
|
||||
CONF_PREFER_RGB_COLOR, DEFAULT_PREFER_RGB_COLOR = "prefer_rgb_color", False
|
||||
DOCS[CONF_PREFER_RGB_COLOR] = (
|
||||
"Whether to prefer RGB color adjustment over "
|
||||
|
|
@ -329,7 +341,6 @@ VALIDATION_TUPLES = [
|
|||
),
|
||||
(CONF_BRIGHTNESS_MODE_TIME_DARK, DEFAULT_BRIGHTNESS_MODE_TIME_DARK, int),
|
||||
(CONF_BRIGHTNESS_MODE_TIME_LIGHT, DEFAULT_BRIGHTNESS_MODE_TIME_LIGHT, int),
|
||||
(CONF_ONLY_ONCE, DEFAULT_ONLY_ONCE, bool),
|
||||
(CONF_TAKE_OVER_CONTROL, DEFAULT_TAKE_OVER_CONTROL, bool),
|
||||
(CONF_DETECT_NON_HA_CHANGES, DEFAULT_DETECT_NON_HA_CHANGES, bool),
|
||||
(
|
||||
|
|
@ -338,6 +349,7 @@ VALIDATION_TUPLES = [
|
|||
int_between(0, 365 * 24 * 60 * 60), # 1 year max
|
||||
),
|
||||
(CONF_ONLY_ONCE, DEFAULT_ONLY_ONCE, bool),
|
||||
(CONF_ADAPT_ONLY_ON_BARE_TURN_ON, DEFAULT_ADAPT_ONLY_ON_BARE_TURN_ON, bool),
|
||||
(CONF_SEPARATE_TURN_ON_COMMANDS, DEFAULT_SEPARATE_TURN_ON_COMMANDS, bool),
|
||||
(CONF_SEND_SPLIT_DELAY, DEFAULT_SEND_SPLIT_DELAY, int_between(0, 10000)),
|
||||
(CONF_ADAPT_DELAY, DEFAULT_ADAPT_DELAY, cv.positive_float),
|
||||
|
|
|
|||
|
|
@ -45,10 +45,11 @@
|
|||
"brightness_mode": "brightness_mode: Brightness mode to use. Possible values are `default`, `linear`, and `tanh` (uses `brightness_mode_time_dark` and `brightness_mode_time_light`). 📈",
|
||||
"brightness_mode_time_dark": "brightness_mode_time_dark: (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness before/after sunrise/sunset. 📈📉",
|
||||
"brightness_mode_time_light": "brightness_mode_time_light: (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness after/before sunrise/sunset. 📈📉.",
|
||||
"only_once": "only_once: Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄",
|
||||
"take_over_control": "take_over_control: Disable Adaptive Lighting if another source calls `light.turn_on` while lights are on and being adapted. Note that this calls `homeassistant.update_entity` every `interval`! 🔒",
|
||||
"detect_non_ha_changes": "detect_non_ha_changes: Detects and halts adaptations for non-`light.turn_on` state changes. Needs `take_over_control` enabled. 🕵️ Caution: ⚠️ Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Disable this feature if you encounter such issues.",
|
||||
"autoreset_control_seconds": "autoreset_control_seconds: Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️",
|
||||
"only_once": "only_once: Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄",
|
||||
"adapt_only_on_bare_turn_on": "adapt_only_on_bare_turn_on: When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is invoked without specifying color or brightness. ❌🌈 This e.g., prevents adaptation when activating a scene. If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. Needs `take_over_control` enabled. 🕵️ ",
|
||||
"separate_turn_on_commands": "separate_turn_on_commands: Use separate `light.turn_on` calls for color and brightness, needed for some light types. 🔀",
|
||||
"send_split_delay": "send_split_delay: Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️",
|
||||
"adapt_delay": "adapt_delay: Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️",
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ from .const import (
|
|||
ATTR_ADAPT_COLOR,
|
||||
ATTR_ADAPTIVE_LIGHTING_MANAGER,
|
||||
CONF_ADAPT_DELAY,
|
||||
CONF_ADAPT_ONLY_ON_BARE_TURN_ON,
|
||||
CONF_ADAPT_UNTIL_SLEEP,
|
||||
CONF_AUTORESET_CONTROL,
|
||||
CONF_BRIGHTNESS_MODE,
|
||||
|
|
@ -876,15 +877,18 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
self._adapt_delay = data[CONF_ADAPT_DELAY]
|
||||
self._send_split_delay = data[CONF_SEND_SPLIT_DELAY]
|
||||
self._take_over_control = data[CONF_TAKE_OVER_CONTROL]
|
||||
self._detect_non_ha_changes = data[CONF_DETECT_NON_HA_CHANGES]
|
||||
if not data[CONF_TAKE_OVER_CONTROL] and data[CONF_DETECT_NON_HA_CHANGES]:
|
||||
if not data[CONF_TAKE_OVER_CONTROL] and (
|
||||
data[CONF_DETECT_NON_HA_CHANGES] or data[CONF_ADAPT_ONLY_ON_BARE_TURN_ON]
|
||||
):
|
||||
_LOGGER.warning(
|
||||
"%s: Config mismatch: 'detect_non_ha_changes: true' "
|
||||
"requires 'take_over_control' to be enabled. Adjusting config "
|
||||
"%s: Config mismatch: `detect_non_ha_changes` or `adapt_only_on_bare_turn_on` "
|
||||
"set to `true` requires `take_over_control` to be enabled. Adjusting config "
|
||||
"and continuing setup with `take_over_control: true`.",
|
||||
self._name,
|
||||
)
|
||||
self._take_over_control = True
|
||||
self._detect_non_ha_changes = data[CONF_DETECT_NON_HA_CHANGES]
|
||||
self._adapt_only_on_bare_turn_on = data[CONF_ADAPT_ONLY_ON_BARE_TURN_ON]
|
||||
self._auto_reset_manual_control_time = data[CONF_AUTORESET_CONTROL]
|
||||
self._skip_redundant_commands = data[CONF_SKIP_REDUNDANT_COMMANDS]
|
||||
self._multi_light_intercept = data[CONF_MULTI_LIGHT_INTERCEPT]
|
||||
|
|
@ -1446,13 +1450,14 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
|
||||
async def _respond_to_off_to_on_event(self, entity_id: str, event: Event) -> None:
|
||||
assert not self.manager.is_proactively_adapting(event.context.id)
|
||||
from_turn_on = self.manager._off_to_on_state_event_is_from_turn_on(
|
||||
entity_id,
|
||||
event,
|
||||
)
|
||||
if (
|
||||
self._take_over_control
|
||||
and not self._detect_non_ha_changes
|
||||
and not self.manager._off_to_on_state_event_is_from_turn_on(
|
||||
entity_id,
|
||||
event,
|
||||
)
|
||||
and not from_turn_on
|
||||
):
|
||||
# There is an edge case where 2 switches control the same light, e.g.,
|
||||
# one for brightness and one for color. Now we will mark both switches
|
||||
|
|
@ -1468,6 +1473,25 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
self.manager.mark_as_manual_control(entity_id)
|
||||
return
|
||||
|
||||
if (
|
||||
self._take_over_control
|
||||
and self._adapt_only_on_bare_turn_on
|
||||
and from_turn_on
|
||||
):
|
||||
service_data = self.manager.turn_on_event[entity_id].data[ATTR_SERVICE_DATA]
|
||||
if self.manager._mark_manual_control_if_non_bare_turn_on(
|
||||
entity_id,
|
||||
service_data,
|
||||
):
|
||||
_LOGGER.debug(
|
||||
"Skipping responding to 'off' → 'on' event for '%s' with context.id='%s' because"
|
||||
" we only adapt on bare `light.turn_on` events and not on service_data: '%s'",
|
||||
entity_id,
|
||||
event.context.id,
|
||||
service_data,
|
||||
)
|
||||
return
|
||||
|
||||
if self._adapt_delay > 0:
|
||||
await asyncio.sleep(self._adapt_delay)
|
||||
|
||||
|
|
@ -2070,6 +2094,14 @@ class AdaptiveLightingManager:
|
|||
# and of TOGGLE calls when toggling off.
|
||||
or self.hass.states.is_state(entity_id, STATE_ON)
|
||||
or self.manual_control.get(entity_id, False)
|
||||
or (
|
||||
switch._take_over_control
|
||||
and switch._adapt_only_on_bare_turn_on
|
||||
and self._mark_manual_control_if_non_bare_turn_on(
|
||||
entity_id,
|
||||
data[CONF_PARAMS],
|
||||
)
|
||||
)
|
||||
):
|
||||
_LOGGER.debug(
|
||||
"Switch is off or light is already on for entity_id='%s', skipped='%s'"
|
||||
|
|
@ -2622,6 +2654,7 @@ class AdaptiveLightingManager:
|
|||
turn_on_event = self.turn_on_event.get(light)
|
||||
if (
|
||||
turn_on_event is not None
|
||||
and not self.is_proactively_adapting(turn_on_event.context.id)
|
||||
and not is_our_context(turn_on_event.context)
|
||||
and not force
|
||||
):
|
||||
|
|
@ -2855,6 +2888,21 @@ class AdaptiveLightingManager:
|
|||
)
|
||||
return False
|
||||
|
||||
def _mark_manual_control_if_non_bare_turn_on(
|
||||
self,
|
||||
entity_id: str,
|
||||
service_data: ServiceData,
|
||||
) -> bool:
|
||||
_LOGGER.debug(
|
||||
"_mark_manual_control_if_non_bare_turn_on: entity_id='%s', service_data='%s'",
|
||||
entity_id,
|
||||
service_data,
|
||||
)
|
||||
if any(attr in service_data for attr in COLOR_ATTRS | BRIGHTNESS_ATTRS):
|
||||
self.mark_as_manual_control(entity_id)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class _AsyncSingleShotTimer:
|
||||
def __init__(self, delay, callback) -> None:
|
||||
|
|
|
|||
|
|
@ -46,10 +46,11 @@
|
|||
"brightness_mode": "brightness_mode: Brightness mode to use. Possible values are `default`, `linear`, and `tanh` (uses `brightness_mode_time_dark` and `brightness_mode_time_light`). 📈",
|
||||
"brightness_mode_time_dark": "brightness_mode_time_dark: (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness before/after sunrise/sunset. 📈📉",
|
||||
"brightness_mode_time_light": "brightness_mode_time_light: (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness after/before sunrise/sunset. 📈📉.",
|
||||
"only_once": "only_once: Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄",
|
||||
"take_over_control": "take_over_control: Disable Adaptive Lighting if another source calls `light.turn_on` while lights are on and being adapted. Note that this calls `homeassistant.update_entity` every `interval`! 🔒",
|
||||
"detect_non_ha_changes": "detect_non_ha_changes: Detects and halts adaptations for non-`light.turn_on` state changes. Needs `take_over_control` enabled. 🕵️ Caution: ⚠️ Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Disable this feature if you encounter such issues.",
|
||||
"autoreset_control_seconds": "autoreset_control_seconds: Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️",
|
||||
"only_once": "only_once: Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄",
|
||||
"adapt_only_on_bare_turn_on": "adapt_only_on_bare_turn_on: When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is invoked without specifying color or brightness. ❌🌈 This e.g., prevents adaptation when activating a scene. If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. Needs `take_over_control` enabled. 🕵️ ",
|
||||
"separate_turn_on_commands": "separate_turn_on_commands: Use separate `light.turn_on` calls for color and brightness, needed for some light types. 🔀",
|
||||
"send_split_delay": "send_split_delay: Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️",
|
||||
"adapt_delay": "adapt_delay: Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue