mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 08:47:10 +00:00
Handle missing or incorrect device name and unique id for ESPHome during manual add (#95678)
* Handle incorrect or missing device name for ESPHome noise encryption If we did not have the device name during setup we could never get the key from the dashboard. The device will send us its name if we try encryption which allows us to find the right key from the dashboard. This should help get users unstuck when they change the key and cannot get the device back online after deleting and trying to set it up again manually * bump lib to get name * tweak * reduce number of connections * less connections when we know we will fail * coverage shows it works but it does not * add more coverage * fix test * bump again
This commit is contained in:
parent
79a122e1e5
commit
f0cb03e631
@ -40,6 +40,8 @@ ERROR_INVALID_ENCRYPTION_KEY = "invalid_psk"
|
|||||||
ESPHOME_URL = "https://esphome.io/"
|
ESPHOME_URL = "https://esphome.io/"
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ZERO_NOISE_PSK = "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA="
|
||||||
|
|
||||||
|
|
||||||
class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||||
"""Handle a esphome config flow."""
|
"""Handle a esphome config flow."""
|
||||||
@ -149,11 +151,22 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
async def _async_try_fetch_device_info(self) -> FlowResult:
|
async def _async_try_fetch_device_info(self) -> FlowResult:
|
||||||
error = await self.fetch_device_info()
|
error = await self.fetch_device_info()
|
||||||
|
|
||||||
if (
|
if error == ERROR_REQUIRES_ENCRYPTION_KEY:
|
||||||
error == ERROR_REQUIRES_ENCRYPTION_KEY
|
if not self._device_name and not self._noise_psk:
|
||||||
and await self._retrieve_encryption_key_from_dashboard()
|
# If device name is not set we can send a zero noise psk
|
||||||
):
|
# to get the device name which will allow us to populate
|
||||||
error = await self.fetch_device_info()
|
# the device name and hopefully get the encryption key
|
||||||
|
# from the dashboard.
|
||||||
|
self._noise_psk = ZERO_NOISE_PSK
|
||||||
|
error = await self.fetch_device_info()
|
||||||
|
self._noise_psk = None
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._device_name
|
||||||
|
and await self._retrieve_encryption_key_from_dashboard()
|
||||||
|
):
|
||||||
|
error = await self.fetch_device_info()
|
||||||
|
|
||||||
# If the fetched key is invalid, unset it again.
|
# If the fetched key is invalid, unset it again.
|
||||||
if error == ERROR_INVALID_ENCRYPTION_KEY:
|
if error == ERROR_INVALID_ENCRYPTION_KEY:
|
||||||
self._noise_psk = None
|
self._noise_psk = None
|
||||||
@ -323,7 +336,10 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
self._device_info = await cli.device_info()
|
self._device_info = await cli.device_info()
|
||||||
except RequiresEncryptionAPIError:
|
except RequiresEncryptionAPIError:
|
||||||
return ERROR_REQUIRES_ENCRYPTION_KEY
|
return ERROR_REQUIRES_ENCRYPTION_KEY
|
||||||
except InvalidEncryptionKeyAPIError:
|
except InvalidEncryptionKeyAPIError as ex:
|
||||||
|
if ex.received_name:
|
||||||
|
self._device_name = ex.received_name
|
||||||
|
self._name = ex.received_name
|
||||||
return ERROR_INVALID_ENCRYPTION_KEY
|
return ERROR_INVALID_ENCRYPTION_KEY
|
||||||
except ResolveAPIError:
|
except ResolveAPIError:
|
||||||
return "resolve_error"
|
return "resolve_error"
|
||||||
@ -334,9 +350,8 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
self._name = self._device_info.friendly_name or self._device_info.name
|
self._name = self._device_info.friendly_name or self._device_info.name
|
||||||
self._device_name = self._device_info.name
|
self._device_name = self._device_info.name
|
||||||
await self.async_set_unique_id(
|
mac_address = format_mac(self._device_info.mac_address)
|
||||||
self._device_info.mac_address, raise_on_progress=False
|
await self.async_set_unique_id(mac_address, raise_on_progress=False)
|
||||||
)
|
|
||||||
if not self._reauth_entry:
|
if not self._reauth_entry:
|
||||||
self._abort_if_unique_id_configured(
|
self._abort_if_unique_id_configured(
|
||||||
updates={CONF_HOST: self._host, CONF_PORT: self._port}
|
updates={CONF_HOST: self._host, CONF_PORT: self._port}
|
||||||
@ -373,14 +388,13 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
Return boolean if a key was retrieved.
|
Return boolean if a key was retrieved.
|
||||||
"""
|
"""
|
||||||
if self._device_name is None:
|
if (
|
||||||
return False
|
self._device_name is None
|
||||||
|
or (dashboard := async_get_dashboard(self.hass)) is None
|
||||||
if (dashboard := async_get_dashboard(self.hass)) is None:
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
await dashboard.async_request_refresh()
|
await dashboard.async_request_refresh()
|
||||||
|
|
||||||
if not dashboard.last_update_success:
|
if not dashboard.last_update_success:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["aioesphomeapi", "noiseprotocol"],
|
"loggers": ["aioesphomeapi", "noiseprotocol"],
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aioesphomeapi==15.0.1",
|
"aioesphomeapi==15.1.1",
|
||||||
"bluetooth-data-tools==1.3.0",
|
"bluetooth-data-tools==1.3.0",
|
||||||
"esphome-dashboard-api==1.2.3"
|
"esphome-dashboard-api==1.2.3"
|
||||||
],
|
],
|
||||||
|
@ -234,7 +234,7 @@ aioecowitt==2023.5.0
|
|||||||
aioemonitor==1.0.5
|
aioemonitor==1.0.5
|
||||||
|
|
||||||
# homeassistant.components.esphome
|
# homeassistant.components.esphome
|
||||||
aioesphomeapi==15.0.1
|
aioesphomeapi==15.1.1
|
||||||
|
|
||||||
# homeassistant.components.flo
|
# homeassistant.components.flo
|
||||||
aioflo==2021.11.0
|
aioflo==2021.11.0
|
||||||
|
@ -212,7 +212,7 @@ aioecowitt==2023.5.0
|
|||||||
aioemonitor==1.0.5
|
aioemonitor==1.0.5
|
||||||
|
|
||||||
# homeassistant.components.esphome
|
# homeassistant.components.esphome
|
||||||
aioesphomeapi==15.0.1
|
aioesphomeapi==15.1.1
|
||||||
|
|
||||||
# homeassistant.components.flo
|
# homeassistant.components.flo
|
||||||
aioflo==2021.11.0
|
aioflo==2021.11.0
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"""Test config flow."""
|
"""Test config flow."""
|
||||||
|
import asyncio
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
from aioesphomeapi import (
|
from aioesphomeapi import (
|
||||||
@ -10,6 +11,7 @@ from aioesphomeapi import (
|
|||||||
RequiresEncryptionAPIError,
|
RequiresEncryptionAPIError,
|
||||||
ResolveAPIError,
|
ResolveAPIError,
|
||||||
)
|
)
|
||||||
|
import aiohttp
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import config_entries, data_entry_flow
|
from homeassistant import config_entries, data_entry_flow
|
||||||
@ -35,6 +37,7 @@ from . import VALID_NOISE_PSK
|
|||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
INVALID_NOISE_PSK = "lSYBYEjQI1bVL8s2Vask4YytGMj1f1epNtmoim2yuTM="
|
INVALID_NOISE_PSK = "lSYBYEjQI1bVL8s2Vask4YytGMj1f1epNtmoim2yuTM="
|
||||||
|
WRONG_NOISE_PSK = "GP+ciK+nVfTQ/gcz6uOdS+oKEdJgesU+jeu8Ssj2how="
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=False)
|
@pytest.fixture(autouse=False)
|
||||||
@ -115,6 +118,58 @@ async def test_user_connection_updates_host(
|
|||||||
assert entry.data[CONF_HOST] == "127.0.0.1"
|
assert entry.data[CONF_HOST] == "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_sets_unique_id(
|
||||||
|
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
||||||
|
) -> None:
|
||||||
|
"""Test that the user flow sets the unique id."""
|
||||||
|
service_info = zeroconf.ZeroconfServiceInfo(
|
||||||
|
host="192.168.43.183",
|
||||||
|
addresses=["192.168.43.183"],
|
||||||
|
hostname="test8266.local.",
|
||||||
|
name="mock_name",
|
||||||
|
port=6053,
|
||||||
|
properties={
|
||||||
|
"mac": "1122334455aa",
|
||||||
|
},
|
||||||
|
type="mock_type",
|
||||||
|
)
|
||||||
|
discovery_result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome", context={"source": config_entries.SOURCE_ZEROCONF}, data=service_info
|
||||||
|
)
|
||||||
|
|
||||||
|
assert discovery_result["type"] == FlowResultType.FORM
|
||||||
|
assert discovery_result["step_id"] == "discovery_confirm"
|
||||||
|
|
||||||
|
discovery_result = await hass.config_entries.flow.async_configure(
|
||||||
|
discovery_result["flow_id"],
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
assert discovery_result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert discovery_result["data"] == {
|
||||||
|
CONF_HOST: "192.168.43.183",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: "",
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
assert result["type"] == FlowResultType.ABORT
|
||||||
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
async def test_user_resolve_error(
|
async def test_user_resolve_error(
|
||||||
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -140,6 +195,53 @@ async def test_user_resolve_error(
|
|||||||
assert len(mock_client.disconnect.mock_calls) == 1
|
assert len(mock_client.disconnect.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_causes_zeroconf_to_abort(
|
||||||
|
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
||||||
|
) -> None:
|
||||||
|
"""Test that the user flow sets the unique id and aborts the zeroconf flow."""
|
||||||
|
service_info = zeroconf.ZeroconfServiceInfo(
|
||||||
|
host="192.168.43.183",
|
||||||
|
addresses=["192.168.43.183"],
|
||||||
|
hostname="test8266.local.",
|
||||||
|
name="mock_name",
|
||||||
|
port=6053,
|
||||||
|
properties={
|
||||||
|
"mac": "1122334455aa",
|
||||||
|
},
|
||||||
|
type="mock_type",
|
||||||
|
)
|
||||||
|
discovery_result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome", context={"source": config_entries.SOURCE_ZEROCONF}, data=service_info
|
||||||
|
)
|
||||||
|
|
||||||
|
assert discovery_result["type"] == FlowResultType.FORM
|
||||||
|
assert discovery_result["step_id"] == "discovery_confirm"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: "",
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert not hass.config_entries.flow.async_progress_by_handler(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
async def test_user_connection_error(
|
async def test_user_connection_error(
|
||||||
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -217,6 +319,211 @@ async def test_user_invalid_password(
|
|||||||
assert result["errors"] == {"base": "invalid_auth"}
|
assert result["errors"] == {"base": "invalid_auth"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_dashboard_has_wrong_key(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_client,
|
||||||
|
mock_dashboard,
|
||||||
|
mock_zeroconf: None,
|
||||||
|
mock_setup_entry: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test user step with key from dashboard that is incorrect."""
|
||||||
|
mock_client.device_info.side_effect = [
|
||||||
|
RequiresEncryptionAPIError,
|
||||||
|
InvalidEncryptionKeyAPIError,
|
||||||
|
DeviceInfo(
|
||||||
|
uses_password=False,
|
||||||
|
name="test",
|
||||||
|
mac_address="11:22:33:44:55:AA",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.esphome.dashboard.ESPHomeDashboardAPI.get_encryption_key",
|
||||||
|
return_value=WRONG_NOISE_PSK,
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data={CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "encryption_key"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_NOISE_PSK: VALID_NOISE_PSK}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: VALID_NOISE_PSK,
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
assert mock_client.noise_psk == VALID_NOISE_PSK
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_discovers_name_and_gets_key_from_dashboard(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_client,
|
||||||
|
mock_dashboard,
|
||||||
|
mock_zeroconf: None,
|
||||||
|
mock_setup_entry: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test user step can discover the name and get the key from the dashboard."""
|
||||||
|
mock_client.device_info.side_effect = [
|
||||||
|
RequiresEncryptionAPIError,
|
||||||
|
InvalidEncryptionKeyAPIError("Wrong key", "test"),
|
||||||
|
DeviceInfo(
|
||||||
|
uses_password=False,
|
||||||
|
name="test",
|
||||||
|
mac_address="11:22:33:44:55:AA",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_dashboard["configured"].append(
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"configuration": "test.yaml",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await dashboard.async_get_dashboard(hass).async_refresh()
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.esphome.dashboard.ESPHomeDashboardAPI.get_encryption_key",
|
||||||
|
return_value=VALID_NOISE_PSK,
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data={CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: VALID_NOISE_PSK,
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
assert mock_client.noise_psk == VALID_NOISE_PSK
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_discovers_name_and_gets_key_from_dashboard_fails(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_client,
|
||||||
|
mock_dashboard,
|
||||||
|
mock_zeroconf: None,
|
||||||
|
mock_setup_entry: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test user step can discover the name and get the key from the dashboard."""
|
||||||
|
mock_client.device_info.side_effect = [
|
||||||
|
RequiresEncryptionAPIError,
|
||||||
|
InvalidEncryptionKeyAPIError("Wrong key", "test"),
|
||||||
|
DeviceInfo(
|
||||||
|
uses_password=False,
|
||||||
|
name="test",
|
||||||
|
mac_address="11:22:33:44:55:aa",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_dashboard["configured"].append(
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"configuration": "test.yaml",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await dashboard.async_get_dashboard(hass).async_refresh()
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.esphome.dashboard.ESPHomeDashboardAPI.get_encryption_key",
|
||||||
|
side_effect=aiohttp.ClientError,
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data={CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "encryption_key"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_NOISE_PSK: VALID_NOISE_PSK}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: VALID_NOISE_PSK,
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
assert mock_client.noise_psk == VALID_NOISE_PSK
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_discovers_name_and_dashboard_is_unavailable(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_client,
|
||||||
|
mock_dashboard,
|
||||||
|
mock_zeroconf: None,
|
||||||
|
mock_setup_entry: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test user step can discover the name but the dashboard is unavailable."""
|
||||||
|
mock_client.device_info.side_effect = [
|
||||||
|
RequiresEncryptionAPIError,
|
||||||
|
InvalidEncryptionKeyAPIError("Wrong key", "test"),
|
||||||
|
DeviceInfo(
|
||||||
|
uses_password=False,
|
||||||
|
name="test",
|
||||||
|
mac_address="11:22:33:44:55:AA",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_dashboard["configured"].append(
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"configuration": "test.yaml",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"esphome_dashboard_api.ESPHomeDashboardAPI.get_devices",
|
||||||
|
side_effect=asyncio.TimeoutError,
|
||||||
|
):
|
||||||
|
await dashboard.async_get_dashboard(hass).async_refresh()
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
"esphome",
|
||||||
|
context={"source": config_entries.SOURCE_USER},
|
||||||
|
data={CONF_HOST: "127.0.0.1", CONF_PORT: 6053},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "encryption_key"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_NOISE_PSK: VALID_NOISE_PSK}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_PORT: 6053,
|
||||||
|
CONF_PASSWORD: "",
|
||||||
|
CONF_NOISE_PSK: VALID_NOISE_PSK,
|
||||||
|
CONF_DEVICE_NAME: "test",
|
||||||
|
}
|
||||||
|
assert mock_client.noise_psk == VALID_NOISE_PSK
|
||||||
|
|
||||||
|
|
||||||
async def test_login_connection_error(
|
async def test_login_connection_error(
|
||||||
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
hass: HomeAssistant, mock_client, mock_zeroconf: None, mock_setup_entry: None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -398,9 +705,9 @@ async def test_user_requires_psk(
|
|||||||
assert result["step_id"] == "encryption_key"
|
assert result["step_id"] == "encryption_key"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
assert len(mock_client.connect.mock_calls) == 1
|
assert len(mock_client.connect.mock_calls) == 2
|
||||||
assert len(mock_client.device_info.mock_calls) == 1
|
assert len(mock_client.device_info.mock_calls) == 2
|
||||||
assert len(mock_client.disconnect.mock_calls) == 1
|
assert len(mock_client.disconnect.mock_calls) == 2
|
||||||
|
|
||||||
|
|
||||||
async def test_encryption_key_valid_psk(
|
async def test_encryption_key_valid_psk(
|
||||||
@ -894,7 +1201,7 @@ async def test_zeroconf_encryption_key_via_dashboard(
|
|||||||
DeviceInfo(
|
DeviceInfo(
|
||||||
uses_password=False,
|
uses_password=False,
|
||||||
name="test8266",
|
name="test8266",
|
||||||
mac_address="11:22:33:44:55:aa",
|
mac_address="11:22:33:44:55:AA",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user