diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index 0a2cd9c3b51..f7a6aecf03b 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -67,6 +67,7 @@ CONF_TRIGGER = "trigger" CONF_CONDITION_TYPE = "condition_type" CONF_INITIAL_STATE = "initial_state" CONF_SKIP_CONDITION = "skip_condition" +CONF_STOP_ACTIONS = "stop_actions" CONDITION_USE_TRIGGER_VALUES = "use_trigger_values" CONDITION_TYPE_AND = "and" @@ -75,6 +76,7 @@ CONDITION_TYPE_OR = "or" DEFAULT_CONDITION_TYPE = CONDITION_TYPE_AND DEFAULT_INITIAL_STATE = True +DEFAULT_STOP_ACTIONS = True EVENT_AUTOMATION_RELOADED = "automation_reloaded" EVENT_AUTOMATION_TRIGGERED = "automation_triggered" @@ -225,7 +227,11 @@ async def async_setup(hass, config): ) component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle") component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on") - component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off") + component.async_register_entity_service( + SERVICE_TURN_OFF, + {vol.Optional(CONF_STOP_ACTIONS, default=DEFAULT_STOP_ACTIONS): cv.boolean}, + "async_turn_off", + ) async def reload_service_handler(service_call): """Remove all automations and load new ones from config.""" @@ -261,6 +267,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity): self._async_detach_triggers = None self._cond_func = cond_func self.action_script = action_script + self.action_script.change_listener = self.async_write_ha_state self._last_triggered = None self._initial_state = initial_state self._is_enabled = False @@ -289,11 +296,10 @@ class AutomationEntity(ToggleEntity, RestoreEntity): attrs = { ATTR_LAST_TRIGGERED: self._last_triggered, ATTR_MODE: self.action_script.script_mode, + ATTR_CUR: self.action_script.runs, } if self.action_script.supports_max: attrs[ATTR_MAX] = self.action_script.max_runs - if self.is_on: - attrs[ATTR_CUR] = self.action_script.runs return attrs @property @@ -388,7 +394,10 @@ class AutomationEntity(ToggleEntity, RestoreEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn the entity off.""" - await self.async_disable() + if CONF_STOP_ACTIONS in kwargs: + await self.async_disable(kwargs[CONF_STOP_ACTIONS]) + else: + await self.async_disable() async def async_trigger(self, variables, skip_condition=False, context=None): """Trigger automation. @@ -456,9 +465,9 @@ class AutomationEntity(ToggleEntity, RestoreEntity): ) self.async_write_ha_state() - async def async_disable(self): + async def async_disable(self, stop_actions=DEFAULT_STOP_ACTIONS): """Disable the automation entity.""" - if not self._is_enabled: + if not self._is_enabled and not self.action_script.runs: return self._is_enabled = False @@ -467,7 +476,8 @@ class AutomationEntity(ToggleEntity, RestoreEntity): self._async_detach_triggers() self._async_detach_triggers = None - await self.action_script.async_stop() + if stop_actions: + await self.action_script.async_stop() self.async_write_ha_state() diff --git a/homeassistant/components/automation/services.yaml b/homeassistant/components/automation/services.yaml index 867dc8e89cd..2f5b0a231e4 100644 --- a/homeassistant/components/automation/services.yaml +++ b/homeassistant/components/automation/services.yaml @@ -12,6 +12,9 @@ turn_off: entity_id: description: Name of the automation to turn off. example: "automation.notify_home" + stop_actions: + description: Stop currently running actions (defaults to true). + example: false toggle: description: Toggle an automation. @@ -27,7 +30,7 @@ trigger: description: Name of the automation to trigger. example: "automation.notify_home" skip_condition: - description: Whether or not the condition will be skipped (defaults to True). + description: Whether or not the condition will be skipped (defaults to true). example: true reload: diff --git a/homeassistant/components/script/__init__.py b/homeassistant/components/script/__init__.py index 95696981cca..e12e2abd312 100644 --- a/homeassistant/components/script/__init__.py +++ b/homeassistant/components/script/__init__.py @@ -278,11 +278,10 @@ class ScriptEntity(ToggleEntity): attrs = { ATTR_LAST_TRIGGERED: self.script.last_triggered, ATTR_MODE: self.script.script_mode, + ATTR_CUR: self.script.runs, } if self.script.supports_max: attrs[ATTR_MAX] = self.script.max_runs - if self.is_on: - attrs[ATTR_CUR] = self.script.runs if self.script.last_action: attrs[ATTR_LAST_ACTION] = self.script.last_action return attrs diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index bdae9a1f326..a832b26d752 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -390,6 +390,17 @@ async def test_services(hass, calls): await hass.async_block_till_done() assert len(calls) == 2 + await common.async_toggle(hass, entity_id) + await hass.async_block_till_done() + + assert not automation.is_on(hass, entity_id) + hass.bus.async_fire("test_event") + await hass.async_block_till_done() + assert len(calls) == 2 + + await common.async_toggle(hass, entity_id) + await hass.async_block_till_done() + await common.async_trigger(hass, entity_id) await hass.async_block_till_done() assert len(calls) == 3 @@ -556,9 +567,9 @@ async def test_reload_config_handles_load_fails(hass, calls): assert len(calls) == 2 -@pytest.mark.parametrize("service", ["turn_off", "reload"]) +@pytest.mark.parametrize("service", ["turn_off_stop", "turn_off_no_stop", "reload"]) async def test_automation_stops(hass, calls, service): - """Test that turning off / reloading an automation stops any running actions.""" + """Test that turning off / reloading stops any running actions as appropriate.""" entity_id = "automation.hello" test_entity = "test.entity" @@ -587,13 +598,20 @@ async def test_automation_stops(hass, calls, service): hass.bus.async_fire("test_event") await running.wait() - if service == "turn_off": + if service == "turn_off_stop": await hass.services.async_call( automation.DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True, ) + elif service == "turn_off_no_stop": + await hass.services.async_call( + automation.DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: entity_id, automation.CONF_STOP_ACTIONS: False}, + blocking=True, + ) else: with patch( "homeassistant.config.load_yaml_config_file", @@ -605,7 +623,7 @@ async def test_automation_stops(hass, calls, service): hass.states.async_set(test_entity, "goodbye") await hass.async_block_till_done() - assert len(calls) == 0 + assert len(calls) == (1 if service == "turn_off_no_stop" else 0) async def test_automation_restore_state(hass):