Fix apple_tv IP Address not being updated from discovery (#107611)

pull/108275/head
J. Nick Koston 2024-01-17 17:43:14 -10:00 committed by GitHub
parent 2d1c5d84f3
commit cfbfdf7949
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 2 deletions

View File

@ -126,7 +126,7 @@ class AppleTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
@callback
def _entry_unique_id_from_identifers(self, all_identifiers: set[str]) -> str | None:
"""Search existing entries for an identifier and return the unique id."""
for entry in self._async_current_entries():
for entry in self._async_current_entries(include_ignore=True):
if not all_identifiers.isdisjoint(
entry.data.get(CONF_IDENTIFIERS, [entry.unique_id])
):
@ -186,7 +186,6 @@ class AppleTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if discovery_info.ip_address.version == 6:
return self.async_abort(reason="ipv6_not_supported")
host = discovery_info.host
self._async_abort_entries_match({CONF_ADDRESS: host})
service_type = discovery_info.type[:-1] # Remove leading .
name = discovery_info.name.replace(f".{service_type}.", "")
properties = discovery_info.properties
@ -196,6 +195,15 @@ class AppleTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if unique_id is None:
return self.async_abort(reason="unknown")
# The unique id for the zeroconf service may not be
# the same as the unique id for the device. If the
# device is already configured so if we don't
# find a match here, we will fallback to
# looking up the device by all its identifiers
# in the next block.
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured(updates={CONF_ADDRESS: host})
if existing_unique_id := self._entry_unique_id_from_identifers({unique_id}):
await self.async_set_unique_id(existing_unique_id)
self._abort_if_unique_id_configured(updates={CONF_ADDRESS: host})

View File

@ -691,6 +691,44 @@ async def test_zeroconf_ip_change(hass: HomeAssistant, mock_scan) -> None:
assert unrelated_entry.data[CONF_ADDRESS] == "127.0.0.2"
async def test_zeroconf_ip_change_after_ip_conflict_with_ignored_entry(
hass: HomeAssistant, mock_scan
) -> None:
"""Test that the config entry gets updated when the ip changes and reloads."""
entry = MockConfigEntry(
domain="apple_tv", unique_id="mrpid", data={CONF_ADDRESS: "127.0.0.2"}
)
ignored_entry = MockConfigEntry(
domain="apple_tv",
unique_id="unrelated",
data={CONF_ADDRESS: "127.0.0.2"},
source=config_entries.SOURCE_IGNORE,
)
ignored_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) == 1
assert entry.data[CONF_ADDRESS] == "127.0.0.1"
assert ignored_entry.data[CONF_ADDRESS] == "127.0.0.2"
async def test_zeroconf_ip_change_via_secondary_identifier(
hass: HomeAssistant, mock_scan
) -> None: