Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for Traccar Server integration."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
7 from pytraccar import ApiClient, ServerModel, TraccarException
8 import voluptuous as vol
9 
10 from homeassistant import config_entries
11 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
12 from homeassistant.const import (
13  CONF_HOST,
14  CONF_PASSWORD,
15  CONF_PORT,
16  CONF_SSL,
17  CONF_USERNAME,
18  CONF_VERIFY_SSL,
19 )
20 from homeassistant.core import callback
21 from homeassistant.helpers.aiohttp_client import async_get_clientsession
23  SchemaFlowFormStep,
24  SchemaOptionsFlowHandler,
25 )
27  BooleanSelector,
28  BooleanSelectorConfig,
29  NumberSelector,
30  NumberSelectorConfig,
31  NumberSelectorMode,
32  SelectSelector,
33  SelectSelectorConfig,
34  SelectSelectorMode,
35  TextSelector,
36  TextSelectorConfig,
37  TextSelectorType,
38 )
39 
40 from .const import (
41  CONF_CUSTOM_ATTRIBUTES,
42  CONF_EVENTS,
43  CONF_MAX_ACCURACY,
44  CONF_SKIP_ACCURACY_FILTER_FOR,
45  DOMAIN,
46  EVENTS,
47  LOGGER,
48 )
49 
50 STEP_USER_DATA_SCHEMA = vol.Schema(
51  {
52  vol.Required(CONF_HOST): TextSelector(
53  TextSelectorConfig(type=TextSelectorType.TEXT)
54  ),
55  vol.Optional(CONF_PORT, default="8082"): TextSelector(
56  TextSelectorConfig(type=TextSelectorType.TEXT)
57  ),
58  vol.Required(CONF_USERNAME): TextSelector(
59  TextSelectorConfig(type=TextSelectorType.EMAIL)
60  ),
61  vol.Required(CONF_PASSWORD): TextSelector(
62  TextSelectorConfig(type=TextSelectorType.PASSWORD)
63  ),
64  vol.Optional(CONF_SSL, default=False): BooleanSelector(BooleanSelectorConfig()),
65  vol.Optional(CONF_VERIFY_SSL, default=True): BooleanSelector(
67  ),
68  }
69 )
70 
71 OPTIONS_FLOW = {
72  "init": SchemaFlowFormStep(
73  schema=vol.Schema(
74  {
75  vol.Optional(CONF_MAX_ACCURACY, default=0.0): NumberSelector(
77  mode=NumberSelectorMode.BOX,
78  min=0.0,
79  )
80  ),
81  vol.Optional(CONF_CUSTOM_ATTRIBUTES, default=[]): SelectSelector(
83  mode=SelectSelectorMode.DROPDOWN,
84  multiple=True,
85  sort=True,
86  custom_value=True,
87  options=[],
88  )
89  ),
90  vol.Optional(CONF_SKIP_ACCURACY_FILTER_FOR, default=[]): SelectSelector(
92  mode=SelectSelectorMode.DROPDOWN,
93  multiple=True,
94  sort=True,
95  custom_value=True,
96  options=[],
97  )
98  ),
99  vol.Optional(CONF_EVENTS, default=[]): SelectSelector(
101  mode=SelectSelectorMode.DROPDOWN,
102  multiple=True,
103  sort=True,
104  custom_value=True,
105  options=list(EVENTS),
106  )
107  ),
108  }
109  )
110  ),
111 }
112 
113 
114 class TraccarServerConfigFlow(ConfigFlow, domain=DOMAIN):
115  """Handle a config flow for Traccar Server."""
116 
117  async def _get_server_info(self, user_input: dict[str, Any]) -> ServerModel:
118  """Get server info."""
119  client = ApiClient(
120  client_session=async_get_clientsession(self.hass),
121  host=user_input[CONF_HOST],
122  port=user_input[CONF_PORT],
123  username=user_input[CONF_USERNAME],
124  password=user_input[CONF_PASSWORD],
125  ssl=user_input[CONF_SSL],
126  verify_ssl=user_input[CONF_VERIFY_SSL],
127  )
128  return await client.get_server()
129 
130  async def async_step_user(
131  self,
132  user_input: dict[str, Any] | None = None,
133  ) -> ConfigFlowResult:
134  """Handle the initial step."""
135  errors: dict[str, str] = {}
136  if user_input is not None:
137  self._async_abort_entries_match_async_abort_entries_match(
138  {
139  CONF_HOST: user_input[CONF_HOST],
140  CONF_PORT: user_input[CONF_PORT],
141  }
142  )
143  try:
144  await self._get_server_info_get_server_info(user_input)
145  except TraccarException as exception:
146  LOGGER.error("Unable to connect to Traccar Server: %s", exception)
147  errors["base"] = "cannot_connect"
148  except Exception: # noqa: BLE001
149  LOGGER.exception("Unexpected exception")
150  errors["base"] = "unknown"
151  else:
152  return self.async_create_entryasync_create_entryasync_create_entry(
153  title=f"{user_input[CONF_HOST]}:{user_input[CONF_PORT]}",
154  data=user_input,
155  )
156 
157  return self.async_show_formasync_show_formasync_show_form(
158  step_id="user",
159  data_schema=STEP_USER_DATA_SCHEMA,
160  errors=errors,
161  )
162 
163  @staticmethod
164  @callback
166  config_entry: config_entries.ConfigEntry,
167  ) -> SchemaOptionsFlowHandler:
168  """Get the options flow for this handler."""
169  return SchemaOptionsFlowHandler(config_entry, OPTIONS_FLOW)
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_step_user(self, dict[str, Any]|None user_input=None)
None _async_abort_entries_match(self, dict[str, Any]|None match_dict=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)
OptionsFlow async_get_options_flow(ConfigEntry config_entry)
_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)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)