1 """Config flow to configure the Netgear integration."""
3 from __future__
import annotations
6 from typing
import Any, cast
7 from urllib.parse
import urlparse
9 from pynetgear
import DEFAULT_HOST, DEFAULT_PORT, DEFAULT_USER
10 import voluptuous
as vol
31 DEFAULT_CONSIDER_HOME,
39 from .errors
import CannotLoginException
40 from .router
import get_api
42 _LOGGER = logging.getLogger(__name__)
50 user_schema = {vol.Optional(CONF_HOST, default=user_input.get(CONF_HOST,
"")): str}
53 return vol.Schema(user_schema)
58 vol.Optional(CONF_USERNAME, default=schema_input.get(CONF_USERNAME,
"")): str,
59 vol.Required(CONF_PASSWORD, default=schema_input.get(CONF_PASSWORD,
"")): str,
64 """Options for the component."""
67 self, user_input: dict[str, int] |
None =
None
68 ) -> ConfigFlowResult:
69 """Manage the options."""
70 if user_input
is not None:
73 settings_schema = vol.Schema(
78 CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME.total_seconds()
84 return self.
async_show_formasync_show_form(step_id=
"init", data_schema=settings_schema)
88 """Handle a config flow."""
93 """Initialize the netgear config flow."""
95 CONF_HOST: DEFAULT_HOST,
96 CONF_PORT: DEFAULT_PORT,
97 CONF_USERNAME: DEFAULT_USER,
105 config_entry: ConfigEntry,
106 ) -> OptionsFlowHandler:
107 """Get the options flow."""
112 user_input: dict[str, Any] |
None =
None,
113 errors: dict[str, str] |
None =
None,
114 ) -> ConfigFlowResult:
115 """Show the setup form to the user."""
126 data_schema=data_schema,
132 self, discovery_info: ssdp.SsdpServiceInfo
133 ) -> ConfigFlowResult:
134 """Initialize flow from ssdp."""
135 updated_data: dict[str, str | int | bool] = {}
137 device_url = urlparse(discovery_info.ssdp_location)
138 if hostname := device_url.hostname:
139 hostname = cast(str, hostname)
140 updated_data[CONF_HOST] = hostname
145 _LOGGER.debug(
"Netgear ssdp discovery info: %s", discovery_info)
147 if ssdp.ATTR_UPNP_SERIAL
not in discovery_info.upnp:
150 await self.
async_set_unique_idasync_set_unique_id(discovery_info.upnp[ssdp.ATTR_UPNP_SERIAL])
153 if device_url.scheme ==
"https":
154 updated_data[CONF_SSL] =
True
156 updated_data[CONF_SSL] =
False
158 updated_data[CONF_PORT] = DEFAULT_PORT
159 for model
in MODELS_PORT_80:
160 if discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NUMBER,
"").startswith(
162 )
or discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NAME,
"").startswith(
165 updated_data[CONF_PORT] = PORT_80
166 for model
in MODELS_PORT_5555:
167 if discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NUMBER,
"").startswith(
169 )
or discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NAME,
"").startswith(
172 updated_data[CONF_PORT] = PORT_5555
173 updated_data[CONF_SSL] =
True
181 self, user_input: dict[str, Any] |
None =
None
182 ) -> ConfigFlowResult:
183 """Handle a flow initiated by the user."""
186 if user_input
is None:
189 host = user_input.get(CONF_HOST, self.
placeholdersplaceholders[CONF_HOST])
192 username = user_input.get(CONF_USERNAME, self.
placeholdersplaceholders[CONF_USERNAME])
193 password = user_input[CONF_PASSWORD]
199 api = await self.hass.async_add_executor_job(
200 get_api, password, host, username, port, ssl
202 except CannotLoginException:
203 errors[
"base"] =
"config"
207 CONF_USERNAME: username,
208 CONF_PASSWORD: password,
215 info = await self.hass.async_add_executor_job(api.get_info)
217 errors[
"base"] =
"info"
220 await self.
async_set_unique_idasync_set_unique_id(info[
"SerialNumber"], raise_on_progress=
False)
223 if info.get(
"ModelName")
is not None and info.get(
"DeviceName")
is not None:
224 name = f
"{info['ModelName']} - {info['DeviceName']}"
226 name = info.get(
"ModelName", DEFAULT_NAME)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
ConfigFlowResult _show_setup_form(self, dict[str, Any]|None user_input=None, dict[str, str]|None errors=None)
OptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_init(self, dict[str, int]|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|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_step_user(self, dict[str, Any]|None user_input=None)
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)
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)
def _discovery_schema_with_defaults(discovery_info)
def _ordered_shared_schema(schema_input)
def _user_schema_with_defaults(user_input)
bool is_ipv4_address(str address)