1 """Config flow to configure Denon AVR receivers using their HTTP interface."""
3 from __future__
import annotations
7 from urllib.parse
import urlparse
10 from denonavr.exceptions
import AvrNetworkError, AvrTimoutError
11 import voluptuous
as vol
24 from .receiver
import ConnectDenonAVR
26 _LOGGER = logging.getLogger(__name__)
30 SUPPORTED_MANUFACTURERS = [
"Denon",
"DENON",
"DENON PROFESSIONAL",
"Marantz"]
31 IGNORED_MODELS = [
"HEOS 1",
"HEOS 3",
"HEOS 5",
"HEOS 7"]
33 CONF_SHOW_ALL_SOURCES =
"show_all_sources"
36 CONF_MANUFACTURER =
"manufacturer"
37 CONF_SERIAL_NUMBER =
"serial_number"
38 CONF_UPDATE_AUDYSSEY =
"update_audyssey"
39 CONF_USE_TELNET =
"use_telnet"
41 DEFAULT_SHOW_SOURCES =
False
45 DEFAULT_UPDATE_AUDYSSEY =
False
46 DEFAULT_USE_TELNET =
False
47 DEFAULT_USE_TELNET_NEW_INSTALL =
True
49 CONFIG_SCHEMA = vol.Schema({vol.Optional(CONF_HOST): str})
53 """Options for the component."""
56 self, user_input: dict[str, Any] |
None =
None
57 ) -> ConfigFlowResult:
58 """Manage the options."""
59 if user_input
is not None:
62 settings_schema = vol.Schema(
65 CONF_SHOW_ALL_SOURCES,
67 CONF_SHOW_ALL_SOURCES, DEFAULT_SHOW_SOURCES
81 CONF_UPDATE_AUDYSSEY, DEFAULT_UPDATE_AUDYSSEY
87 CONF_USE_TELNET, DEFAULT_USE_TELNET
93 return self.
async_show_formasync_show_form(step_id=
"init", data_schema=settings_schema)
97 """Handle a Denon AVR config flow."""
102 """Initialize the Denon AVR flow."""
103 self.
hosthost: str |
None =
None
110 self.
d_receiversd_receivers: list[dict[str, Any]] = []
115 config_entry: ConfigEntry,
116 ) -> OptionsFlowHandler:
117 """Get the options flow."""
121 self, user_input: dict[str, Any] |
None =
None
122 ) -> ConfigFlowResult:
123 """Handle a flow initialized by the user."""
125 if user_input
is not None:
127 if host := user_input.get(CONF_HOST):
141 errors[
"base"] =
"discovery_error"
144 step_id=
"user", data_schema=CONFIG_SCHEMA, errors=errors
148 self, user_input: dict[str, Any] |
None =
None
149 ) -> ConfigFlowResult:
150 """Handle multiple receivers found."""
151 errors: dict[str, str] = {}
152 if user_input
is not None:
153 self.
hosthost = user_input[
"select_host"]
156 select_scheme = vol.Schema(
158 vol.Required(
"select_host"): vol.In(
159 [d_receiver[
"host"]
for d_receiver
in self.
d_receiversd_receivers]
165 step_id=
"select", data_schema=select_scheme, errors=errors
169 self, user_input: dict[str, Any] |
None =
None
170 ) -> ConfigFlowResult:
171 """Allow the user to confirm adding the device."""
172 if user_input
is not None:
179 self, user_input: dict[str, Any] |
None =
None
180 ) -> ConfigFlowResult:
181 """Connect to the receiver."""
190 update_audyssey=
False,
195 success = await connect_denonavr.async_connect_receiver()
196 except (AvrNetworkError, AvrTimoutError):
200 receiver = connect_denonavr.receiver
206 self.
model_namemodel_name = (receiver.model_name).replace(
"*",
"")
215 "Could not get serial number of host %s, "
216 "unique_id's will not be available"
225 CONF_HOST: self.
hosthost,
226 CONF_TYPE: receiver.receiver_type,
228 CONF_MANUFACTURER: receiver.manufacturer,
231 options={CONF_USE_TELNET: DEFAULT_USE_TELNET_NEW_INSTALL},
235 self, discovery_info: ssdp.SsdpServiceInfo
236 ) -> ConfigFlowResult:
237 """Handle a discovered Denon AVR.
239 This flow is triggered by the SSDP component. It will check if the
240 host is already configured and delegate to the import step if not.
244 discovery_info.upnp.get(ssdp.ATTR_UPNP_MANUFACTURER)
245 not in SUPPORTED_MANUFACTURERS
251 ssdp.ATTR_UPNP_MODEL_NAME
not in discovery_info.upnp
252 or ssdp.ATTR_UPNP_SERIAL
not in discovery_info.upnp
256 self.
model_namemodel_name = discovery_info.upnp[ssdp.ATTR_UPNP_MODEL_NAME].replace(
259 self.
serial_numberserial_number = discovery_info.upnp[ssdp.ATTR_UPNP_SERIAL]
260 assert discovery_info.ssdp_location
is not None
261 self.
hosthost = urlparse(discovery_info.ssdp_location).hostname
263 if self.
model_namemodel_name
in IGNORED_MODELS:
272 "title_placeholders": {
273 "name": discovery_info.upnp.get(
274 ssdp.ATTR_UPNP_FRIENDLY_NAME, self.
hosthost
284 """Construct the unique id from the ssdp discovery or user_step."""
285 return f
"{model_name}-{serial_number}"
ConfigFlowResult async_step_connect(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
OptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
str construct_unique_id(str|None model_name, str|None serial_number)
ConfigFlowResult async_step_select(self, dict[str, Any]|None user_input=None)
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")
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)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
None _async_abort_entries_match(self, dict[str, Any]|None match_dict=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)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_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)
IssData update(pyiss.ISS iss)
httpx.AsyncClient get_async_client(HomeAssistant hass, bool verify_ssl=True)