Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for growatt server integration."""
2 
3 from typing import Any
4 
5 import growattServer
6 import voluptuous as vol
7 
8 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
9 from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_URL, CONF_USERNAME
10 from homeassistant.core import callback
11 
12 from .const import (
13  CONF_PLANT_ID,
14  DEFAULT_URL,
15  DOMAIN,
16  LOGIN_INVALID_AUTH_CODE,
17  SERVER_URLS,
18 )
19 
20 
21 class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
22  """Config flow class."""
23 
24  VERSION = 1
25 
26  api: growattServer.GrowattApi
27 
28  def __init__(self) -> None:
29  """Initialise growatt server flow."""
30  self.user_iduser_id = None
31  self.datadata: dict[str, Any] = {}
32 
33  @callback
34  def _async_show_user_form(self, errors=None):
35  """Show the form to the user."""
36  data_schema = vol.Schema(
37  {
38  vol.Required(CONF_USERNAME): str,
39  vol.Required(CONF_PASSWORD): str,
40  vol.Required(CONF_URL, default=DEFAULT_URL): vol.In(SERVER_URLS),
41  }
42  )
43 
44  return self.async_show_formasync_show_formasync_show_form(
45  step_id="user", data_schema=data_schema, errors=errors
46  )
47 
48  async def async_step_user(
49  self, user_input: dict[str, Any] | None = None
50  ) -> ConfigFlowResult:
51  """Handle the start of the config flow."""
52  if not user_input:
53  return self._async_show_user_form_async_show_user_form()
54 
55  # Initialise the library with the username & a random id each time it is started
56  self.apiapi = growattServer.GrowattApi(
57  add_random_user_id=True, agent_identifier=user_input[CONF_USERNAME]
58  )
59  self.apiapi.server_url = user_input[CONF_URL]
60  login_response = await self.hass.async_add_executor_job(
61  self.apiapi.login, user_input[CONF_USERNAME], user_input[CONF_PASSWORD]
62  )
63 
64  if (
65  not login_response["success"]
66  and login_response["msg"] == LOGIN_INVALID_AUTH_CODE
67  ):
68  return self._async_show_user_form_async_show_user_form({"base": "invalid_auth"})
69  self.user_iduser_id = login_response["user"]["id"]
70 
71  self.datadata = user_input
72  return await self.async_step_plantasync_step_plant()
73 
74  async def async_step_plant(
75  self, user_input: dict[str, Any] | None = None
76  ) -> ConfigFlowResult:
77  """Handle adding a "plant" to Home Assistant."""
78  plant_info = await self.hass.async_add_executor_job(
79  self.apiapi.plant_list, self.user_iduser_id
80  )
81 
82  if not plant_info["data"]:
83  return self.async_abortasync_abortasync_abort(reason="no_plants")
84 
85  plants = {plant["plantId"]: plant["plantName"] for plant in plant_info["data"]}
86 
87  if user_input is None and len(plant_info["data"]) > 1:
88  data_schema = vol.Schema({vol.Required(CONF_PLANT_ID): vol.In(plants)})
89 
90  return self.async_show_formasync_show_formasync_show_form(step_id="plant", data_schema=data_schema)
91 
92  if user_input is None:
93  # single plant => mark it as selected
94  user_input = {CONF_PLANT_ID: plant_info["data"][0]["plantId"]}
95 
96  user_input[CONF_NAME] = plants[user_input[CONF_PLANT_ID]]
97  await self.async_set_unique_idasync_set_unique_id(user_input[CONF_PLANT_ID])
98  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
99  self.datadata.update(user_input)
100  return self.async_create_entryasync_create_entryasync_create_entry(title=self.datadata[CONF_NAME], data=self.datadata)
ConfigFlowResult async_step_plant(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:76
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:50
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)
_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)
IssData update(pyiss.ISS iss)
Definition: __init__.py:33