Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for Mikrotik."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Mapping
6 from typing import Any
7 
8 import voluptuous as vol
9 
10 from homeassistant.config_entries import (
11  ConfigEntry,
12  ConfigFlow,
13  ConfigFlowResult,
14  OptionsFlow,
15 )
16 from homeassistant.const import (
17  CONF_HOST,
18  CONF_PASSWORD,
19  CONF_PORT,
20  CONF_USERNAME,
21  CONF_VERIFY_SSL,
22 )
23 from homeassistant.core import callback
24 
25 from .const import (
26  CONF_ARP_PING,
27  CONF_DETECTION_TIME,
28  CONF_FORCE_DHCP,
29  DEFAULT_API_PORT,
30  DEFAULT_DETECTION_TIME,
31  DEFAULT_NAME,
32  DOMAIN,
33 )
34 from .coordinator import get_api
35 from .errors import CannotConnect, LoginError
36 
37 
38 class MikrotikFlowHandler(ConfigFlow, domain=DOMAIN):
39  """Handle a Mikrotik config flow."""
40 
41  VERSION = 1
42 
43  @staticmethod
44  @callback
46  config_entry: ConfigEntry,
47  ) -> MikrotikOptionsFlowHandler:
48  """Get the options flow for this handler."""
50 
51  async def async_step_user(
52  self, user_input: dict[str, Any] | None = None
53  ) -> ConfigFlowResult:
54  """Handle a flow initialized by the user."""
55  errors = {}
56  if user_input is not None:
57  self._async_abort_entries_match_async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
58 
59  try:
60  await self.hass.async_add_executor_job(get_api, user_input)
61  except CannotConnect:
62  errors["base"] = "cannot_connect"
63  except LoginError:
64  errors[CONF_USERNAME] = "invalid_auth"
65  errors[CONF_PASSWORD] = "invalid_auth"
66 
67  if not errors:
68  return self.async_create_entryasync_create_entryasync_create_entry(
69  title=f"{DEFAULT_NAME} ({user_input[CONF_HOST]})", data=user_input
70  )
71  return self.async_show_formasync_show_formasync_show_form(
72  step_id="user",
73  data_schema=vol.Schema(
74  {
75  vol.Required(CONF_HOST): str,
76  vol.Required(CONF_USERNAME): str,
77  vol.Required(CONF_PASSWORD): str,
78  vol.Optional(CONF_PORT, default=DEFAULT_API_PORT): int,
79  vol.Optional(CONF_VERIFY_SSL, default=False): bool,
80  }
81  ),
82  errors=errors,
83  )
84 
85  async def async_step_reauth(
86  self, entry_data: Mapping[str, Any]
87  ) -> ConfigFlowResult:
88  """Perform reauth upon an API authentication error."""
89  return await self.async_step_reauth_confirmasync_step_reauth_confirm()
90 
92  self, user_input: dict[str, str] | None = None
93  ) -> ConfigFlowResult:
94  """Confirm reauth dialog."""
95  errors = {}
96 
97  reauth_entry = self._get_reauth_entry_get_reauth_entry()
98  if user_input is not None:
99  user_input = {**reauth_entry.data, **user_input}
100  try:
101  await self.hass.async_add_executor_job(get_api, user_input)
102  except CannotConnect:
103  errors["base"] = "cannot_connect"
104  except LoginError:
105  errors[CONF_PASSWORD] = "invalid_auth"
106 
107  if not errors:
108  return self.async_update_reload_and_abortasync_update_reload_and_abort(reauth_entry, data=user_input)
109 
110  return self.async_show_formasync_show_formasync_show_form(
111  description_placeholders={CONF_USERNAME: reauth_entry.data[CONF_USERNAME]},
112  step_id="reauth_confirm",
113  data_schema=vol.Schema(
114  {
115  vol.Required(CONF_PASSWORD): str,
116  }
117  ),
118  errors=errors,
119  )
120 
121 
123  """Handle Mikrotik options."""
124 
125  async def async_step_init(
126  self, user_input: dict[str, Any] | None = None
127  ) -> ConfigFlowResult:
128  """Manage the Mikrotik options."""
129  return await self.async_step_device_trackerasync_step_device_tracker()
130 
132  self, user_input: dict[str, Any] | None = None
133  ) -> ConfigFlowResult:
134  """Manage the device tracker options."""
135  if user_input is not None:
136  return self.async_create_entryasync_create_entry(title="", data=user_input)
137 
138  options = {
139  vol.Optional(
140  CONF_FORCE_DHCP,
141  default=self.config_entryconfig_entryconfig_entry.options.get(CONF_FORCE_DHCP, False),
142  ): bool,
143  vol.Optional(
144  CONF_ARP_PING,
145  default=self.config_entryconfig_entryconfig_entry.options.get(CONF_ARP_PING, False),
146  ): bool,
147  vol.Optional(
148  CONF_DETECTION_TIME,
149  default=self.config_entryconfig_entryconfig_entry.options.get(
150  CONF_DETECTION_TIME, DEFAULT_DETECTION_TIME
151  ),
152  ): int,
153  }
154 
155  return self.async_show_formasync_show_form(
156  step_id="device_tracker", data_schema=vol.Schema(options)
157  )
MikrotikOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
Definition: config_flow.py:47
ConfigFlowResult async_step_reauth_confirm(self, dict[str, str]|None user_input=None)
Definition: config_flow.py:93
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
Definition: config_flow.py:87
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:53
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:127
ConfigFlowResult async_step_device_tracker(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:133
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)
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)
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)