22
33from __future__ import annotations
44
5- import datetime as dt # pw-beta options
65from typing import Any
76
87from plugwise import Smile
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
112112async 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(
280275class 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