-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
/
config_flow.py
138 lines (113 loc) · 4.59 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
"""Config flow to configure the Obihai integration."""
from __future__ import annotations
from socket import gaierror, gethostbyname
from typing import Any
from pyobihai import PyObihai
import voluptuous as vol
from homeassistant.components import dhcp
from homeassistant.config_entries import ConfigFlow
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.device_registry import format_mac
from .connectivity import validate_auth
from .const import DEFAULT_PASSWORD, DEFAULT_USERNAME, DOMAIN
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Required(
CONF_USERNAME,
default=DEFAULT_USERNAME,
): str,
vol.Required(
CONF_PASSWORD,
default=DEFAULT_PASSWORD,
): str,
}
)
async def async_validate_creds(
hass: HomeAssistant, user_input: dict[str, Any]
) -> PyObihai | None:
"""Manage Obihai options."""
if user_input[CONF_USERNAME] and user_input[CONF_PASSWORD]:
return await hass.async_add_executor_job(
validate_auth,
user_input[CONF_HOST],
user_input[CONF_USERNAME],
user_input[CONF_PASSWORD],
)
# Don't bother authenticating if we've already determined the credentials are invalid
return None
class ObihaiFlowHandler(ConfigFlow, domain=DOMAIN):
"""Config flow for Obihai."""
VERSION = 2
discovery_schema: vol.Schema | None = None
_dhcp_discovery_info: dhcp.DhcpServiceInfo | None = None
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle a flow initialized by the user."""
errors: dict[str, str] = {}
ip: str | None = None
if user_input is not None:
try:
ip = await self.hass.async_add_executor_job(
gethostbyname, user_input[CONF_HOST]
)
except gaierror:
errors["base"] = "cannot_connect"
if ip:
if pyobihai := await async_validate_creds(self.hass, user_input):
device_mac = await self.hass.async_add_executor_job(
pyobihai.get_device_mac
)
await self.async_set_unique_id(format_mac(device_mac))
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=user_input[CONF_HOST],
data=user_input,
)
errors["base"] = "invalid_auth"
data_schema = self.discovery_schema or DATA_SCHEMA
return self.async_show_form(
step_id="user",
errors=errors,
data_schema=self.add_suggested_values_to_schema(data_schema, user_input),
)
async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowResult:
"""Prepare configuration for a DHCP discovered Obihai."""
self._dhcp_discovery_info = discovery_info
return await self.async_step_dhcp_confirm()
async def async_step_dhcp_confirm(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Attempt to confirm."""
assert self._dhcp_discovery_info
await self.async_set_unique_id(format_mac(self._dhcp_discovery_info.macaddress))
self._abort_if_unique_id_configured()
if user_input is None:
credentials = {
CONF_HOST: self._dhcp_discovery_info.ip,
CONF_PASSWORD: DEFAULT_PASSWORD,
CONF_USERNAME: DEFAULT_USERNAME,
}
if await async_validate_creds(self.hass, credentials):
self.discovery_schema = self.add_suggested_values_to_schema(
DATA_SCHEMA, credentials
)
else:
self.discovery_schema = self.add_suggested_values_to_schema(
DATA_SCHEMA,
{
CONF_HOST: self._dhcp_discovery_info.ip,
CONF_USERNAME: "",
CONF_PASSWORD: "",
},
)
# Show the confirmation dialog
return self.async_show_form(
step_id="dhcp_confirm",
data_schema=self.discovery_schema,
description_placeholders={CONF_HOST: self._dhcp_discovery_info.ip},
)
return await self.async_step_user(user_input=user_input)