mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Fix radio_id can be unavailable (#92698)
Allow radio_id to be unavailable
This commit is contained in:
parent
2c5cad4ca0
commit
b22c45ea29
@ -6,7 +6,12 @@ import logging
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from afsapi import AFSAPI, ConnectionError as FSConnectionError, InvalidPinException
|
from afsapi import (
|
||||||
|
AFSAPI,
|
||||||
|
ConnectionError as FSConnectionError,
|
||||||
|
InvalidPinException,
|
||||||
|
NotImplementedException,
|
||||||
|
)
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -68,10 +73,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
_LOGGER.exception(exception)
|
_LOGGER.exception(exception)
|
||||||
return self.async_abort(reason="unknown")
|
return self.async_abort(reason="unknown")
|
||||||
|
|
||||||
|
afsapi = AFSAPI(webfsapi_url, import_info[CONF_PIN])
|
||||||
try:
|
try:
|
||||||
afsapi = AFSAPI(webfsapi_url, import_info[CONF_PIN])
|
|
||||||
|
|
||||||
unique_id = await afsapi.get_radio_id()
|
unique_id = await afsapi.get_radio_id()
|
||||||
|
except NotImplementedException:
|
||||||
|
unique_id = None # Not all radios have this call implemented
|
||||||
except FSConnectionError:
|
except FSConnectionError:
|
||||||
return self.async_abort(reason="cannot_connect")
|
return self.async_abort(reason="cannot_connect")
|
||||||
except InvalidPinException:
|
except InvalidPinException:
|
||||||
@ -141,14 +147,18 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
_LOGGER.debug(exception)
|
_LOGGER.debug(exception)
|
||||||
return self.async_abort(reason="unknown")
|
return self.async_abort(reason="unknown")
|
||||||
|
|
||||||
|
# try to login with default pin
|
||||||
|
afsapi = AFSAPI(self._webfsapi_url, DEFAULT_PIN)
|
||||||
try:
|
try:
|
||||||
# try to login with default pin
|
await afsapi.get_friendly_name()
|
||||||
afsapi = AFSAPI(self._webfsapi_url, DEFAULT_PIN)
|
|
||||||
|
|
||||||
unique_id = await afsapi.get_radio_id()
|
|
||||||
except InvalidPinException:
|
except InvalidPinException:
|
||||||
return self.async_abort(reason="invalid_auth")
|
return self.async_abort(reason="invalid_auth")
|
||||||
|
|
||||||
|
try:
|
||||||
|
unique_id = await afsapi.get_radio_id()
|
||||||
|
except NotImplementedException:
|
||||||
|
unique_id = None
|
||||||
|
|
||||||
await self.async_set_unique_id(unique_id)
|
await self.async_set_unique_id(unique_id)
|
||||||
self._abort_if_unique_id_configured(
|
self._abort_if_unique_id_configured(
|
||||||
updates={CONF_WEBFSAPI_URL: self._webfsapi_url}, reload_on_update=True
|
updates={CONF_WEBFSAPI_URL: self._webfsapi_url}, reload_on_update=True
|
||||||
@ -175,7 +185,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
self.context["title_placeholders"] = {"name": self._name}
|
self.context["title_placeholders"] = {"name": self._name}
|
||||||
|
|
||||||
unique_id = await afsapi.get_radio_id()
|
try:
|
||||||
|
unique_id = await afsapi.get_radio_id()
|
||||||
|
except NotImplementedException:
|
||||||
|
unique_id = None
|
||||||
await self.async_set_unique_id(unique_id)
|
await self.async_set_unique_id(unique_id)
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
@ -240,7 +253,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
await self.hass.config_entries.async_reload(self._reauth_entry.entry_id)
|
await self.hass.config_entries.async_reload(self._reauth_entry.entry_id)
|
||||||
return self.async_abort(reason="reauth_successful")
|
return self.async_abort(reason="reauth_successful")
|
||||||
|
|
||||||
unique_id = await afsapi.get_radio_id()
|
try:
|
||||||
|
unique_id = await afsapi.get_radio_id()
|
||||||
|
except NotImplementedException:
|
||||||
|
unique_id = None
|
||||||
await self.async_set_unique_id(unique_id, raise_on_progress=False)
|
await self.async_set_unique_id(unique_id, raise_on_progress=False)
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
return await self._async_create_entry(user_input[CONF_PIN])
|
return await self._async_create_entry(user_input[CONF_PIN])
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Test the Frontier Silicon config flow."""
|
"""Test the Frontier Silicon config flow."""
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from afsapi import ConnectionError, InvalidPinException
|
from afsapi import ConnectionError, InvalidPinException, NotImplementedException
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -37,19 +37,31 @@ INVALID_MOCK_DISCOVERY = ssdp.SsdpServiceInfo(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_import_success(hass: HomeAssistant) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("radio_id_return_value", "radio_id_side_effect"),
|
||||||
|
[("mock_radio_id", None), (None, NotImplementedException)],
|
||||||
|
)
|
||||||
|
async def test_import_success(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
radio_id_return_value: str | None,
|
||||||
|
radio_id_side_effect: Exception | None,
|
||||||
|
) -> None:
|
||||||
"""Test successful import."""
|
"""Test successful import."""
|
||||||
|
with patch(
|
||||||
result = await hass.config_entries.flow.async_init(
|
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_radio_id",
|
||||||
DOMAIN,
|
return_value=radio_id_return_value,
|
||||||
context={"source": config_entries.SOURCE_IMPORT},
|
side_effect=radio_id_side_effect,
|
||||||
data={
|
):
|
||||||
CONF_HOST: "1.1.1.1",
|
result = await hass.config_entries.flow.async_init(
|
||||||
CONF_PORT: 80,
|
DOMAIN,
|
||||||
CONF_PIN: "1234",
|
context={"source": config_entries.SOURCE_IMPORT},
|
||||||
CONF_NAME: "Test name",
|
data={
|
||||||
},
|
CONF_HOST: "1.1.1.1",
|
||||||
)
|
CONF_PORT: 80,
|
||||||
|
CONF_PIN: "1234",
|
||||||
|
CONF_NAME: "Test name",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == "Test name"
|
assert result["title"] == "Test name"
|
||||||
@ -141,8 +153,15 @@ async def test_import_already_exists(
|
|||||||
assert result["reason"] == "already_configured"
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("radio_id_return_value", "radio_id_side_effect"),
|
||||||
|
[("mock_radio_id", None), (None, NotImplementedException)],
|
||||||
|
)
|
||||||
async def test_form_default_pin(
|
async def test_form_default_pin(
|
||||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
hass: HomeAssistant,
|
||||||
|
mock_setup_entry: AsyncMock,
|
||||||
|
radio_id_return_value: str | None,
|
||||||
|
radio_id_side_effect: Exception | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test manual device add with default pin."""
|
"""Test manual device add with default pin."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -152,10 +171,15 @@ async def test_form_default_pin(
|
|||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
with patch(
|
||||||
result["flow_id"],
|
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_radio_id",
|
||||||
{CONF_HOST: "1.1.1.1", CONF_PORT: 80},
|
return_value=radio_id_return_value,
|
||||||
)
|
side_effect=radio_id_side_effect,
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_HOST: "1.1.1.1", CONF_PORT: 80},
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||||
@ -167,8 +191,15 @@ async def test_form_default_pin(
|
|||||||
mock_setup_entry.assert_called_once()
|
mock_setup_entry.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("radio_id_return_value", "radio_id_side_effect"),
|
||||||
|
[("mock_radio_id", None), (None, NotImplementedException)],
|
||||||
|
)
|
||||||
async def test_form_nondefault_pin(
|
async def test_form_nondefault_pin(
|
||||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
hass: HomeAssistant,
|
||||||
|
mock_setup_entry: AsyncMock,
|
||||||
|
radio_id_return_value: str | None,
|
||||||
|
radio_id_side_effect: Exception | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test we get the form."""
|
"""Test we get the form."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -192,10 +223,15 @@ async def test_form_nondefault_pin(
|
|||||||
assert result2["step_id"] == "device_config"
|
assert result2["step_id"] == "device_config"
|
||||||
assert result2["errors"] is None
|
assert result2["errors"] is None
|
||||||
|
|
||||||
result3 = await hass.config_entries.flow.async_configure(
|
with patch(
|
||||||
result2["flow_id"],
|
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_radio_id",
|
||||||
{CONF_PIN: "4321"},
|
return_value=radio_id_return_value,
|
||||||
)
|
side_effect=radio_id_side_effect,
|
||||||
|
):
|
||||||
|
result3 = await hass.config_entries.flow.async_configure(
|
||||||
|
result2["flow_id"],
|
||||||
|
{CONF_PIN: "4321"},
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
||||||
@ -322,14 +358,27 @@ async def test_invalid_device_url(
|
|||||||
mock_setup_entry.assert_called_once()
|
mock_setup_entry.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
async def test_ssdp(hass: HomeAssistant, mock_setup_entry: MockConfigEntry) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("radio_id_return_value", "radio_id_side_effect"),
|
||||||
|
[("mock_radio_id", None), (None, NotImplementedException)],
|
||||||
|
)
|
||||||
|
async def test_ssdp(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_setup_entry: MockConfigEntry,
|
||||||
|
radio_id_return_value: str | None,
|
||||||
|
radio_id_side_effect: Exception | None,
|
||||||
|
) -> None:
|
||||||
"""Test a device being discovered."""
|
"""Test a device being discovered."""
|
||||||
|
with patch(
|
||||||
result = await hass.config_entries.flow.async_init(
|
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_radio_id",
|
||||||
DOMAIN,
|
return_value=radio_id_return_value,
|
||||||
context={"source": config_entries.SOURCE_SSDP},
|
side_effect=radio_id_side_effect,
|
||||||
data=MOCK_DISCOVERY,
|
):
|
||||||
)
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": config_entries.SOURCE_SSDP},
|
||||||
|
data=MOCK_DISCOVERY,
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] == FlowResultType.FORM
|
assert result["type"] == FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm"
|
assert result["step_id"] == "confirm"
|
||||||
@ -404,7 +453,7 @@ async def test_ssdp_nondefault_pin(hass: HomeAssistant) -> None:
|
|||||||
"""Test a device being discovered."""
|
"""Test a device being discovered."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_radio_id",
|
"homeassistant.components.frontier_silicon.config_flow.AFSAPI.get_friendly_name",
|
||||||
side_effect=InvalidPinException,
|
side_effect=InvalidPinException,
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user