Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for proximity."""
2 
3 from __future__ import annotations
4 
5 from typing import Any, cast
6 
7 import voluptuous as vol
8 
9 from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER_DOMAIN
10 from homeassistant.components.person import DOMAIN as PERSON_DOMAIN
11 from homeassistant.components.zone import DOMAIN as ZONE_DOMAIN
12 from homeassistant.config_entries import (
13  ConfigEntry,
14  ConfigFlow,
15  ConfigFlowResult,
16  OptionsFlow,
17 )
18 from homeassistant.const import CONF_ZONE, UnitOfLength
19 from homeassistant.core import State, callback
21  EntitySelector,
22  EntitySelectorConfig,
23  NumberSelector,
24  NumberSelectorConfig,
25 )
26 from homeassistant.helpers.typing import VolDictType
27 from homeassistant.util import slugify
28 
29 from .const import (
30  CONF_IGNORED_ZONES,
31  CONF_TOLERANCE,
32  CONF_TRACKED_ENTITIES,
33  DEFAULT_PROXIMITY_ZONE,
34  DEFAULT_TOLERANCE,
35  DOMAIN,
36 )
37 
38 RESULT_SUCCESS = "success"
39 
40 
41 def _base_schema(user_input: dict[str, Any]) -> VolDictType:
42  return {
43  vol.Required(
44  CONF_TRACKED_ENTITIES, default=user_input.get(CONF_TRACKED_ENTITIES, [])
45  ): EntitySelector(
47  domain=[DEVICE_TRACKER_DOMAIN, PERSON_DOMAIN], multiple=True
48  ),
49  ),
50  vol.Optional(
51  CONF_IGNORED_ZONES, default=user_input.get(CONF_IGNORED_ZONES, [])
52  ): EntitySelector(
53  EntitySelectorConfig(domain=ZONE_DOMAIN, multiple=True),
54  ),
55  vol.Required(
56  CONF_TOLERANCE,
57  default=user_input.get(CONF_TOLERANCE, DEFAULT_TOLERANCE),
58  ): NumberSelector(
60  min=1, max=100, step=1, unit_of_measurement=UnitOfLength.METERS
61  ),
62  ),
63  }
64 
65 
66 class ProximityConfigFlow(ConfigFlow, domain=DOMAIN):
67  """Handle a proximity config flow."""
68 
69  VERSION = 1
70 
71  def _user_form_schema(self, user_input: dict[str, Any] | None = None) -> vol.Schema:
72  if user_input is None:
73  user_input = {}
74  return vol.Schema(
75  {
76  vol.Required(
77  CONF_ZONE,
78  default=user_input.get(
79  CONF_ZONE, f"{ZONE_DOMAIN}.{DEFAULT_PROXIMITY_ZONE}"
80  ),
81  ): EntitySelector(
82  EntitySelectorConfig(domain=ZONE_DOMAIN),
83  ),
84  **_base_schema(user_input),
85  }
86  )
87 
88  @staticmethod
89  @callback
90  def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow:
91  """Get the options flow for this handler."""
92  return ProximityOptionsFlow()
93 
94  async def async_step_user(
95  self, user_input: dict[str, Any] | None = None
96  ) -> ConfigFlowResult:
97  """Handle a flow initialized by the user."""
98  if user_input is not None:
99  self._async_abort_entries_match_async_abort_entries_match(user_input)
100 
101  title = cast(State, self.hass.states.get(user_input[CONF_ZONE])).name
102 
103  slugified_existing_entry_titles = [
104  slugify(e.title) for e in self._async_current_entries_async_current_entries()
105  ]
106 
107  possible_title = title
108  tries = 1
109  while slugify(possible_title) in slugified_existing_entry_titles:
110  tries += 1
111  possible_title = f"{title} {tries}"
112 
113  return self.async_create_entryasync_create_entryasync_create_entry(title=possible_title, data=user_input)
114 
115  return self.async_show_formasync_show_formasync_show_form(
116  step_id="user",
117  data_schema=self._user_form_schema_user_form_schema(user_input),
118  )
119 
120 
122  """Handle a option flow."""
123 
124  def _user_form_schema(self, user_input: dict[str, Any]) -> vol.Schema:
125  return vol.Schema(_base_schema(user_input))
126 
127  async def async_step_init(
128  self, user_input: dict[str, Any] | None = None
129  ) -> ConfigFlowResult:
130  """Handle options flow."""
131  if user_input is not None:
132  self.hass.config_entries.async_update_entry(
133  self.config_entryconfig_entryconfig_entry, data={**self.config_entryconfig_entryconfig_entry.data, **user_input}
134  )
135  return self.async_create_entryasync_create_entry(title=self.config_entryconfig_entryconfig_entry.title, data={})
136 
137  return self.async_show_formasync_show_form(
138  step_id="init",
139  data_schema=self._user_form_schema_user_form_schema(dict(self.config_entryconfig_entryconfig_entry.data)),
140  )
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:96
OptionsFlow async_get_options_flow(ConfigEntry config_entry)
Definition: config_flow.py:90
vol.Schema _user_form_schema(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:71
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:129
vol.Schema _user_form_schema(self, dict[str, Any] user_input)
Definition: config_flow.py:124
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)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=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)
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)
VolDictType _base_schema(dict[str, Any] user_input)
Definition: config_flow.py:41