1 """Config flow to configure the AsusWrt integration."""
3 from __future__
import annotations
8 from typing
import Any, cast
10 from pyasuswrt
import AsusWrtError
11 import voluptuous
as vol
15 DEFAULT_CONSIDER_HOME,
30 SchemaCommonFlowHandler,
32 SchemaOptionsFlowHandler,
37 from .bridge
import AsusWrtBridge
46 DEFAULT_TRACK_UNKNOWN,
64 PASS_KEY_MSG =
"Only provide password or SSH key file"
66 RESULT_CONN_ERROR =
"cannot_connect"
67 RESULT_SUCCESS =
"success"
68 RESULT_UNKNOWN =
"unknown"
70 _LOGGER = logging.getLogger(__name__)
72 LEGACY_SCHEMA = vol.Schema(
74 vol.Required(CONF_MODE, default=MODE_ROUTER): vol.In(
75 {MODE_ROUTER:
"Router", MODE_AP:
"Access Point"}
80 OPTIONS_SCHEMA = vol.Schema(
83 CONF_CONSIDER_HOME, default=DEFAULT_CONSIDER_HOME.total_seconds()
84 ): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=900)),
85 vol.Optional(CONF_TRACK_UNKNOWN, default=DEFAULT_TRACK_UNKNOWN): bool,
91 """Get options schema."""
92 options_flow: SchemaOptionsFlowHandler
93 options_flow = cast(SchemaOptionsFlowHandler, handler.parent_handler)
94 used_protocol = options_flow.config_entry.data[CONF_PROTOCOL]
95 if used_protocol
in [PROTOCOL_SSH, PROTOCOL_TELNET]:
96 data_schema = OPTIONS_SCHEMA.extend(
98 vol.Required(CONF_INTERFACE, default=DEFAULT_INTERFACE): str,
99 vol.Required(CONF_DNSMASQ, default=DEFAULT_DNSMASQ): str,
102 if options_flow.config_entry.data[CONF_MODE] == MODE_AP:
103 return data_schema.extend(
105 vol.Optional(CONF_REQUIRE_IP, default=
True): bool,
110 return OPTIONS_SCHEMA
119 """Validate that the value is an existing file."""
120 file_in = os.path.expanduser(value)
121 return os.path.isfile(file_in)
and os.access(file_in, os.R_OK)
125 """Get the ip address from the host name."""
127 return socket.gethostbyname(host)
128 except socket.gaierror:
133 """Handle a config flow for AsusWRT."""
138 """Initialize the AsusWrt config flow."""
143 """Show the setup form to the user."""
147 add_schema: VolDictType
150 vol.Exclusive(CONF_PASSWORD, PASS_KEY, PASS_KEY_MSG): str,
151 vol.Optional(CONF_PORT): cv.port,
152 vol.Exclusive(CONF_SSH_KEY, PASS_KEY, PASS_KEY_MSG): str,
155 add_schema = {vol.Required(CONF_PASSWORD): str}
158 vol.Required(CONF_HOST, default=user_input.get(CONF_HOST,
"")): str,
159 vol.Required(CONF_USERNAME, default=user_input.get(CONF_USERNAME,
"")): str,
163 default=user_input.get(CONF_PROTOCOL, PROTOCOL_HTTPS),
166 options=ALLOWED_PROTOCOL, translation_key=
"protocols"
173 data_schema=vol.Schema(schema),
174 errors={CONF_BASE: error}
if error
else None,
178 self, user_input: dict[str, Any]
179 ) -> tuple[str, str |
None]:
180 """Attempt to connect the AsusWrt router."""
183 host: str = user_input[CONF_HOST]
184 protocol = user_input[CONF_PROTOCOL]
185 error: str |
None =
None
187 conf = {**user_input, CONF_MODE: MODE_ROUTER}
188 api = AsusWrtBridge.get_bridge(self.hass, conf)
190 await api.async_connect()
192 except (AsusWrtError, OSError):
194 "Error connecting to the AsusWrt router at %s using protocol %s",
198 error = RESULT_CONN_ERROR
202 "Unknown error connecting with AsusWrt router at %s using protocol %s",
206 error = RESULT_UNKNOWN
209 if not api.is_connected:
211 "Error connecting to the AsusWrt router at %s using protocol %s",
215 error = RESULT_CONN_ERROR
217 if error
is not None:
221 "Successfully connected to the AsusWrt router at %s using protocol %s",
225 unique_id = api.label_mac
226 await api.async_disconnect()
228 return RESULT_SUCCESS, unique_id
231 self, user_input: dict[str, Any] |
None =
None
232 ) -> ConfigFlowResult:
233 """Handle a flow initiated by the user."""
237 if unique_id
is None:
240 if user_input
is None:
244 pwd: str |
None = user_input.get(CONF_PASSWORD)
245 ssh: str |
None = user_input.get(CONF_SSH_KEY)
246 protocol: str = user_input[CONF_PROTOCOL]
248 if not pwd
and protocol != PROTOCOL_SSH:
252 if ssh
and not await self.hass.async_add_executor_job(_is_file, ssh):
255 host: str = user_input[CONF_HOST]
256 if not await self.hass.async_add_executor_job(_get_ip, host):
260 if result == RESULT_SUCCESS:
268 "This device does not provide a valid Unique ID."
269 " Configuration of multiple instance will not be possible"
272 if protocol
in [PROTOCOL_SSH, PROTOCOL_TELNET]:
279 self, user_input: dict[str, Any] |
None =
None
280 ) -> ConfigFlowResult:
281 """Handle a flow for legacy settings."""
282 if user_input
is None:
289 """Save entry data if unique id is valid."""
298 config_entry: ConfigEntry,
299 ) -> SchemaOptionsFlowHandler:
300 """Get options flow for this handler."""
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult _async_save_entry(self)
SchemaOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_legacy(self, dict[str, Any]|None user_input=None)
tuple[str, str|None] _async_check_connection(self, dict[str, Any] user_input)
ConfigFlowResult _show_setup_form(self, str|None error=None)
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)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=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)
bool show_advanced_options(self)
_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)
vol.Schema get_options_schema(SchemaCommonFlowHandler handler)
str|None _get_ip(str host)
IssData update(pyiss.ISS iss)