1 """Config flow for Onkyo."""
6 import voluptuous
as vol
29 CONF_RECEIVER_MAX_VOLUME,
34 OPTION_MAX_VOLUME_DEFAULT,
35 OPTION_VOLUME_RESOLUTION,
36 OPTION_VOLUME_RESOLUTION_DEFAULT,
37 VOLUME_RESOLUTION_ALLOWED,
40 from .receiver
import ReceiverInfo, async_discover, async_interview
42 _LOGGER = logging.getLogger(__name__)
44 CONF_DEVICE =
"device"
46 INPUT_SOURCES_ALL_MEANINGS = [
47 input_source.value_meaning
for input_source
in InputSource
49 STEP_MANUAL_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str})
50 STEP_CONFIGURE_SCHEMA = vol.Schema(
52 vol.Required(OPTION_VOLUME_RESOLUTION): vol.In(VOLUME_RESOLUTION_ALLOWED),
55 options=INPUT_SOURCES_ALL_MEANINGS,
57 mode=SelectSelectorMode.DROPDOWN,
65 """Onkyo config flow."""
67 _receiver_info: ReceiverInfo
68 _discovered_infos: dict[str, ReceiverInfo]
71 self, user_input: dict[str, Any] |
None =
None
72 ) -> ConfigFlowResult:
73 """Handle a flow initialized by the user."""
75 step_id=
"user", menu_options=[
"manual",
"eiscp_discovery"]
78 async
def async_step_manual(
79 self, user_input: dict[str, Any] |
None =
None
80 ) -> ConfigFlowResult:
81 """Handle manual device entry."""
84 if user_input
is not None:
85 host = user_input[CONF_HOST]
86 _LOGGER.debug(
"Config flow start manual: %s", host)
90 _LOGGER.exception(
"Unexpected exception")
91 errors[
"base"] =
"unknown"
94 errors[
"base"] =
"cannot_connect"
99 info.identifier, raise_on_progress=
False
106 return await self.async_step_configure_receiver()
108 suggested_values = user_input
117 STEP_MANUAL_SCHEMA, suggested_values
122 async
def async_step_eiscp_discovery(
123 self, user_input: dict[str, Any] |
None =
None
124 ) -> ConfigFlowResult:
125 """Start eiscp discovery and handle user device selection."""
126 if user_input
is not None:
129 self.
_receiver_info_receiver_info.identifier, raise_on_progress=
False
134 return await self.async_step_configure_receiver()
136 _LOGGER.debug(
"Config flow start eiscp discovery")
141 _LOGGER.exception(
"Unexpected exception")
144 _LOGGER.debug(
"Discovered devices: %s", infos)
147 discovered_names = {}
150 if info.identifier
in current_unique_ids:
153 device_name = f
"{info.model_name} ({info.host})"
154 discovered_names[info.identifier] = device_name
156 _LOGGER.debug(
"Discovered new devices: %s", self.
_discovered_infos_discovered_infos)
158 if not discovered_names:
162 step_id=
"eiscp_discovery",
163 data_schema=vol.Schema(
164 {vol.Required(CONF_DEVICE): vol.In(discovered_names)}
168 async
def async_step_configure_receiver(
169 self, user_input: dict[str, Any] |
None =
None
170 ) -> ConfigFlowResult:
171 """Handle the configuration of a single receiver."""
178 entry_options = entry.options
180 if user_input
is not None:
181 source_meanings: list[str] = user_input[OPTION_INPUT_SOURCES]
182 if not source_meanings:
183 errors[OPTION_INPUT_SOURCES] =
"empty_input_source_list"
185 sources_store: dict[str, str] = {}
186 for source_meaning
in source_meanings:
187 source = InputSource.from_meaning(source_meaning)
189 source_name = source_meaning
190 if entry_options
is not None:
191 source_name = entry_options[OPTION_INPUT_SOURCES].
get(
192 source.value, source_name
194 sources_store[source.value] = source_name
196 volume_resolution = user_input[OPTION_VOLUME_RESOLUTION]
198 if entry_options
is None:
205 OPTION_VOLUME_RESOLUTION: volume_resolution,
206 OPTION_MAX_VOLUME: OPTION_MAX_VOLUME_DEFAULT,
207 OPTION_INPUT_SOURCES: sources_store,
211 assert entry
is not None
218 OPTION_VOLUME_RESOLUTION: volume_resolution,
219 OPTION_MAX_VOLUME: entry_options[OPTION_MAX_VOLUME],
220 OPTION_INPUT_SOURCES: sources_store,
224 _LOGGER.debug(
"Configured receiver, result: %s", result)
227 _LOGGER.debug(
"Configuring receiver, info: %s", self.
_receiver_info_receiver_info)
229 suggested_values = user_input
230 if suggested_values
is None:
231 if entry_options
is None:
233 OPTION_VOLUME_RESOLUTION: OPTION_VOLUME_RESOLUTION_DEFAULT,
234 OPTION_INPUT_SOURCES: [],
238 OPTION_VOLUME_RESOLUTION: entry_options[OPTION_VOLUME_RESOLUTION],
239 OPTION_INPUT_SOURCES: [
241 for input_source
in entry_options[OPTION_INPUT_SOURCES]
246 step_id=
"configure_receiver",
248 STEP_CONFIGURE_SCHEMA, suggested_values
251 description_placeholders={
252 "name": f
"{self._receiver_info.model_name} ({self._receiver_info.host})"
256 async
def async_step_reconfigure(
257 self, user_input: dict[str, Any] |
None =
None
258 ) -> ConfigFlowResult:
259 """Handle reconfiguration of the receiver."""
260 return await self.async_step_manual()
262 async
def async_step_import(self, user_input: dict[str, Any]) -> ConfigFlowResult:
263 """Import the yaml config."""
264 _LOGGER.debug(
"Import flow user input: %s", user_input)
266 host: str = user_input[CONF_HOST]
267 name: str |
None = user_input.get(CONF_NAME)
268 user_max_volume: int = user_input[OPTION_MAX_VOLUME]
269 user_volume_resolution: int = user_input[CONF_RECEIVER_MAX_VOLUME]
270 user_sources: dict[InputSource, str] = user_input[CONF_SOURCES]
272 info: ReceiverInfo |
None = user_input.get(
"info")
277 _LOGGER.exception(
"Import flow interview error for host %s", host)
281 _LOGGER.error(
"Import flow interview error for host %s", host)
284 unique_id = info.identifier
288 name = name
or info.model_name
290 volume_resolution = VOLUME_RESOLUTION_ALLOWED[-1]
291 for volume_resolution_allowed
in VOLUME_RESOLUTION_ALLOWED:
292 if user_volume_resolution <= volume_resolution_allowed:
293 volume_resolution = volume_resolution_allowed
297 100, user_max_volume * user_volume_resolution / volume_resolution
300 sources_store: dict[str, str] = {}
301 for source, source_name
in user_sources.items():
302 sources_store[source.value] = source_name
310 OPTION_VOLUME_RESOLUTION: volume_resolution,
311 OPTION_MAX_VOLUME: max_volume,
312 OPTION_INPUT_SOURCES: sources_store,
319 config_entry: ConfigEntry,
321 """Return the options flow."""
326 """Handle an options flow for Onkyo."""
328 def __init__(self, config_entry: ConfigEntry) ->
None:
329 """Initialize options flow."""
330 sources_store: dict[str, str] = config_entry.options[OPTION_INPUT_SOURCES]
334 self, user_input: dict[str, Any] |
None =
None
335 ) -> ConfigFlowResult:
336 """Manage the options."""
337 if user_input
is not None:
338 sources_store: dict[str, str] = {}
339 for source_meaning, source_name
in user_input.items():
340 if source_meaning
in INPUT_SOURCES_ALL_MEANINGS:
341 source = InputSource.from_meaning(source_meaning)
342 sources_store[source.value] = source_name
347 OPTION_VOLUME_RESOLUTION
349 OPTION_MAX_VOLUME: user_input[OPTION_MAX_VOLUME],
350 OPTION_INPUT_SOURCES: sources_store,
354 schema_dict: dict[Any, Selector] = {}
357 schema_dict[vol.Required(OPTION_MAX_VOLUME, default=max_volume)] = (
363 for source, source_name
in self.
_input_sources_input_sources.items():
364 schema_dict[vol.Required(source.value_meaning, default=source_name)] = (
370 data_schema=vol.Schema(schema_dict),
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
None __init__(self, ConfigEntry config_entry)
ConfigFlowResult async_step_init(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")
set[str|None] _async_current_ids(self, bool include_ignore=True)
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)
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)
ConfigEntry _get_reconfigure_entry(self)
None _abort_if_unique_id_mismatch(self, *str reason="unique_id_mismatch", 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)
OptionsFlow async_get_options_flow(ConfigEntry config_entry)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
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_show_menu(self, *str|None step_id=None, Container[str] menu_options, Mapping[str, str]|None description_placeholders=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)
web.Response get(self, web.Request request, str config_key)
ReceiverInfo|None async_interview(str host)
None async_discover(HomeAssistant hass)
config_entries.ConfigFlowResult async_step_import(self, dict[str, Any]|None _)