diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index 234fcc97839..9581a6b1c40 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -817,9 +817,28 @@ async def _async_process_config( """ automation_matches: set[int] = set() config_matches: set[int] = set() + automation_configs_with_id: dict[str, tuple[int, AutomationEntityConfig]] = {} + automation_configs_without_id: list[tuple[int, AutomationEntityConfig]] = [] + + for config_idx, config in enumerate(automation_configs): + if automation_id := config.config_block.get(CONF_ID): + automation_configs_with_id[automation_id] = (config_idx, config) + continue + automation_configs_without_id.append((config_idx, config)) for automation_idx, automation in enumerate(automations): - for config_idx, config in enumerate(automation_configs): + if automation.unique_id: + if automation.unique_id not in automation_configs_with_id: + continue + config_idx, config = automation_configs_with_id.pop( + automation.unique_id + ) + if automation_matches_config(automation, config): + automation_matches.add(automation_idx) + config_matches.add(config_idx) + continue + + for config_idx, config in automation_configs_without_id: if config_idx in config_matches: # Only allow an automation config to match at most once continue diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index f40309bf7f6..742ae85ed68 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -738,7 +738,8 @@ async def test_automation_stops(hass, calls, service): assert len(calls) == (1 if service == "turn_off_no_stop" else 0) -async def test_reload_unchanged_does_not_stop(hass, calls): +@pytest.mark.parametrize("extra_config", ({}, {"id": "sun"})) +async def test_reload_unchanged_does_not_stop(hass, calls, extra_config): """Test that reloading stops any running actions as appropriate.""" test_entity = "test.entity" @@ -753,6 +754,7 @@ async def test_reload_unchanged_does_not_stop(hass, calls): ], } } + config[automation.DOMAIN].update(**extra_config) assert await async_setup_component(hass, automation.DOMAIN, config) running = asyncio.Event() @@ -970,6 +972,41 @@ async def test_reload_identical_automations_without_id(hass, calls): }, } }, + { + "id": "sun", + "trigger": {"platform": "event", "event_type": "test_event"}, + "action": [{"service": "test.automation"}], + }, + # An automation using templates + { + "id": "sun", + "trigger": {"platform": "event", "event_type": "test_event"}, + "action": [{"service": "{{ 'test.automation' }}"}], + }, + # An automation using blueprint + { + "id": "sun", + "use_blueprint": { + "path": "test_event_service.yaml", + "input": { + "trigger_event": "test_event", + "service_to_call": "test.automation", + "a_number": 5, + }, + }, + }, + # An automation using blueprint with templated input + { + "id": "sun", + "use_blueprint": { + "path": "test_event_service.yaml", + "input": { + "trigger_event": "{{ 'test_event' }}", + "service_to_call": "{{ 'test.automation' }}", + "a_number": 5, + }, + }, + }, ), ) async def test_reload_unchanged_automation(hass, calls, automation_config): @@ -1004,7 +1041,8 @@ async def test_reload_unchanged_automation(hass, calls, automation_config): assert len(calls) == 2 -async def test_reload_automation_when_blueprint_changes(hass, calls): +@pytest.mark.parametrize("extra_config", ({}, {"id": "sun"})) +async def test_reload_automation_when_blueprint_changes(hass, calls, extra_config): """Test an automation is updated at reload if the blueprint has changed.""" with patch( "homeassistant.components.automation.AutomationEntity", wraps=AutomationEntity @@ -1023,6 +1061,7 @@ async def test_reload_automation_when_blueprint_changes(hass, calls): } ] } + config[automation.DOMAIN][0].update(**extra_config) assert await async_setup_component(hass, automation.DOMAIN, config) assert automation_entity_init.call_count == 1 automation_entity_init.reset_mock()