Skip to content

Commit 03dcb7a

Browse files
authored
Merge pull request #736 from plugwise/config_flow
Improve config_flow coding
2 parents e737bd4 + 77a43bc commit 03dcb7a

File tree

2 files changed

+60
-67
lines changed

2 files changed

+60
-67
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Versions from 0.40 and up
44

5+
## Ongoing
6+
7+
- Improve / clean up config_flow code.
8+
59
## v0.53.3
610

711
- Test-code improvements.

custom_components/plugwise/config_flow.py

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from __future__ import annotations
44

5-
import datetime as dt # pw-beta options
65
from typing import Any
76

87
from plugwise import Smile
@@ -79,40 +78,41 @@
7978
# Upstream basically the whole file (excluding the pw-beta options)
8079

8180

82-
def _base_schema(
83-
discovery_info: ZeroconfServiceInfo | None,
84-
user_input: dict[str, Any] | None,
81+
def base_schema(
82+
cf_input: ZeroconfServiceInfo | dict[str, Any] | None,
8583
) -> vol.Schema:
8684
"""Generate base schema for gateways."""
87-
if not discovery_info:
88-
if not user_input:
89-
return vol.Schema(
90-
{
91-
vol.Required(CONF_PASSWORD): str,
92-
vol.Required(CONF_HOST): str,
93-
vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
94-
vol.Required(CONF_USERNAME, default=SMILE): vol.In(
95-
{SMILE: FLOW_SMILE, STRETCH: FLOW_STRETCH}
96-
),
97-
}
98-
)
85+
if not cf_input: # no discovery- or user-input available
9986
return vol.Schema(
10087
{
101-
vol.Required(CONF_PASSWORD, default=user_input[CONF_PASSWORD]): str,
102-
vol.Required(CONF_HOST, default=user_input[CONF_HOST]): str,
103-
vol.Optional(CONF_PORT, default=user_input[CONF_PORT]): int,
104-
vol.Required(CONF_USERNAME, default=user_input[CONF_USERNAME]): vol.In(
88+
vol.Required(CONF_HOST): str,
89+
vol.Required(CONF_PASSWORD): str,
90+
vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
91+
vol.Required(CONF_USERNAME, default=SMILE): vol.In(
10592
{SMILE: FLOW_SMILE, STRETCH: FLOW_STRETCH}
10693
),
10794
}
10895
)
109-
return vol.Schema({vol.Required(CONF_PASSWORD): str})
96+
97+
if isinstance(cf_input, ZeroconfServiceInfo):
98+
return vol.Schema({vol.Required(CONF_PASSWORD): str})
99+
100+
return vol.Schema(
101+
{
102+
vol.Required(CONF_HOST, default=cf_input[CONF_HOST]): str,
103+
vol.Required(CONF_PASSWORD, default=cf_input[CONF_PASSWORD]): str,
104+
vol.Optional(CONF_PORT, default=cf_input[CONF_PORT]): int,
105+
vol.Required(CONF_USERNAME, default=cf_input[CONF_USERNAME]): vol.In(
106+
{SMILE: FLOW_SMILE, STRETCH: FLOW_STRETCH}
107+
),
108+
}
109+
)
110110

111111

112112
async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> Smile:
113113
"""Validate whether the user input allows us to connect to the gateway.
114114
115-
Data has the keys from _base_schema() with values provided by the user.
115+
Data has the keys from base_schema() with values provided by the user.
116116
"""
117117
websession = async_get_clientsession(hass, verify_ssl=False)
118118
api = Smile(
@@ -134,8 +134,8 @@ class PlugwiseConfigFlow(ConfigFlow, domain=DOMAIN):
134134
MINOR_VERSION = 2
135135

136136
discovery_info: ZeroconfServiceInfo | None = None
137-
_username: str = DEFAULT_USERNAME
138137
_timeout: int = DEFAULT_TIMEOUT
138+
_username: str = DEFAULT_USERNAME
139139

140140
async def async_step_zeroconf(
141141
self, discovery_info: ZeroconfServiceInfo
@@ -169,7 +169,7 @@ async def async_step_zeroconf(
169169

170170
if DEFAULT_USERNAME not in unique_id:
171171
self._username = STRETCH_USERNAME
172-
_product = _properties.get(PRODUCT, None)
172+
_product = _properties.get(PRODUCT, "Unknown Smile")
173173
_version = _properties.get(VERSION, "n/a")
174174
_name = f"{ZEROCONF_MAP.get(_product, _product)} v{_version}"
175175

@@ -203,13 +203,7 @@ async def async_step_zeroconf(
203203

204204
self.context.update(
205205
{
206-
TITLE_PLACEHOLDERS: {
207-
CONF_HOST: discovery_info.host,
208-
CONF_NAME: _name,
209-
CONF_PORT: discovery_info.port,
210-
CONF_TIMEOUT: self._timeout,
211-
CONF_USERNAME: self._username,
212-
},
206+
TITLE_PLACEHOLDERS: {CONF_NAME: _name},
213207
ATTR_CONFIGURATION_URL: (
214208
f"http://{discovery_info.host}:{discovery_info.port}"
215209
),
@@ -227,7 +221,7 @@ async def async_step_user(
227221
if not user_input:
228222
return self.async_show_form(
229223
step_id=SOURCE_USER,
230-
data_schema=_base_schema(self.discovery_info, None),
224+
data_schema=base_schema(self.discovery_info),
231225
errors=errors,
232226
)
233227

@@ -236,6 +230,7 @@ async def async_step_user(
236230
user_input[CONF_PORT] = self.discovery_info.port
237231
user_input[CONF_USERNAME] = self._username
238232

233+
# Ensure a timeout-value is available, required for validation
239234
user_input[CONF_TIMEOUT] = self._timeout
240235
try:
241236
api = await validate_input(self.hass, user_input)
@@ -255,7 +250,7 @@ async def async_step_user(
255250
if errors:
256251
return self.async_show_form(
257252
step_id=SOURCE_USER,
258-
data_schema=_base_schema(None, user_input),
253+
data_schema=base_schema(user_input),
259254
errors=errors,
260255
)
261256

@@ -280,6 +275,29 @@ def async_get_options_flow(
280275
class PlugwiseOptionsFlowHandler(OptionsFlowWithConfigEntry): # pw-beta options
281276
"""Plugwise option flow."""
282277

278+
def _create_options_schema(self, coordinator):
279+
interval = DEFAULT_SCAN_INTERVAL[coordinator.api.smile_type] # pw-beta options
280+
schema = {
281+
vol.Optional(
282+
CONF_SCAN_INTERVAL,
283+
default=self._options.get(CONF_SCAN_INTERVAL, interval.seconds),
284+
): vol.All(cv.positive_int, vol.Clamp(min=10)),
285+
} # pw-beta
286+
287+
if coordinator.api.smile_type == THERMOSTAT:
288+
schema.update({
289+
vol.Optional(
290+
CONF_HOMEKIT_EMULATION,
291+
default=self._options.get(CONF_HOMEKIT_EMULATION, False),
292+
): vol.All(cv.boolean),
293+
vol.Optional(
294+
CONF_REFRESH_INTERVAL,
295+
default=self._options.get(CONF_REFRESH_INTERVAL, 1.5),
296+
): vol.All(vol.Coerce(float), vol.Range(min=1.5, max=10.0)),
297+
}) # pw-beta
298+
299+
return vol.Schema(schema)
300+
283301
async def async_step_none(
284302
self, user_input: dict[str, Any] | None = None
285303
) -> ConfigFlowResult: # pragma: no cover
@@ -289,9 +307,7 @@ async def async_step_none(
289307
return self.async_create_entry(title="", data=self._options)
290308
return self.async_show_form(step_id="none")
291309

292-
async def async_step_init(
293-
self, user_input: dict[str, Any] | None = None
294-
) -> ConfigFlowResult: # pragma: no cover
310+
async def async_step_init(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
295311
"""Manage the Plugwise options."""
296312
if not self.config_entry.data.get(CONF_HOST):
297313
return await self.async_step_none(user_input)
@@ -300,34 +316,7 @@ async def async_step_init(
300316
return self.async_create_entry(title="", data=user_input)
301317

302318
coordinator = self.config_entry.runtime_data
303-
interval: dt.timedelta = DEFAULT_SCAN_INTERVAL[
304-
coordinator.api.smile_type
305-
] # pw-beta options
306-
307-
data = {
308-
vol.Optional(
309-
CONF_SCAN_INTERVAL,
310-
default=self._options.get(
311-
CONF_SCAN_INTERVAL, interval.seconds
312-
),
313-
): vol.All(cv.positive_int, vol.Clamp(min=10)),
314-
} # pw-beta
315-
316-
if coordinator.api.smile_type != THERMOSTAT:
317-
return self.async_show_form(step_id=INIT, data_schema=vol.Schema(data))
318-
319-
data.update(
320-
{
321-
vol.Optional(
322-
CONF_HOMEKIT_EMULATION,
323-
default=self._options.get(
324-
CONF_HOMEKIT_EMULATION, False
325-
),
326-
): vol.All(cv.boolean),
327-
vol.Optional(
328-
CONF_REFRESH_INTERVAL,
329-
default=self._options.get(CONF_REFRESH_INTERVAL, 1.5),
330-
): vol.All(vol.Coerce(float), vol.Range(min=1.5, max=10.0)),
331-
}
332-
) # pw-beta
333-
return self.async_show_form(step_id=INIT, data_schema=vol.Schema(data))
319+
return self.async_show_form(
320+
step_id=INIT,
321+
data_schema=self._create_options_schema(coordinator)
322+
)

0 commit comments

Comments
 (0)