Skip to content

Commit

Permalink
Handle IP address changes properly for tplink (#108731)
Browse files Browse the repository at this point in the history
* Update device config for SETUP_RETRY and use CONF_HOST on startup

* Make entry state checks use a constant

Co-authored-by: J. Nick Koston <nick@koston.org>

* Update tests

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
  • Loading branch information
sdb9696 and bdraco authored Jan 24, 2024
1 parent 1cb15a3 commit 393dee1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
2 changes: 2 additions & 0 deletions homeassistant/components/tplink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

if not config:
config = DeviceConfig(host)
else:
config.host = host

config.timeout = CONNECT_TIMEOUT
if config.uses_http is True:
Expand Down
7 changes: 5 additions & 2 deletions homeassistant/components/tplink/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ async def async_step_integration_discovery(
def _update_config_if_entry_in_setup_error(
self, entry: ConfigEntry, host: str, config: dict
) -> None:
"""If discovery encounters a device that is in SETUP_ERROR update the device config."""
if entry.state is not ConfigEntryState.SETUP_ERROR:
"""If discovery encounters a device that is in SETUP_ERROR or SETUP_RETRY update the device config."""
if entry.state not in (
ConfigEntryState.SETUP_ERROR,
ConfigEntryState.SETUP_RETRY,
):
return
entry_data = entry.data
entry_config_dict = entry_data.get(CONF_DEVICE_CONFIG)
Expand Down
53 changes: 53 additions & 0 deletions tests/components/tplink/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
DOMAIN,
AuthenticationException,
Credentials,
DeviceConfig,
SmartDeviceException,
)
from homeassistant.components.tplink.const import CONF_DEVICE_CONFIG
Expand All @@ -36,6 +37,7 @@
MAC_ADDRESS,
MAC_ADDRESS2,
MODULE,
_mocked_bulb,
_patch_connect,
_patch_discovery,
_patch_single_discovery,
Expand Down Expand Up @@ -736,6 +738,57 @@ async def test_discovered_by_dhcp_or_discovery_failed_to_get_device(
assert result["reason"] == "cannot_connect"


async def test_discovery_with_ip_change(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_discovery: AsyncMock,
mock_connect: AsyncMock,
) -> None:
"""Test reauth flow."""
mock_connect["connect"].side_effect = SmartDeviceException()
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state == config_entries.ConfigEntryState.SETUP_RETRY

flows = hass.config_entries.flow.async_progress()
assert len(flows) == 0
assert mock_config_entry.data[CONF_DEVICE_CONFIG] == DEVICE_CONFIG_DICT_LEGACY
assert mock_config_entry.data[CONF_DEVICE_CONFIG].get(CONF_HOST) == "127.0.0.1"

discovery_result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
data={
CONF_HOST: "127.0.0.2",
CONF_MAC: MAC_ADDRESS,
CONF_ALIAS: ALIAS,
CONF_DEVICE_CONFIG: DEVICE_CONFIG_DICT_AUTH,
},
)
await hass.async_block_till_done()
assert discovery_result["type"] is FlowResultType.ABORT
assert discovery_result["reason"] == "already_configured"
assert mock_config_entry.data[CONF_DEVICE_CONFIG] == DEVICE_CONFIG_DICT_AUTH
assert mock_config_entry.data[CONF_HOST] == "127.0.0.2"

config = DeviceConfig.from_dict(DEVICE_CONFIG_DICT_AUTH)

mock_connect["connect"].reset_mock(side_effect=True)
bulb = _mocked_bulb(
device_config=config,
mac=mock_config_entry.unique_id,
)
mock_connect["connect"].return_value = bulb
await hass.config_entries.async_reload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state == config_entries.ConfigEntryState.LOADED
# Check that init set the new host correctly before calling connect
assert config.host == "127.0.0.1"
config.host = "127.0.0.2"
mock_connect["connect"].assert_awaited_once_with(config=config)


async def test_reauth(
hass: HomeAssistant,
mock_added_config_entry: MockConfigEntry,
Expand Down

0 comments on commit 393dee1

Please sign in to comment.