diff --git a/homeassistant/components/apple_tv/config_flow.py b/homeassistant/components/apple_tv/config_flow.py index d000c0346af..9b80d992cdd 100644 --- a/homeassistant/components/apple_tv/config_flow.py +++ b/homeassistant/components/apple_tv/config_flow.py @@ -324,18 +324,29 @@ class AppleTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): all_identifiers = set(self.atv.all_identifiers) discovered_ip_address = str(self.atv.address) for entry in self._async_current_entries(): - if not all_identifiers.intersection( + existing_identifiers = set( entry.data.get(CONF_IDENTIFIERS, [entry.unique_id]) - ): + ) + if not all_identifiers.intersection(existing_identifiers): continue - if entry.data.get(CONF_ADDRESS) != discovered_ip_address: + combined_identifiers = existing_identifiers | all_identifiers + if entry.data.get( + CONF_ADDRESS + ) != discovered_ip_address or combined_identifiers != set( + entry.data.get(CONF_IDENTIFIERS, []) + ): self.hass.config_entries.async_update_entry( entry, - data={**entry.data, CONF_ADDRESS: discovered_ip_address}, - ) - self.hass.async_create_task( - self.hass.config_entries.async_reload(entry.entry_id) + data={ + **entry.data, + CONF_ADDRESS: discovered_ip_address, + CONF_IDENTIFIERS: list(combined_identifiers), + }, ) + if entry.source != config_entries.SOURCE_IGNORE: + self.hass.async_create_task( + self.hass.config_entries.async_reload(entry.entry_id) + ) if not allow_exist: raise DeviceAlreadyConfigured() diff --git a/tests/components/apple_tv/test_config_flow.py b/tests/components/apple_tv/test_config_flow.py index 52388e694f5..6256d1dde9c 100644 --- a/tests/components/apple_tv/test_config_flow.py +++ b/tests/components/apple_tv/test_config_flow.py @@ -730,6 +730,52 @@ async def test_zeroconf_ip_change_via_secondary_identifier( assert len(mock_async_setup.mock_calls) == 2 assert entry.data[CONF_ADDRESS] == "127.0.0.1" assert unrelated_entry.data[CONF_ADDRESS] == "127.0.0.2" + assert set(entry.data[CONF_IDENTIFIERS]) == {"airplayid", "mrpid"} + + +async def test_zeroconf_updates_identifiers_for_ignored_entries( + hass: HomeAssistant, mock_scan +) -> None: + """Test that an ignored config entry gets updated when the ip changes. + + Instead of checking only the unique id, all the identifiers + in the config entry are checked + """ + entry = MockConfigEntry( + domain="apple_tv", + unique_id="aa:bb:cc:dd:ee:ff", + source=config_entries.SOURCE_IGNORE, + data={CONF_IDENTIFIERS: ["mrpid"], CONF_ADDRESS: "127.0.0.2"}, + ) + unrelated_entry = MockConfigEntry( + domain="apple_tv", unique_id="unrelated", data={CONF_ADDRESS: "127.0.0.2"} + ) + unrelated_entry.add_to_hass(hass) + entry.add_to_hass(hass) + mock_scan.result = [ + create_conf( + IPv4Address("127.0.0.1"), "Device", mrp_service(), airplay_service() + ) + ] + + with patch( + "homeassistant.components.apple_tv.async_setup_entry", return_value=True + ) as mock_async_setup: + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_ZEROCONF}, + data=DMAP_SERVICE, + ) + await hass.async_block_till_done() + + assert result["type"] == data_entry_flow.FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert ( + len(mock_async_setup.mock_calls) == 0 + ) # Should not be called because entry is ignored + assert entry.data[CONF_ADDRESS] == "127.0.0.1" + assert unrelated_entry.data[CONF_ADDRESS] == "127.0.0.2" + assert set(entry.data[CONF_IDENTIFIERS]) == {"airplayid", "mrpid"} async def test_zeroconf_add_existing_aborts(hass: HomeAssistant, dmap_device) -> None: