Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for Environment Canada integration."""
2 
3 import logging
4 from typing import Any
5 import xml.etree.ElementTree as ET
6 
7 import aiohttp
8 from env_canada import ECWeather, ec_exc
9 import voluptuous as vol
10 
11 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
12 from homeassistant.const import CONF_LANGUAGE, CONF_LATITUDE, CONF_LONGITUDE
13 from homeassistant.helpers import config_validation as cv
14 
15 from .const import CONF_STATION, CONF_TITLE, DOMAIN
16 
17 _LOGGER = logging.getLogger(__name__)
18 
19 
20 async def validate_input(data):
21  """Validate the user input allows us to connect."""
22  lat = data.get(CONF_LATITUDE)
23  lon = data.get(CONF_LONGITUDE)
24  station = data.get(CONF_STATION)
25  lang = data.get(CONF_LANGUAGE).lower()
26 
27  if station:
28  weather_data = ECWeather(station_id=station, language=lang)
29  else:
30  weather_data = ECWeather(coordinates=(lat, lon), language=lang)
31  await weather_data.update()
32 
33  if lat is None or lon is None:
34  lat = weather_data.lat
35  lon = weather_data.lon
36 
37  return {
38  CONF_TITLE: weather_data.metadata.get("location"),
39  CONF_STATION: weather_data.station_id,
40  CONF_LATITUDE: lat,
41  CONF_LONGITUDE: lon,
42  }
43 
44 
46  """Handle a config flow for Environment Canada weather."""
47 
48  VERSION = 1
49 
50  async def async_step_user(
51  self, user_input: dict[str, Any] | None = None
52  ) -> ConfigFlowResult:
53  """Handle the initial step."""
54  errors = {}
55  if user_input is not None:
56  try:
57  info = await validate_input(user_input)
58  except (ET.ParseError, vol.MultipleInvalid, ec_exc.UnknownStationId):
59  errors["base"] = "bad_station_id"
60  except aiohttp.ClientConnectionError:
61  errors["base"] = "cannot_connect"
62  except aiohttp.ClientResponseError as err:
63  if err.status == 404:
64  errors["base"] = "bad_station_id"
65  else:
66  errors["base"] = "error_response"
67  except Exception:
68  _LOGGER.exception("Unexpected exception")
69  errors["base"] = "unknown"
70 
71  if not errors:
72  user_input[CONF_STATION] = info[CONF_STATION]
73  user_input[CONF_LATITUDE] = info[CONF_LATITUDE]
74  user_input[CONF_LONGITUDE] = info[CONF_LONGITUDE]
75 
76  # The combination of station and language are unique for all EC weather reporting
77  await self.async_set_unique_idasync_set_unique_id(
78  f"{user_input[CONF_STATION]}-{user_input[CONF_LANGUAGE].lower()}"
79  )
80  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
81  return self.async_create_entryasync_create_entryasync_create_entry(title=info[CONF_TITLE], data=user_input)
82 
83  data_schema = vol.Schema(
84  {
85  vol.Optional(CONF_STATION): str,
86  vol.Optional(
87  CONF_LATITUDE, default=self.hass.config.latitude
88  ): cv.latitude,
89  vol.Optional(
90  CONF_LONGITUDE, default=self.hass.config.longitude
91  ): cv.longitude,
92  vol.Required(CONF_LANGUAGE, default="English"): vol.In(
93  ["English", "French"]
94  ),
95  }
96  )
97 
98  return self.async_show_formasync_show_formasync_show_form(
99  step_id="user", data_schema=data_schema, errors=errors
100  )
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:52
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_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)