Before scheduling turn_on do a last-minute check if lights are off (#671)

* Before scheduling turn_on do a last-minute check if lights are off

* Pass force

* add comment

* fix for proactive

* commetn

* No default for force

* rm newline

* no force

* Return bool
This commit is contained in:
Bas Nijholt 2023-08-02 23:11:45 -07:00 committed by GitHub
commit e0e04da0f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 1 deletions

View file

@ -141,6 +141,7 @@ class AdaptationData:
context: Context
sleep_time: float
service_call_datas: AsyncGenerator[ServiceData, None]
force: bool
max_length: int
which: Literal["brightness", "color", "both"]
initial_sleep: bool = False
@ -179,6 +180,7 @@ def prepare_adaptation_data(
service_data: ServiceData,
split: bool,
filter_by_state: bool,
force: bool,
) -> AdaptationData:
"""Prepares a data object carrying all data required to execute an adaptation."""
_LOGGER.debug(
@ -209,6 +211,7 @@ def prepare_adaptation_data(
context=context,
sleep_time=sleep_time,
service_call_datas=service_data_iterator,
force=force,
max_length=service_datas_length,
which=lighting_type,
)

View file

@ -537,6 +537,7 @@ async def async_setup_entry( # noqa: PLR0915
adapt_brightness=data[ATTR_ADAPT_BRIGHTNESS],
adapt_color=data[ATTR_ADAPT_COLOR],
prefer_rgb_color=data[CONF_PREFER_RGB_COLOR],
force=True,
)
@callback
@ -1171,6 +1172,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
adapt_brightness: bool | None = None,
adapt_color: bool | None = None,
prefer_rgb_color: bool | None = None,
force: bool = False,
context: Context | None = None,
) -> AdaptationData | None:
"""Prepare `AdaptationData` for adapting a light."""
@ -1257,6 +1259,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
service_data,
split=self._separate_turn_on_commands,
filter_by_state=self._skip_redundant_commands,
force=force,
)
async def _adapt_light(
@ -1267,6 +1270,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
adapt_brightness: bool | None = None,
adapt_color: bool | None = None,
prefer_rgb_color: bool | None = None,
force: bool = False,
) -> None:
# This should never happen if it's been proactively adapted.
# The context.parent_id is the context.id of the service call that was intercepted
@ -1283,6 +1287,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
adapt_brightness,
adapt_color,
prefer_rgb_color,
force,
context,
)
if data is None:
@ -1308,6 +1313,20 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
# All service datas processed
break
if (
not data.force
and not is_on(self.hass, data.entity_id)
# if proactively adapting, we are sure that it came from a `light.turn_on`
and not self.manager.is_proactively_adapting(data.context.id)
):
# Do a last-minute check if the entity is still on.
_LOGGER.debug(
"%s: Skipping adaptation of %s because it is now off",
self._name,
data.entity_id,
)
return
_LOGGER.debug(
"%s: Scheduling 'light.turn_on' with the following 'service_data': %s"
" with context.id='%s'",
@ -1440,6 +1459,8 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
self._take_over_control
and self._detect_non_ha_changes
and not force
# Note: This call updates the state of the light
# so it might suddenly be off.
and await self.manager.significant_change(
self,
light,
@ -1460,7 +1481,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
transition,
context.id,
)
await self._adapt_light(light, context, transition)
await self._adapt_light(light, context, transition, force=force)
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)

View file

@ -312,6 +312,7 @@ async def test_prepare_adaptation_data(
service_data,
split,
filter_by_state,
force=False,
)
generated_service_datas = [item async for item in data.service_call_datas]

View file

@ -1342,6 +1342,7 @@ async def test_cancellable_service_calls_task(hass):
context,
0,
_create_service_call_data_iterator(hass, [service_data], False),
force=False,
max_length=1,
which="both",
)