1 """Config flow for OctoPrint integration."""
3 from __future__
import annotations
6 from collections.abc
import Mapping
8 from typing
import TYPE_CHECKING, Any
11 from pyoctoprintapi
import ApiError, OctoprintClient, OctoprintException
12 import voluptuous
as vol
31 from .const
import DOMAIN
33 _LOGGER = logging.getLogger(__name__)
37 username="", host="", port=80, path="/", ssl=False, verify_ssl=True
41 vol.Required(CONF_USERNAME, default=username): str,
42 vol.Required(CONF_HOST, default=host): str,
43 vol.Required(CONF_PORT, default=port): cv.port,
44 vol.Required(CONF_PATH, default=path): str,
45 vol.Required(CONF_SSL, default=ssl): bool,
46 vol.Required(CONF_VERIFY_SSL, default=verify_ssl): bool,
48 extra=vol.ALLOW_EXTRA,
53 """Handle a config flow for OctoPrint."""
57 api_key_task: asyncio.Task[
None] |
None =
None
58 discovery_schema: vol.Schema |
None =
None
59 _reauth_data: dict[str, Any] |
None =
None
60 _user_input: dict[str, Any] |
None =
None
63 """Handle a config flow for OctoPrint."""
64 self._sessions: list[aiohttp.ClientSession] = []
67 self, user_input: dict[str, Any] |
None =
None
68 ) -> ConfigFlowResult:
69 """Handle the initial step."""
72 if user_input
is None and self.
_user_input_user_input:
75 if user_input
is None:
79 if CONF_API_KEY
in user_input:
83 except AbortFlow
as err:
86 errors[
"base"] =
"cannot_connect"
88 errors[
"base"] =
"unknown"
95 user_input.get(CONF_USERNAME),
96 user_input[CONF_HOST],
97 user_input[CONF_PORT],
98 user_input[CONF_PATH],
100 user_input[CONF_VERIFY_SSL],
108 self, user_input: dict[str, Any] |
None =
None
109 ) -> ConfigFlowResult:
110 """Get an Application Api Key."""
117 step_id=
"get_api_key",
118 progress_action=
"get_api_key",
124 except OctoprintException:
125 _LOGGER.exception(
"Failed to get an application key")
128 _LOGGER.exception(
"Failed to get an application key")
136 """Finish the configuration setup."""
138 if existing_entry
is not None:
139 self.hass.config_entries.async_update_entry(existing_entry, data=user_input)
141 self.hass.async_create_task(
142 self.hass.config_entries.async_reload(existing_entry.entry_id),
148 octoprint.set_api_key(user_input[CONF_API_KEY])
151 discovery = await octoprint.get_discovery_info()
152 except ApiError
as err:
153 _LOGGER.error(
"Failed to connect to printer")
154 raise CannotConnect
from err
156 await self.
async_set_unique_idasync_set_unique_id(discovery.upnp_uuid, raise_on_progress=
False)
162 """Handle api fetch failure."""
170 self, discovery_info: zeroconf.ZeroconfServiceInfo
171 ) -> ConfigFlowResult:
172 """Handle discovery flow."""
173 uuid = discovery_info.properties[
"uuid"]
179 "title_placeholders": {CONF_HOST: discovery_info.host},
180 "configuration_url": (
181 f
"http://{discovery_info.host}:{discovery_info.port}"
182 f
"{discovery_info.properties[CONF_PATH]}"
188 host=discovery_info.host,
189 port=discovery_info.port,
190 path=discovery_info.properties[CONF_PATH],
196 self, discovery_info: ssdp.SsdpServiceInfo
197 ) -> ConfigFlowResult:
198 """Handle ssdp discovery flow."""
199 uuid = discovery_info.upnp[
"UDN"][5:]
203 url =
URL(discovery_info.upnp[
"presentationURL"])
206 "title_placeholders": {CONF_HOST: url.host
or "-"},
207 "configuration_url": discovery_info.upnp[
"presentationURL"],
215 ssl=url.scheme ==
"https",
221 self, entry_data: Mapping[str, Any]
222 ) -> ConfigFlowResult:
223 """Handle reauthorization request from Octoprint."""
228 "title_placeholders": {CONF_HOST: entry_data[CONF_HOST]},
235 self, user_input: dict[str, Any] |
None =
None
236 ) -> ConfigFlowResult:
237 """Handle reauthorization flow."""
240 if user_input
is None:
242 step_id=
"reauth_confirm",
243 data_schema=vol.Schema(
246 CONF_USERNAME, default=self.
_reauth_data_reauth_data[CONF_USERNAME]
252 self.
_reauth_data_reauth_data[CONF_USERNAME] = user_input[CONF_USERNAME]
258 """Get application api key."""
263 self.
_user_input_user_input[CONF_API_KEY] = await octoprint.request_app_key(
264 "Home Assistant", self.
_user_input_user_input[CONF_USERNAME], 300
268 """Build an octoprint client from the user_input."""
269 verify_ssl = user_input.get(CONF_VERIFY_SSL,
True)
271 connector = aiohttp.TCPConnector(
277 session = aiohttp.ClientSession(connector=connector)
278 self._sessions.append(session)
280 return OctoprintClient(
281 host=user_input[CONF_HOST],
283 port=user_input[CONF_PORT],
284 ssl=user_input[CONF_SSL],
285 path=user_input[CONF_PATH],
289 """Detach the session."""
290 for session
in self._sessions:
295 """Error to indicate we cannot connect."""
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult async_step_get_api_key(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
ConfigFlowResult _finish_config(self, dict[str, Any] user_input)
ConfigFlowResult async_step_import(self, dict[str, Any] import_data)
None _async_get_auth_key(self)
ConfigFlowResult async_step_reauth_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_auth_failed(self, None user_input)
OctoprintClient _get_octoprint_client(self, dict[str, Any] user_input)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_zeroconf(self, zeroconf.ZeroconfServiceInfo discovery_info)
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)
_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_progress(self, *str|None step_id=None, str progress_action, Mapping[str, str]|None description_placeholders=None, asyncio.Task[Any]|None progress_task=None)
_FlowResultT async_show_progress_done(self, *str next_step_id)
_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 _schema_with_defaults(username="", host="", port=80, path="/", ssl=False, verify_ssl=True)
ssl.SSLContext get_default_context()
ssl.SSLContext get_default_no_verify_context()