1 """Config flow for Nanoleaf integration."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
8 from typing
import Any, Final, cast
10 from aionanoleaf
import InvalidToken, Nanoleaf, Unauthorized, Unavailable
11 import voluptuous
as vol
20 from .const
import DOMAIN
22 _LOGGER = logging.getLogger(__name__)
25 CONFIG_FILE: Final =
".nanoleaf.conf"
27 USER_SCHEMA: Final = vol.Schema(
29 vol.Required(CONF_HOST): str,
35 """Nanoleaf config flow."""
40 discovery_conf: JsonObjectType
46 self, user_input: dict[str, Any] |
None =
None
47 ) -> ConfigFlowResult:
48 """Handle Nanoleaf flow initiated by the user."""
49 if user_input
is None:
51 step_id=
"user", data_schema=USER_SCHEMA, last_step=
False
58 await self.
nanoleafnanoleaf.authorize()
62 data_schema=USER_SCHEMA,
63 errors={
"base":
"cannot_connect"},
69 _LOGGER.exception(
"Unknown error connecting to Nanoleaf")
72 data_schema=USER_SCHEMA,
74 errors={
"base":
"unknown"},
79 self, entry_data: Mapping[str, Any]
80 ) -> ConfigFlowResult:
81 """Handle Nanoleaf reauth flow if token is invalid."""
85 self.context[
"title_placeholders"] = {
"name": self.
_get_reauth_entry_get_reauth_entry().title}
89 self, discovery_info: zeroconf.ZeroconfServiceInfo
90 ) -> ConfigFlowResult:
91 """Handle Nanoleaf Zeroconf discovery."""
92 _LOGGER.debug(
"Zeroconf discovered: %s", discovery_info)
96 self, discovery_info: zeroconf.ZeroconfServiceInfo
97 ) -> ConfigFlowResult:
98 """Handle Nanoleaf Homekit discovery."""
99 _LOGGER.debug(
"Homekit discovered: %s", discovery_info)
103 self, discovery_info: zeroconf.ZeroconfServiceInfo
104 ) -> ConfigFlowResult:
105 """Handle Nanoleaf Homekit and Zeroconf discovery."""
108 discovery_info.name.replace(f
".{discovery_info.type}",
""),
109 discovery_info.properties[zeroconf.ATTR_PROPERTIES_ID],
113 self, discovery_info: ssdp.SsdpServiceInfo
114 ) -> ConfigFlowResult:
115 """Handle Nanoleaf SSDP discovery."""
116 _LOGGER.debug(
"SSDP discovered: %s", discovery_info)
118 discovery_info.ssdp_headers[
"_host"],
119 discovery_info.ssdp_headers[
"nl-devicename"],
120 discovery_info.ssdp_headers[
"nl-deviceid"],
124 self, host: str, name: str, device_id: str
125 ) -> ConfigFlowResult:
126 """Handle Nanoleaf discovery."""
134 load_json_object, self.hass.config.path(CONFIG_FILE)
137 auth_token: JsonValueType =
None
139 auth_token = cast(JsonObjectType, device_conf).
get(
"token")
140 if not auth_token
and (host_conf := self.
discovery_confdiscovery_conf.
get(host)):
141 auth_token = cast(JsonObjectType, host_conf).
get(
"token")
143 if auth_token
is not None:
148 "Importing Nanoleaf %s from the discovery integration", name
150 return await self.
async_setup_finishasync_setup_finish(discovery_integration_import=
True)
152 self.context[
"title_placeholders"] = {
"name": name}
156 self, user_input: dict[str, Any] |
None =
None
157 ) -> ConfigFlowResult:
158 """Handle Nanoleaf link step."""
159 if user_input
is None:
163 await self.
nanoleafnanoleaf.authorize()
166 step_id=
"link", errors={
"base":
"not_allowing_new_tokens"}
171 _LOGGER.exception(
"Unknown error authorizing Nanoleaf")
177 data_updates={CONF_TOKEN: self.
nanoleafnanoleaf.auth_token},
183 self, discovery_integration_import: bool =
False
184 ) -> ConfigFlowResult:
185 """Finish Nanoleaf config flow."""
194 "Unknown error connecting with Nanoleaf at %s", self.
nanoleafnanoleaf.host
202 if discovery_integration_import:
208 "Successfully imported Nanoleaf %s from the discovery integration",
212 await self.hass.async_add_executor_job(
213 save_json, self.hass.config.path(CONFIG_FILE), self.
discovery_confdiscovery_conf
216 await self.hass.async_add_executor_job(
217 os.remove, self.hass.config.path(CONFIG_FILE)
223 CONF_HOST: self.
nanoleafnanoleaf.host,
224 CONF_TOKEN: self.
nanoleafnanoleaf.auth_token,
ConfigFlowResult async_step_link(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult _async_discovery_handler(self, str host, str name, str device_id)
ConfigFlowResult async_step_homekit(self, zeroconf.ZeroconfServiceInfo discovery_info)
ConfigFlowResult _async_homekit_zeroconf_discovery_handler(self, zeroconf.ZeroconfServiceInfo discovery_info)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
ConfigFlowResult async_setup_finish(self, bool discovery_integration_import=False)
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 _get_reauth_entry(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_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)
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)
_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)
web.Response get(self, web.Request request, str config_key)
dict[str, Any]|None get_info(HomeAssistant hass)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)