-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add config flow to frontier_silicon (#64365)
* Add config_flow to frontier_silicon * Add missing translation file * Delay unique_id validation until radio_id can be determined * Fix tests * Improve tests * Use FlowResultType * Bump afsapi to 0.2.6 * Fix requirements_test_all.txt * Stash ssdp, reauth and unignore flows for now * Re-introduce SSDP flow * hassfest changes * Address review comments * Small style update * Fix tests * Update integrations.json * fix order in manifest.json * fix black errors * Apply suggestions from code review Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Address review comments * fix black errors * Use async_setup_platform instead of async_setup * Address review comments on tests * parameterize tests * Remove discovery component changes from this PR * Address review comments * Apply suggestions from code review Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Add extra asserts to tests * Restructure _async_step_device_config_if_needed * Add return statement * Update homeassistant/components/frontier_silicon/media_player.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --------- Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
- Loading branch information
Showing
14 changed files
with
636 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,45 @@ | ||
"""The frontier_silicon component.""" | ||
"""The Frontier Silicon integration.""" | ||
from __future__ import annotations | ||
|
||
import logging | ||
|
||
from afsapi import AFSAPI, ConnectionError as FSConnectionError | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import PlatformNotReady | ||
|
||
from .const import CONF_PIN, CONF_WEBFSAPI_URL, DOMAIN | ||
|
||
PLATFORMS = [Platform.MEDIA_PLAYER] | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up Frontier Silicon from a config entry.""" | ||
|
||
webfsapi_url = entry.data[CONF_WEBFSAPI_URL] | ||
pin = entry.data[CONF_PIN] | ||
|
||
afsapi = AFSAPI(webfsapi_url, pin) | ||
|
||
try: | ||
await afsapi.get_power() | ||
except FSConnectionError as exception: | ||
raise PlatformNotReady from exception | ||
|
||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = afsapi | ||
|
||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
|
||
return True | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
|
||
return unload_ok |
178 changes: 178 additions & 0 deletions
178
homeassistant/components/frontier_silicon/config_flow.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
"""Config flow for Frontier Silicon Media Player integration.""" | ||
from __future__ import annotations | ||
|
||
import logging | ||
from typing import Any | ||
|
||
from afsapi import AFSAPI, ConnectionError as FSConnectionError, InvalidPinException | ||
import voluptuous as vol | ||
|
||
from homeassistant import config_entries | ||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT | ||
from homeassistant.data_entry_flow import FlowResult | ||
|
||
from .const import CONF_PIN, CONF_WEBFSAPI_URL, DEFAULT_PIN, DEFAULT_PORT, DOMAIN | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
STEP_USER_DATA_SCHEMA = vol.Schema( | ||
{ | ||
vol.Required(CONF_HOST): str, | ||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int, | ||
} | ||
) | ||
|
||
STEP_DEVICE_CONFIG_DATA_SCHEMA = vol.Schema( | ||
{ | ||
vol.Required( | ||
CONF_PIN, | ||
default=DEFAULT_PIN, | ||
): str, | ||
} | ||
) | ||
|
||
|
||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||
"""Handle a config flow for Frontier Silicon Media Player.""" | ||
|
||
VERSION = 1 | ||
|
||
def __init__(self) -> None: | ||
"""Initialize flow.""" | ||
|
||
self._webfsapi_url: str | None = None | ||
self._name: str | None = None | ||
self._unique_id: str | None = None | ||
|
||
async def async_step_import(self, import_info: dict[str, Any]) -> FlowResult: | ||
"""Handle the import of legacy configuration.yaml entries.""" | ||
|
||
device_url = f"http://{import_info[CONF_HOST]}:{import_info[CONF_PORT]}/device" | ||
try: | ||
self._webfsapi_url = await AFSAPI.get_webfsapi_endpoint(device_url) | ||
except FSConnectionError: | ||
return self.async_abort(reason="cannot_connect") | ||
except Exception as exception: # pylint: disable=broad-except | ||
_LOGGER.exception(exception) | ||
return self.async_abort(reason="unknown") | ||
|
||
try: | ||
afsapi = AFSAPI(self._webfsapi_url, import_info[CONF_PIN]) | ||
|
||
self._unique_id = await afsapi.get_radio_id() | ||
except FSConnectionError: | ||
return self.async_abort(reason="cannot_connect") | ||
except InvalidPinException: | ||
return self.async_abort(reason="invalid_auth") | ||
except Exception as exception: # pylint: disable=broad-except | ||
_LOGGER.exception(exception) | ||
return self.async_abort(reason="unknown") | ||
|
||
await self.async_set_unique_id(self._unique_id, raise_on_progress=False) | ||
self._abort_if_unique_id_configured() | ||
|
||
self._name = import_info[CONF_NAME] or "Radio" | ||
|
||
return await self._create_entry(pin=import_info[CONF_PIN]) | ||
|
||
async def async_step_user( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle the initial step of manual configuration.""" | ||
errors = {} | ||
|
||
if user_input: | ||
device_url = ( | ||
f"http://{user_input[CONF_HOST]}:{user_input[CONF_PORT]}/device" | ||
) | ||
try: | ||
self._webfsapi_url = await AFSAPI.get_webfsapi_endpoint(device_url) | ||
except FSConnectionError: | ||
errors["base"] = "cannot_connect" | ||
except Exception as exception: # pylint: disable=broad-except | ||
_LOGGER.exception(exception) | ||
errors["base"] = "unknown" | ||
else: | ||
return await self._async_step_device_config_if_needed() | ||
|
||
data_schema = self.add_suggested_values_to_schema( | ||
STEP_USER_DATA_SCHEMA, user_input | ||
) | ||
return self.async_show_form( | ||
step_id="user", data_schema=data_schema, errors=errors | ||
) | ||
|
||
async def _async_step_device_config_if_needed(self) -> FlowResult: | ||
"""Most users will not have changed the default PIN on their radio. | ||
We try to use this default PIN, and only if this fails ask for it via `async_step_device_config` | ||
""" | ||
|
||
try: | ||
# try to login with default pin | ||
afsapi = AFSAPI(self._webfsapi_url, DEFAULT_PIN) | ||
|
||
self._name = await afsapi.get_friendly_name() | ||
except InvalidPinException: | ||
# Ask for a PIN | ||
return await self.async_step_device_config() | ||
|
||
self.context["title_placeholders"] = {"name": self._name} | ||
|
||
self._unique_id = await afsapi.get_radio_id() | ||
await self.async_set_unique_id(self._unique_id) | ||
self._abort_if_unique_id_configured() | ||
|
||
return await self._create_entry() | ||
|
||
async def async_step_device_config( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle device configuration step. | ||
We ask for the PIN in this step. | ||
""" | ||
assert self._webfsapi_url is not None | ||
|
||
if user_input is None: | ||
return self.async_show_form( | ||
step_id="device_config", data_schema=STEP_DEVICE_CONFIG_DATA_SCHEMA | ||
) | ||
|
||
errors = {} | ||
|
||
try: | ||
afsapi = AFSAPI(self._webfsapi_url, user_input[CONF_PIN]) | ||
|
||
self._name = await afsapi.get_friendly_name() | ||
|
||
except FSConnectionError: | ||
errors["base"] = "cannot_connect" | ||
except InvalidPinException: | ||
errors["base"] = "invalid_auth" | ||
except Exception as exception: # pylint: disable=broad-except | ||
_LOGGER.exception(exception) | ||
errors["base"] = "unknown" | ||
else: | ||
self._unique_id = await afsapi.get_radio_id() | ||
await self.async_set_unique_id(self._unique_id) | ||
self._abort_if_unique_id_configured() | ||
return await self._create_entry(pin=user_input[CONF_PIN]) | ||
|
||
data_schema = self.add_suggested_values_to_schema( | ||
STEP_DEVICE_CONFIG_DATA_SCHEMA, user_input | ||
) | ||
return self.async_show_form( | ||
step_id="device_config", | ||
data_schema=data_schema, | ||
errors=errors, | ||
) | ||
|
||
async def _create_entry(self, pin: str | None = None) -> FlowResult: | ||
"""Create the entry.""" | ||
assert self._name is not None | ||
assert self._webfsapi_url is not None | ||
|
||
data = {CONF_WEBFSAPI_URL: self._webfsapi_url, CONF_PIN: pin or DEFAULT_PIN} | ||
|
||
return self.async_create_entry(title=self._name, data=data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"config": { | ||
"flow_title": "{name}", | ||
"step": { | ||
"user": { | ||
"title": "Frontier Silicon Setup", | ||
"data": { | ||
"host": "[%key:common::config_flow::data::host%]", | ||
"port": "[%key:common::config_flow::data::port%]" | ||
} | ||
}, | ||
"device_config": { | ||
"title": "Device Configuration", | ||
"description": "The pin can be found via 'MENU button > Main Menu > System setting > Network > NetRemote PIN setup'", | ||
"data": { | ||
"pin": "[%key:common::config_flow::data::pin%]" | ||
} | ||
} | ||
}, | ||
"error": { | ||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", | ||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", | ||
"unknown": "[%key:common::config_flow::error::unknown%]" | ||
}, | ||
"abort": { | ||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]" | ||
} | ||
}, | ||
"issues": { | ||
"removed_yaml": { | ||
"title": "The Frontier Silicon YAML configuration has been removed", | ||
"description": "Configuring Frontier Silicon using YAML has been removed.\n\nYour existing YAML configuration is not used by Home Assistant.\n\nRemove the YAML configuration from your configuration.yaml file and restart Home Assistant to fix this issue." | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.