1 """Config flow for Frontier Silicon Media Player integration."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
8 from urllib.parse
import urlparse
12 ConnectionError
as FSConnectionError,
14 NotImplementedException,
16 import voluptuous
as vol
27 SSDP_ATTR_SPEAKER_NAME,
30 _LOGGER = logging.getLogger(__name__)
32 STEP_USER_DATA_SCHEMA = vol.Schema(
34 vol.Required(CONF_HOST): str,
35 vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
39 STEP_DEVICE_CONFIG_DATA_SCHEMA = vol.Schema(
50 """Return the hostname from a url."""
51 return str(urlparse(url).hostname)
55 """Handle a config flow for Frontier Silicon Media Player."""
63 self, user_input: dict[str, Any] |
None =
None
64 ) -> ConfigFlowResult:
65 """Handle the initial step of manual configuration."""
70 f
"http://{user_input[CONF_HOST]}:{user_input[CONF_PORT]}/device"
73 self.
_webfsapi_url_webfsapi_url = await AFSAPI.get_webfsapi_endpoint(device_url)
74 except FSConnectionError:
75 errors[
"base"] =
"cannot_connect"
77 _LOGGER.exception(
"Unexpected exception")
78 errors[
"base"] =
"unknown"
83 STEP_USER_DATA_SCHEMA, user_input
86 step_id=
"user", data_schema=data_schema, errors=errors
90 self, discovery_info: ssdp.SsdpServiceInfo
91 ) -> ConfigFlowResult:
92 """Process entity discovered via SSDP."""
94 device_url = discovery_info.ssdp_location
95 if device_url
is None:
103 if speaker_name := discovery_info.ssdp_headers.get(SSDP_ATTR_SPEAKER_NAME):
105 self.context[
"title_placeholders"] = {
"name": speaker_name}
108 self.
_webfsapi_url_webfsapi_url = await AFSAPI.get_webfsapi_endpoint(device_url)
109 except FSConnectionError:
111 except Exception
as exception:
112 _LOGGER.debug(exception)
116 afsapi = AFSAPI(self.
_webfsapi_url_webfsapi_url, DEFAULT_PIN)
118 await afsapi.get_friendly_name()
119 except InvalidPinException:
123 unique_id = await afsapi.get_radio_id()
124 except NotImplementedException:
129 updates={CONF_WEBFSAPI_URL: self.
_webfsapi_url_webfsapi_url}, reload_on_update=
True
132 self.
_name_name = await afsapi.get_friendly_name()
137 """Most users will not have changed the default PIN on their radio.
139 We try to use this default PIN, and only if this fails ask for it via `async_step_device_config`
144 afsapi = AFSAPI(self.
_webfsapi_url_webfsapi_url, DEFAULT_PIN)
146 self.
_name_name = await afsapi.get_friendly_name()
147 except InvalidPinException:
151 self.context[
"title_placeholders"] = {
"name": self.
_name_name}
154 unique_id = await afsapi.get_radio_id()
155 except NotImplementedException:
163 self, user_input: dict[str, Any] |
None =
None
164 ) -> ConfigFlowResult:
165 """Allow the user to confirm adding the device. Used when the default PIN could successfully be used."""
167 if user_input
is not None:
172 step_id=
"confirm", description_placeholders={
"name": self.
_name_name}
176 self, entry_data: Mapping[str, Any]
177 ) -> ConfigFlowResult:
178 """Perform reauth upon an API authentication error."""
179 self.
_webfsapi_url_webfsapi_url = entry_data[CONF_WEBFSAPI_URL]
183 self, user_input: dict[str, Any] |
None =
None
184 ) -> ConfigFlowResult:
185 """Handle device configuration step.
187 We ask for the PIN in this step.
190 if user_input
is None:
192 step_id=
"device_config", data_schema=STEP_DEVICE_CONFIG_DATA_SCHEMA
198 afsapi = AFSAPI(self.
_webfsapi_url_webfsapi_url, user_input[CONF_PIN])
200 self.
_name_name = await afsapi.get_friendly_name()
202 except FSConnectionError:
203 errors[
"base"] =
"cannot_connect"
204 except InvalidPinException:
205 errors[
"base"] =
"invalid_auth"
207 _LOGGER.exception(
"Unexpected exception")
208 errors[
"base"] =
"unknown"
213 data_updates={CONF_PIN: user_input[CONF_PIN]},
217 unique_id = await afsapi.get_radio_id()
218 except NotImplementedException:
225 STEP_DEVICE_CONFIG_DATA_SCHEMA, user_input
228 step_id=
"device_config",
229 data_schema=data_schema,
234 """Create the entry."""
237 title=self.
_name_name,
238 data={CONF_WEBFSAPI_URL: self.
_webfsapi_url_webfsapi_url, CONF_PIN: pin
or DEFAULT_PIN},
ConfigFlowResult async_step_device_config(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult async_step_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
def _async_create_entry(self, str|None pin=None)
ConfigFlowResult _async_step_device_config_if_needed(self)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
ConfigEntry _get_reauth_entry(self)
None _set_confirm_only(self)
ConfigEntry|None async_set_unique_id(self, str|None unique_id=None, *bool raise_on_progress=True)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=None)
ConfigFlowResult async_update_reload_and_abort(self, ConfigEntry entry, *str|None|UndefinedType unique_id=UNDEFINED, str|UndefinedType title=UNDEFINED, Mapping[str, Any]|UndefinedType data=UNDEFINED, Mapping[str, Any]|UndefinedType data_updates=UNDEFINED, Mapping[str, Any]|UndefinedType options=UNDEFINED, str|UndefinedType reason=UNDEFINED, bool reload_even_if_entry_is_unchanged=True)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
vol.Schema add_suggested_values_to_schema(self, vol.Schema data_schema, Mapping[str, Any]|None suggested_values)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
str hostname_from_url(str url)