Ensure automations do not execute from a trigger if they are disabled (#115305)

* Ensure automations are stopped as soon as the stop future is set

* revert script changes and move them to #115325
This commit is contained in:
J. Nick Koston 2024-04-10 02:42:18 -10:00 committed by GitHub
parent f80894d56f
commit 63545ceaa4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 97 additions and 1 deletions

View file

@ -795,6 +795,22 @@ class AutomationEntity(BaseAutomationEntity, RestoreEntity):
"""Log helper callback."""
self._logger.log(level, "%s %s", msg, self.name, **kwargs)
async def _async_trigger_if_enabled(
self,
run_variables: dict[str, Any],
context: Context | None = None,
skip_condition: bool = False,
) -> ScriptRunResult | None:
"""Trigger automation if enabled.
If the trigger starts but has a delay, the automation will be triggered
when the delay has passed so we need to make sure its still enabled before
executing the action.
"""
if not self._is_enabled:
return None
return await self.async_trigger(run_variables, context, skip_condition)
async def _async_attach_triggers(
self, home_assistant_start: bool
) -> Callable[[], None] | None:
@ -818,7 +834,7 @@ class AutomationEntity(BaseAutomationEntity, RestoreEntity):
return await async_initialize_triggers(
self.hass,
self._trigger_config,
self.async_trigger,
self._async_trigger_if_enabled,
DOMAIN,
str(self.name),
self._log_callback,

View file

@ -2651,3 +2651,83 @@ def test_deprecated_constants(
import_and_test_deprecated_constant(
caplog, automation, constant_name, replacement.__name__, replacement, "2025.1"
)
async def test_automation_turns_off_other_automation(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test an automation that turns off another automation."""
hass.set_state(CoreState.not_running)
calls = async_mock_service(hass, "persistent_notification", "create")
hass.states.async_set("binary_sensor.presence", "on")
await hass.async_block_till_done()
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "state",
"entity_id": "binary_sensor.presence",
"from": "on",
},
"action": {
"service": "automation.turn_off",
"target": {
"entity_id": "automation.automation_1",
},
"data": {
"stop_actions": True,
},
},
"id": "automation_0",
"mode": "single",
},
{
"trigger": {
"platform": "state",
"entity_id": "binary_sensor.presence",
"from": "on",
"for": {
"hours": 0,
"minutes": 0,
"seconds": 5,
},
},
"action": {
"service": "persistent_notification.create",
"metadata": {},
"data": {
"message": "Test race",
},
},
"id": "automation_1",
"mode": "single",
},
]
},
)
await hass.async_start()
await hass.async_block_till_done()
hass.states.async_set("binary_sensor.presence", "off")
await hass.async_block_till_done()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=5))
await hass.async_block_till_done()
assert len(calls) == 0
await hass.services.async_call(
"automation",
"turn_on",
{"entity_id": "automation.automation_1"},
blocking=True,
)
hass.states.async_set("binary_sensor.presence", "off")
await hass.async_block_till_done()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=5))
await hass.async_block_till_done()
assert len(calls) == 0