1 """Config flow for HomeWizard."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
7 from typing
import Any, NamedTuple
9 from homewizard_energy
import HomeWizardEnergyV1
10 from homewizard_energy.errors
import DisabledError, RequestError, UnsupportedError
11 from homewizard_energy.v1.models
import Device
12 import voluptuous
as vol
30 _LOGGER = logging.getLogger(__name__)
43 """Handle a config flow for P1 meter."""
47 discovery: DiscoveryData
50 self, user_input: dict[str, Any] |
None =
None
51 ) -> ConfigFlowResult:
52 """Handle a flow initiated by the user."""
53 errors: dict[str, str] |
None =
None
54 if user_input
is not None:
56 device_info = await self.
_async_try_connect_async_try_connect(user_input[CONF_IP_ADDRESS])
57 except RecoverableError
as ex:
59 errors = {
"base": ex.error_code}
62 f
"{device_info.product_type}_{device_info.serial}"
66 title=f
"{device_info.product_name}",
70 user_input = user_input
or {}
73 data_schema=vol.Schema(
76 CONF_IP_ADDRESS, default=user_input.get(CONF_IP_ADDRESS)
84 self, discovery_info: zeroconf.ZeroconfServiceInfo
85 ) -> ConfigFlowResult:
86 """Handle zeroconf discovery."""
88 CONF_API_ENABLED
not in discovery_info.properties
89 or CONF_PATH
not in discovery_info.properties
90 or CONF_PRODUCT_NAME
not in discovery_info.properties
91 or CONF_PRODUCT_TYPE
not in discovery_info.properties
92 or CONF_SERIAL
not in discovery_info.properties
96 if (discovery_info.properties[CONF_PATH]) !=
"/api/v1":
100 ip=discovery_info.host,
101 product_type=discovery_info.properties[CONF_PRODUCT_TYPE],
102 product_name=discovery_info.properties[CONF_PRODUCT_NAME],
103 serial=discovery_info.properties[CONF_SERIAL],
107 f
"{self.discovery.product_type}_{self.discovery.serial}"
110 updates={CONF_IP_ADDRESS: discovery_info.host}
116 self, discovery_info: DhcpServiceInfo
117 ) -> ConfigFlowResult:
118 """Handle dhcp discovery to update existing entries.
120 This flow is triggered only by DHCP discovery of known devices.
124 except RecoverableError
as ex:
129 f
"{device.product_type}_{discovery_info.macaddress}"
133 updates={CONF_IP_ADDRESS: discovery_info.ip}
142 self, user_input: dict[str, Any] |
None =
None
143 ) -> ConfigFlowResult:
144 """Confirm discovery."""
145 errors: dict[str, str] |
None =
None
146 if user_input
is not None or not onboarding.async_is_onboarded(self.hass):
149 except RecoverableError
as ex:
151 errors = {
"base": ex.error_code}
154 title=self.
discoverydiscovery.product_name,
155 data={CONF_IP_ADDRESS: self.
discoverydiscovery.ip},
162 name = self.
discoverydiscovery.product_name
163 if self.
discoverydiscovery.product_type
not in [
"HWE-P1",
"HWE-WTR"]:
164 name = f
"{name} ({self.discovery.serial})"
165 self.context[
"title_placeholders"] = {
"name": name}
168 step_id=
"discovery_confirm",
169 description_placeholders={
170 CONF_PRODUCT_TYPE: self.
discoverydiscovery.product_type,
171 CONF_SERIAL: self.
discoverydiscovery.serial,
172 CONF_IP_ADDRESS: self.
discoverydiscovery.ip,
178 self, entry_data: Mapping[str, Any]
179 ) -> ConfigFlowResult:
180 """Handle re-auth if API was disabled."""
184 self, user_input: dict[str, Any] |
None =
None
185 ) -> ConfigFlowResult:
186 """Confirm reauth dialog."""
187 errors: dict[str, str] |
None =
None
188 if user_input
is not None:
192 except RecoverableError
as ex:
194 errors = {
"base": ex.error_code}
196 await self.hass.config_entries.async_reload(reauth_entry.entry_id)
202 self, user_input: dict[str, Any] |
None =
None
203 ) -> ConfigFlowResult:
204 """Handle reconfiguration of the integration."""
205 errors: dict[str, str] = {}
208 device_info = await self.
_async_try_connect_async_try_connect(user_input[CONF_IP_ADDRESS])
209 except RecoverableError
as ex:
211 errors = {
"base": ex.error_code}
214 f
"{device_info.product_type}_{device_info.serial}"
219 data_updates=user_input,
223 step_id=
"reconfigure",
224 data_schema=vol.Schema(
228 default=reconfigure_entry.data.get(CONF_IP_ADDRESS),
232 description_placeholders={
233 "title": reconfigure_entry.title,
242 Make connection with device to test the connection
243 and to get info for unique_id.
245 energy_api = HomeWizardEnergyV1(ip_address)
247 return await energy_api.device()
249 except DisabledError
as ex:
251 "API disabled, API must be enabled in the app",
"api_not_enabled"
254 except UnsupportedError
as ex:
255 _LOGGER.error(
"API version unsuppored")
256 raise AbortFlow(
"unsupported_api_version")
from ex
258 except RequestError
as ex:
260 "Device unreachable or unexpected response",
"network_error"
263 except Exception
as ex:
264 _LOGGER.exception(
"Unexpected exception")
268 await energy_api.close()
272 """Raised when a connection has been failed but can be retried."""
274 def __init__(self, message: str, error_code: str) ->
None:
275 """Init RecoverableError."""
ConfigFlowResult async_step_reauth_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_zeroconf(self, zeroconf.ZeroconfServiceInfo discovery_info)
ConfigFlowResult async_step_reconfigure(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_dhcp(self, DhcpServiceInfo discovery_info)
ConfigFlowResult async_step_discovery_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Device _async_try_connect(str ip_address)
None __init__(self, str message, str error_code)
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)
None _set_confirm_only(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)
ConfigEntry _get_reconfigure_entry(self)
None _abort_if_unique_id_mismatch(self, *str reason="unique_id_mismatch", Mapping[str, str]|None description_placeholders=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)