Retry tplink setup later if device has an unexpected mac address (#98784)

Retry tplink setup later if device has an unexpected serial

If the DHCP reservation changed and there is now a different tplink device at
the saved IP address, retry setup later to avoid cross linking devices
pull/99145/head
J. Nick Koston 2023-08-27 12:00:39 -05:00 committed by GitHub
parent d21ee30ddf
commit d17ffff3e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 1 deletions

View File

@ -85,11 +85,23 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up TPLink from a config entry.""" """Set up TPLink from a config entry."""
host = entry.data[CONF_HOST]
try: try:
device: SmartDevice = await Discover.discover_single(entry.data[CONF_HOST]) device: SmartDevice = await Discover.discover_single(host)
except SmartDeviceException as ex: except SmartDeviceException as ex:
raise ConfigEntryNotReady from ex raise ConfigEntryNotReady from ex
found_mac = dr.format_mac(device.mac)
if found_mac != entry.unique_id:
# If the mac address of the device does not match the unique_id
# of the config entry, it likely means the DHCP lease has expired
# and the device has been assigned a new IP address. We need to
# wait for the next discovery to find the device at its new address
# and update the config entry so we do not mix up devices.
raise ConfigEntryNotReady(
f"Unexpected device found at {host}; expected {entry.unique_id}, found {found_mac}"
)
hass.data[DOMAIN][entry.entry_id] = TPLinkDataUpdateCoordinator(hass, device) hass.data[DOMAIN][entry.entry_id] = TPLinkDataUpdateCoordinator(hass, device)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

View File

@ -4,6 +4,8 @@ from __future__ import annotations
from datetime import timedelta from datetime import timedelta
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import pytest
from homeassistant import setup from homeassistant import setup
from homeassistant.components import tplink from homeassistant.components import tplink
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
@ -111,3 +113,23 @@ async def test_dimmer_switch_unique_id_fix_original_entity_still_exists(
) )
assert migrated_dimmer_entity_reg.entity_id == original_dimmer_entity_reg.entity_id assert migrated_dimmer_entity_reg.entity_id == original_dimmer_entity_reg.entity_id
assert migrated_dimmer_entity_reg.entity_id != rollout_dimmer_entity_reg.entity_id assert migrated_dimmer_entity_reg.entity_id != rollout_dimmer_entity_reg.entity_id
async def test_config_entry_wrong_mac_Address(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test config entry enters setup retry when mac address mismatches."""
mismatched_mac = f"{MAC_ADDRESS[:-1]}0"
already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=mismatched_mac
)
already_migrated_config_entry.add_to_hass(hass)
with _patch_discovery(), _patch_single_discovery():
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
await hass.async_block_till_done()
assert already_migrated_config_entry.state == ConfigEntryState.SETUP_RETRY
assert (
"Unexpected device found at 127.0.0.1; expected aa:bb:cc:dd:ee:f0, found aa:bb:cc:dd:ee:ff"
in caplog.text
)