Handle IP address changes properly for tplink (#108731)

* 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>
This commit is contained in:
Steven B 2024-01-24 10:24:44 +00:00 committed by GitHub
parent 1cb15a398c
commit 393dee1524
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 60 additions and 2 deletions

View file

@ -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:

View file

@ -78,8 +78,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
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)

View file

@ -10,6 +10,7 @@ from homeassistant.components.tplink import (
DOMAIN,
AuthenticationException,
Credentials,
DeviceConfig,
SmartDeviceException,
)
from homeassistant.components.tplink.const import CONF_DEVICE_CONFIG
@ -36,6 +37,7 @@ from . import (
MAC_ADDRESS,
MAC_ADDRESS2,
MODULE,
_mocked_bulb,
_patch_connect,
_patch_discovery,
_patch_single_discovery,
@ -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,