Add dim-only brightness adaptation

This commit is contained in:
Bas Nijholt 2026-09-06 09:29:32 -07:00
commit 3c10d827c2
11 changed files with 378 additions and 93 deletions

View file

@ -169,11 +169,21 @@ def _remove_brightness_increases(
service_data: ServiceData,
state: State,
) -> ServiceData:
"""Filter service data by removing brightness increases."""
"""Filter brightness targets above the light's reported numeric value."""
current_brightness = state.attributes.get(ATTR_BRIGHTNESS)
if not isinstance(current_brightness, (int, float)) or isinstance(
current_brightness,
bool,
):
return dict(service_data)
return {
k: v
for k, v in service_data.items()
if k != ATTR_BRIGHTNESS or k not in state.attributes or v <= state.attributes[k]
if k != ATTR_BRIGHTNESS
or not isinstance(v, (int, float))
or isinstance(v, bool)
or v <= current_brightness
}
@ -192,7 +202,7 @@ async def _create_service_call_data_iterator(
hass: HomeAssistant,
service_datas: list[ServiceData],
filter_by_state: bool,
skip_brightness_increases: bool,
skip_brightness_increases: bool = False,
) -> AsyncGenerator[ServiceData]:
"""Enumerates and filters a list of service datas on the fly.
@ -296,7 +306,7 @@ def prepare_adaptation_data(
split: bool,
filter_by_state: bool,
force: bool,
skip_brightness_increases: bool,
skip_brightness_increases: bool = False,
already_applied: LightControlAttributes = LightControlAttributes.NONE,
) -> AdaptationData:
"""Prepares a data object carrying all data required to execute an adaptation."""

View file

@ -268,10 +268,13 @@ CONF_SKIP_BRIGHTNESS_INCREASES, DEFAULT_SKIP_BRIGHTNESS_INCREASES = (
False,
)
DOCS[CONF_SKIP_BRIGHTNESS_INCREASES] = (
"Skip sending adaptation commands when the target brightness "
"is greater than the current entity brightness. Will "
"result in lights which have been manually dimmed "
"not increasing in brightness."
"Prevent automatic adaptation from increasing brightness above the light's "
"reported numeric brightness, while still adapting to lower brightness targets "
"and adapting color. A retained brightness on an off light is also used as the "
"ceiling. If brightness is missing or non-numeric, the calculated target is used. "
"Bare turn-on and leaving sleep mode may therefore keep a light dim until you "
"request a brighter level directly or disable this option. This option does not "
"override manual-control pauses."
)
CONF_INTERCEPT, DEFAULT_INTERCEPT = "intercept", True

View file

@ -250,6 +250,12 @@ change_switch_settings:
example: 0
selector:
text: null
skip_brightness_increases:
description: Prevent automatic adaptation from increasing brightness above the light's reported numeric brightness, while still adapting to lower brightness targets and adapting color. A retained brightness on an off light is also used as the ceiling. If brightness is missing or non-numeric, the calculated target is used. Bare turn-on and leaving sleep mode may therefore keep a light dim until you request a brighter level directly or disable this option. This option does not override manual-control pauses.
required: false
example: false
selector:
boolean: null
autoreset_control_seconds:
description: Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️
required: false

View file

@ -75,6 +75,7 @@
"send_split_delay": "send_split_delay",
"adapt_delay": "adapt_delay",
"skip_redundant_commands": "skip_redundant_commands: Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state.",
"skip_brightness_increases": "skip_brightness_increases: Prevent automatic adaptation from increasing brightness above the light's reported numeric brightness, while still adapting to lower brightness targets and adapting color. A retained brightness on an off light is also used as the ceiling. If brightness is missing or non-numeric, the calculated target is used. Bare turn-on and leaving sleep mode may therefore keep a light dim until you request a brighter level directly or disable this option. This option does not override manual-control pauses.",
"intercept": "intercept: Intercept and adapt `light.turn_on` calls to enabling instantaneous color and brightness adaptation. 🏎️ Disable for lights that do not support `light.turn_on` with color and brightness.",
"multi_light_intercept": "multi_light_intercept: Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches. Requires `intercept` to be enabled.",
"include_config_in_attributes": "include_config_in_attributes: Show all options as attributes on the switch in Home Assistant when set to `true`. 📝"
@ -278,6 +279,10 @@
"description": "Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️",
"name": "adapt_delay"
},
"skip_brightness_increases": {
"description": "Prevent automatic adaptation from increasing brightness above the light's reported numeric brightness, while still adapting to lower brightness targets and adapting color. A retained brightness on an off light is also used as the ceiling. If brightness is missing or non-numeric, the calculated target is used. Bare turn-on and leaving sleep mode may therefore keep a light dim until you request a brighter level directly or disable this option. This option does not override manual-control pauses.",
"name": "skip_brightness_increases"
},
"autoreset_control_seconds": {
"description": "Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️",
"name": "autoreset_control_seconds"

View file

@ -76,6 +76,7 @@
"send_split_delay": "send_split_delay",
"adapt_delay": "adapt_delay",
"skip_redundant_commands": "skip_redundant_commands: Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state.",
"skip_brightness_increases": "skip_brightness_increases: Prevent automatic adaptation from increasing brightness above the light's reported numeric brightness, while still adapting to lower brightness targets and adapting color. A retained brightness on an off light is also used as the ceiling. If brightness is missing or non-numeric, the calculated target is used. Bare turn-on and leaving sleep mode may therefore keep a light dim until you request a brighter level directly or disable this option. This option does not override manual-control pauses.",
"intercept": "intercept: Intercept and adapt `light.turn_on` calls to enabling instantaneous color and brightness adaptation. 🏎️ Disable for lights that do not support `light.turn_on` with color and brightness.",
"multi_light_intercept": "multi_light_intercept: Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches. Requires `intercept` to be enabled.",
"include_config_in_attributes": "include_config_in_attributes: Show all options as attributes on the switch in Home Assistant when set to `true`. 📝"
@ -279,6 +280,10 @@
"description": "Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️",
"name": "adapt_delay"
},
"skip_brightness_increases": {
"description": "Prevent automatic adaptation from increasing brightness above the light's reported numeric brightness, while still adapting to lower brightness targets and adapting color. A retained brightness on an off light is also used as the ceiling. If brightness is missing or non-numeric, the calculated target is used. Bare turn-on and leaving sleep mode may therefore keep a light dim until you request a brighter level directly or disable this option. This option does not override manual-control pauses.",
"name": "skip_brightness_increases"
},
"autoreset_control_seconds": {
"description": "Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️",
"name": "autoreset_control_seconds"