Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for HVV integration."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from pygti.auth import GTI_DEFAULT_HOST
9 from pygti.exceptions import CannotConnect, InvalidAuth
10 import voluptuous as vol
11 
12 from homeassistant.config_entries import (
13  ConfigEntry,
14  ConfigFlow,
15  ConfigFlowResult,
16  OptionsFlow,
17 )
18 from homeassistant.const import CONF_HOST, CONF_OFFSET, CONF_PASSWORD, CONF_USERNAME
19 from homeassistant.core import callback
20 from homeassistant.helpers import aiohttp_client
22 
23 from .const import CONF_FILTER, CONF_REAL_TIME, CONF_STATION, DOMAIN
24 from .hub import GTIHub
25 
26 _LOGGER = logging.getLogger(__name__)
27 
28 SCHEMA_STEP_USER = vol.Schema(
29  {
30  vol.Required(CONF_HOST, default=GTI_DEFAULT_HOST): str,
31  vol.Required(CONF_USERNAME): str,
32  vol.Required(CONF_PASSWORD): str,
33  }
34 )
35 
36 SCHEMA_STEP_STATION = vol.Schema({vol.Required(CONF_STATION): str})
37 
38 SCHEMA_STEP_OPTIONS = vol.Schema(
39  {
40  vol.Required(CONF_FILTER): vol.In([]),
41  vol.Required(CONF_OFFSET, default=0): cv.positive_int,
42  vol.Optional(CONF_REAL_TIME, default=True): bool,
43  }
44 )
45 
46 
47 class HVVDeparturesConfigFlow(ConfigFlow, domain=DOMAIN):
48  """Handle a config flow for HVV."""
49 
50  VERSION = 1
51 
52  hub: GTIHub
53  data: dict[str, Any]
54 
55  def __init__(self) -> None:
56  """Initialize component."""
57  self.stationsstations: dict[str, Any] = {}
58 
59  async def async_step_user(
60  self, user_input: dict[str, Any] | None = None
61  ) -> ConfigFlowResult:
62  """Handle the initial step."""
63  errors = {}
64 
65  if user_input is not None:
66  session = aiohttp_client.async_get_clientsession(self.hass)
67  self.hubhub = GTIHub(
68  user_input[CONF_HOST],
69  user_input[CONF_USERNAME],
70  user_input[CONF_PASSWORD],
71  session,
72  )
73 
74  try:
75  response = await self.hubhub.authenticate()
76  _LOGGER.debug("Init gti: %r", response)
77  except CannotConnect:
78  errors["base"] = "cannot_connect"
79  except InvalidAuth:
80  errors["base"] = "invalid_auth"
81 
82  if not errors:
83  self.datadata = user_input
84  return await self.async_step_stationasync_step_station()
85 
86  return self.async_show_formasync_show_formasync_show_form(
87  step_id="user", data_schema=SCHEMA_STEP_USER, errors=errors
88  )
89 
90  async def async_step_station(
91  self, user_input: dict[str, Any] | None = None
92  ) -> ConfigFlowResult:
93  """Handle the step where the user inputs his/her station."""
94  if user_input is not None:
95  errors = {}
96 
97  check_name = await self.hubhub.gti.checkName(
98  {"theName": {"name": user_input[CONF_STATION]}, "maxList": 20}
99  )
100 
101  stations = check_name.get("results")
102 
103  self.stationsstations = {
104  f"{station.get('name')}": station
105  for station in stations
106  if station.get("type") == "STATION"
107  }
108 
109  if not self.stationsstations:
110  errors["base"] = "no_results"
111 
112  return self.async_show_formasync_show_formasync_show_form(
113  step_id="station", data_schema=SCHEMA_STEP_STATION, errors=errors
114  )
115 
116  # schema
117 
118  return await self.async_step_station_selectasync_step_station_select()
119 
120  return self.async_show_formasync_show_formasync_show_form(step_id="station", data_schema=SCHEMA_STEP_STATION)
121 
123  self, user_input: dict[str, Any] | None = None
124  ) -> ConfigFlowResult:
125  """Handle the step where the user inputs his/her station."""
126 
127  schema = vol.Schema({vol.Required(CONF_STATION): vol.In(list(self.stationsstations))})
128 
129  if user_input is None:
130  return self.async_show_formasync_show_formasync_show_form(step_id="station_select", data_schema=schema)
131 
132  self.datadata.update({"station": self.stationsstations[user_input[CONF_STATION]]})
133 
134  title = self.datadata[CONF_STATION]["name"]
135 
136  return self.async_create_entryasync_create_entryasync_create_entry(title=title, data=self.datadata)
137 
138  @staticmethod
139  @callback
141  config_entry: ConfigEntry,
142  ) -> OptionsFlowHandler:
143  """Get options flow."""
144  return OptionsFlowHandler()
145 
146 
148  """Options flow handler."""
149 
150  def __init__(self) -> None:
151  """Initialize HVV Departures options flow."""
152  self.departure_filtersdeparture_filters: dict[str, Any] = {}
153 
154  async def async_step_init(
155  self, user_input: dict[str, Any] | None = None
156  ) -> ConfigFlowResult:
157  """Manage the options."""
158  errors = {}
159  if not self.departure_filtersdeparture_filters:
160  departure_list = {}
161  hub: GTIHub = self.hass.data[DOMAIN][self.config_entryconfig_entryconfig_entry.entry_id]
162 
163  try:
164  departure_list = await hub.gti.departureList(
165  {
166  "station": {
167  "type": "STATION",
168  "id": self.config_entryconfig_entryconfig_entry.data[CONF_STATION].get("id"),
169  },
170  "time": {"date": "heute", "time": "jetzt"},
171  "maxList": 5,
172  "maxTimeOffset": 200,
173  "useRealtime": True,
174  "returnFilters": True,
175  }
176  )
177  except CannotConnect:
178  errors["base"] = "cannot_connect"
179  except InvalidAuth:
180  errors["base"] = "invalid_auth"
181 
182  if not errors:
183  self.departure_filtersdeparture_filters = {
184  str(i): departure_filter
185  for i, departure_filter in enumerate(departure_list["filter"])
186  }
187 
188  if user_input is not None and not errors:
189  options = {
190  CONF_FILTER: [
191  self.departure_filtersdeparture_filters[x] for x in user_input[CONF_FILTER]
192  ],
193  CONF_OFFSET: user_input[CONF_OFFSET],
194  CONF_REAL_TIME: user_input[CONF_REAL_TIME],
195  }
196 
197  return self.async_create_entryasync_create_entry(title="", data=options)
198 
199  if CONF_FILTER in self.config_entryconfig_entryconfig_entry.options:
200  old_filter = [
201  i
202  for (i, f) in self.departure_filtersdeparture_filters.items()
203  if f in self.config_entryconfig_entryconfig_entry.options[CONF_FILTER]
204  ]
205  else:
206  old_filter = []
207 
208  return self.async_show_formasync_show_form(
209  step_id="init",
210  data_schema=vol.Schema(
211  {
212  vol.Optional(CONF_FILTER, default=old_filter): cv.multi_select(
213  {
214  key: (
215  f"{departure_filter['serviceName']},"
216  f" {departure_filter['label']}"
217  )
218  for key, departure_filter in self.departure_filtersdeparture_filters.items()
219  }
220  ),
221  vol.Required(
222  CONF_OFFSET,
223  default=self.config_entryconfig_entryconfig_entry.options.get(CONF_OFFSET, 0),
224  ): cv.positive_int,
225  vol.Optional(
226  CONF_REAL_TIME,
227  default=self.config_entryconfig_entryconfig_entry.options.get(CONF_REAL_TIME, True),
228  ): bool,
229  }
230  ),
231  errors=errors,
232  )
OptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
Definition: config_flow.py:142
ConfigFlowResult async_step_station(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:92
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:61
ConfigFlowResult async_step_station_select(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:124
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:156
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_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)
None config_entry(self, ConfigEntry value)
str
_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)
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
IssData update(pyiss.ISS iss)
Definition: __init__.py:33
dict[str, str|bool] authenticate(HomeAssistant hass, str host, str security_code)
Definition: config_flow.py:132