1 """Config flow for WattTime integration."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
6 from typing
import TYPE_CHECKING, Any
8 from aiowatttime
import Client
9 from aiowatttime.errors
import CoordinatesNotFoundError, InvalidCredentialsError
10 import voluptuous
as vol
29 CONF_BALANCING_AUTHORITY,
30 CONF_BALANCING_AUTHORITY_ABBREV,
35 CONF_LOCATION_TYPE =
"location_type"
37 LOCATION_TYPE_COORDINATES =
"Specify coordinates"
38 LOCATION_TYPE_HOME =
"Use home location"
40 STEP_COORDINATES_DATA_SCHEMA = vol.Schema(
42 vol.Required(CONF_LATITUDE): cv.latitude,
43 vol.Required(CONF_LONGITUDE): cv.longitude,
47 STEP_LOCATION_DATA_SCHEMA = vol.Schema(
49 vol.Required(CONF_LOCATION_TYPE): vol.In(
50 [LOCATION_TYPE_HOME, LOCATION_TYPE_COORDINATES]
55 STEP_REAUTH_CONFIRM_DATA_SCHEMA = vol.Schema(
57 vol.Required(CONF_PASSWORD): str,
61 STEP_USER_DATA_SCHEMA = vol.Schema(
63 vol.Required(CONF_USERNAME): str,
64 vol.Required(CONF_PASSWORD): str,
71 """Get a unique ID from a data payload."""
72 return f
"{data[CONF_LATITUDE]}, {data[CONF_LONGITUDE]}"
76 """Handle a config flow for WattTime."""
82 self.
_client_client: Client |
None =
None
83 self.
_data_data: dict[str, Any] = {}
86 self, username: str, password: str, error_step_id: str, error_schema: vol.Schema
87 ) -> ConfigFlowResult:
88 """Validate input credentials and proceed accordingly."""
89 session = aiohttp_client.async_get_clientsession(self.hass)
92 self.
_client_client = await Client.async_login(username, password, session=session)
93 except InvalidCredentialsError:
95 step_id=error_step_id,
96 data_schema=error_schema,
97 errors={
"base":
"invalid_auth"},
98 description_placeholders={CONF_USERNAME: username},
100 except Exception
as err:
101 LOGGER.exception(
"Unexpected exception while logging in: %s", err)
103 step_id=error_step_id,
104 data_schema=error_schema,
105 errors={
"base":
"unknown"},
106 description_placeholders={CONF_USERNAME: username},
109 if CONF_LATITUDE
in self.
_data_data:
114 self.hass.config_entries.async_update_entry(
115 existing_entry, data=self.
_data_data
117 self.hass.async_create_task(
118 self.hass.config_entries.async_reload(existing_entry.entry_id)
123 self.
_data_data[CONF_USERNAME] = username
124 self.
_data_data[CONF_PASSWORD] = password
130 config_entry: ConfigEntry,
131 ) -> WattTimeOptionsFlowHandler:
132 """Define the config flow to handle options."""
136 self, user_input: dict[str, Any] |
None =
None
137 ) -> ConfigFlowResult:
138 """Handle the coordinates step."""
141 step_id=
"coordinates", data_schema=STEP_COORDINATES_DATA_SCHEMA
152 grid_region = await self.
_client_client.emissions.async_get_grid_region(
153 user_input[CONF_LATITUDE], user_input[CONF_LONGITUDE]
155 except CoordinatesNotFoundError:
157 step_id=
"coordinates",
158 data_schema=STEP_COORDINATES_DATA_SCHEMA,
159 errors={CONF_LATITUDE:
"unknown_coordinates"},
161 except Exception
as err:
162 LOGGER.exception(
"Unexpected exception while getting region: %s", err)
164 step_id=
"coordinates",
165 data_schema=STEP_COORDINATES_DATA_SCHEMA,
166 errors={
"base":
"unknown"},
172 CONF_USERNAME: self.
_data_data[CONF_USERNAME],
173 CONF_PASSWORD: self.
_data_data[CONF_PASSWORD],
174 CONF_LATITUDE: user_input[CONF_LATITUDE],
175 CONF_LONGITUDE: user_input[CONF_LONGITUDE],
176 CONF_BALANCING_AUTHORITY: grid_region[
"name"],
177 CONF_BALANCING_AUTHORITY_ABBREV: grid_region[
"abbrev"],
182 self, user_input: dict[str, Any] |
None =
None
183 ) -> ConfigFlowResult:
184 """Handle the "pick a location" step."""
187 step_id=
"location", data_schema=STEP_LOCATION_DATA_SCHEMA
190 if user_input[CONF_LOCATION_TYPE] == LOCATION_TYPE_HOME:
193 CONF_LATITUDE: self.hass.config.latitude,
194 CONF_LONGITUDE: self.hass.config.longitude,
200 self, entry_data: Mapping[str, Any]
201 ) -> ConfigFlowResult:
202 """Handle configuration by re-auth."""
207 self, user_input: dict[str, Any] |
None =
None
208 ) -> ConfigFlowResult:
209 """Handle re-auth completion."""
212 step_id=
"reauth_confirm",
213 data_schema=STEP_REAUTH_CONFIRM_DATA_SCHEMA,
214 description_placeholders={CONF_USERNAME: self.
_data_data[CONF_USERNAME]},
217 self.
_data_data[CONF_PASSWORD] = user_input[CONF_PASSWORD]
220 self.
_data_data[CONF_USERNAME],
221 self.
_data_data[CONF_PASSWORD],
223 STEP_REAUTH_CONFIRM_DATA_SCHEMA,
227 self, user_input: dict[str, Any] |
None =
None
228 ) -> ConfigFlowResult:
229 """Handle the initial step."""
232 step_id=
"user", data_schema=STEP_USER_DATA_SCHEMA
236 user_input[CONF_USERNAME],
237 user_input[CONF_PASSWORD],
239 STEP_USER_DATA_SCHEMA,
244 """Handle a WattTime options flow."""
247 self, user_input: dict[str, Any] |
None =
None
248 ) -> ConfigFlowResult:
249 """Manage the options."""
250 if user_input
is not None:
255 data_schema=vol.Schema(
ConfigFlowResult async_step_location(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_coordinates(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_reauth_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
ConfigFlowResult _async_validate_credentials(self, str username, str password, str error_step_id, vol.Schema error_schema)
WattTimeOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
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_abort(self, *str reason, 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)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_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)
str get_unique_id(dict[str, Any] data)