-
-
Notifications
You must be signed in to change notification settings - Fork 33.4k
/
Copy pathconfig_flow.py
158 lines (129 loc) · 5.07 KB
/
config_flow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""Config flow for Shark IQ integration."""
from __future__ import annotations
import asyncio
from collections.abc import Mapping
from typing import Any
import aiohttp
from sharkiq import SharkIqAuthError, get_ayla_api
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_PASSWORD, CONF_REGION, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import selector
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import (
DOMAIN,
LOGGER,
SHARKIQ_REGION_DEFAULT,
SHARKIQ_REGION_EUROPE,
SHARKIQ_REGION_OPTIONS,
)
SHARKIQ_SCHEMA = vol.Schema(
{
vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
vol.Required(
CONF_REGION, default=SHARKIQ_REGION_DEFAULT
): selector.SelectSelector(
selector.SelectSelectorConfig(
options=SHARKIQ_REGION_OPTIONS, translation_key="region"
),
),
}
)
async def _validate_input(
hass: HomeAssistant, data: Mapping[str, Any]
) -> dict[str, str]:
"""Validate the user input allows us to connect."""
ayla_api = get_ayla_api(
username=data[CONF_USERNAME],
password=data[CONF_PASSWORD],
websession=async_get_clientsession(hass),
europe=(data[CONF_REGION] == SHARKIQ_REGION_EUROPE),
)
try:
async with asyncio.timeout(10):
LOGGER.debug("Initialize connection to Ayla networks API")
await ayla_api.async_sign_in()
except (TimeoutError, aiohttp.ClientError, TypeError) as error:
LOGGER.error(error)
raise CannotConnect(
"Unable to connect to SharkIQ services. Check your region settings."
) from error
except SharkIqAuthError as error:
LOGGER.error(error)
raise InvalidAuth(
"Username or password incorrect. Please check your credentials."
) from error
except Exception as error:
LOGGER.exception("Unexpected exception")
LOGGER.error(error)
raise UnknownAuth(
"An unknown error occurred. Check your region settings and open an issue on Github if the issue persists."
) from error
# Return info that you want to store in the config entry.
return {"title": data[CONF_USERNAME]}
class SharkIqConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Shark IQ."""
VERSION = 1
async def _async_validate_input(
self, user_input: Mapping[str, Any]
) -> tuple[dict[str, str] | None, dict[str, str]]:
"""Validate form input."""
errors = {}
info = None
# noinspection PyBroadException
try:
info = await _validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except InvalidAuth:
errors["base"] = "invalid_auth"
except UnknownAuth:
errors["base"] = "unknown"
return info, errors
async def async_step_user(
self, user_input: dict[str, str] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
info, errors = await self._async_validate_input(user_input)
if info:
await self.async_set_unique_id(user_input[CONF_USERNAME])
self._abort_if_unique_id_configured()
return self.async_create_entry(title=info["title"], data=user_input)
return self.async_show_form(
step_id="user", data_schema=SHARKIQ_SCHEMA, errors=errors
)
async def async_step_reauth(
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle re-auth if login is invalid."""
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow initiated by reauthentication."""
errors: dict[str, str] = {}
if user_input is not None:
_, errors = await self._async_validate_input(user_input)
if not errors:
errors = {"base": "unknown"}
if entry := await self.async_set_unique_id(self.unique_id):
self.hass.config_entries.async_update_entry(entry, data=user_input)
return self.async_abort(reason="reauth_successful")
if errors["base"] != "invalid_auth":
return self.async_abort(reason=errors["base"])
return self.async_show_form(
step_id="reauth_confirm",
data_schema=SHARKIQ_SCHEMA,
errors=errors,
)
class CannotConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""
class InvalidAuth(HomeAssistantError):
"""Error to indicate there is invalid auth."""
class UnknownAuth(HomeAssistantError):
"""Error to indicate there is an uncaught auth error."""