Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for file integration."""
2 
3 from __future__ import annotations
4 
5 from copy import deepcopy
6 from typing import Any
7 
8 import voluptuous as vol
9 
10 from homeassistant.config_entries import (
11  ConfigEntry,
12  ConfigFlow,
13  ConfigFlowResult,
14  OptionsFlow,
15 )
16 from homeassistant.const import (
17  CONF_FILE_PATH,
18  CONF_NAME,
19  CONF_PLATFORM,
20  CONF_UNIT_OF_MEASUREMENT,
21  CONF_VALUE_TEMPLATE,
22  Platform,
23 )
24 from homeassistant.core import callback
26  BooleanSelector,
27  BooleanSelectorConfig,
28  TemplateSelector,
29  TemplateSelectorConfig,
30  TextSelector,
31  TextSelectorConfig,
32  TextSelectorType,
33 )
34 
35 from .const import CONF_TIMESTAMP, DEFAULT_NAME, DOMAIN
36 
39 TEXT_SELECTOR = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT))
40 
41 FILE_OPTIONS_SCHEMAS = {
42  Platform.SENSOR.value: vol.Schema(
43  {
44  vol.Optional(CONF_VALUE_TEMPLATE): TEMPLATE_SELECTOR,
45  vol.Optional(CONF_UNIT_OF_MEASUREMENT): TEXT_SELECTOR,
46  }
47  ),
48  Platform.NOTIFY.value: vol.Schema(
49  {
50  vol.Optional(CONF_TIMESTAMP, default=False): BOOLEAN_SELECTOR,
51  }
52  ),
53 }
54 
55 FILE_FLOW_SCHEMAS = {
56  Platform.SENSOR.value: vol.Schema(
57  {
58  vol.Required(CONF_FILE_PATH): TEXT_SELECTOR,
59  }
60  ).extend(FILE_OPTIONS_SCHEMAS[Platform.SENSOR.value].schema),
61  Platform.NOTIFY.value: vol.Schema(
62  {
63  vol.Required(CONF_FILE_PATH): TEXT_SELECTOR,
64  }
65  ).extend(FILE_OPTIONS_SCHEMAS[Platform.NOTIFY.value].schema),
66 }
67 
68 
69 class FileConfigFlowHandler(ConfigFlow, domain=DOMAIN):
70  """Handle a file config flow."""
71 
72  VERSION = 2
73 
74  @staticmethod
75  @callback
77  config_entry: ConfigEntry,
78  ) -> FileOptionsFlowHandler:
79  """Get the options flow for this handler."""
80  return FileOptionsFlowHandler()
81 
82  async def validate_file_path(self, file_path: str) -> bool:
83  """Ensure the file path is valid."""
84  return await self.hass.async_add_executor_job(
85  self.hass.config.is_allowed_path, file_path
86  )
87 
88  async def async_step_user(
89  self, user_input: dict[str, Any] | None = None
90  ) -> ConfigFlowResult:
91  """Handle a flow initiated by the user."""
92  return self.async_show_menuasync_show_menu(
93  step_id="user",
94  menu_options=["notify", "sensor"],
95  )
96 
97  async def _async_handle_step(
98  self, platform: str, user_input: dict[str, Any] | None = None
99  ) -> ConfigFlowResult:
100  """Handle file config flow step."""
101  errors: dict[str, str] = {}
102  if user_input:
103  user_input[CONF_PLATFORM] = platform
104  self._async_abort_entries_match_async_abort_entries_match(user_input)
105  if not await self.validate_file_pathvalidate_file_path(user_input[CONF_FILE_PATH]):
106  errors[CONF_FILE_PATH] = "not_allowed"
107  else:
108  title = f"{DEFAULT_NAME} [{user_input[CONF_FILE_PATH]}]"
109  data = deepcopy(user_input)
110  options = {}
111  for key, value in user_input.items():
112  if key not in (CONF_FILE_PATH, CONF_PLATFORM, CONF_NAME):
113  data.pop(key)
114  options[key] = value
115  return self.async_create_entryasync_create_entryasync_create_entry(data=data, title=title, options=options)
116 
117  return self.async_show_formasync_show_formasync_show_form(
118  step_id=platform, data_schema=FILE_FLOW_SCHEMAS[platform], errors=errors
119  )
120 
121  async def async_step_notify(
122  self, user_input: dict[str, Any] | None = None
123  ) -> ConfigFlowResult:
124  """Handle file notifier config flow."""
125  return await self._async_handle_step_async_handle_step(Platform.NOTIFY.value, user_input)
126 
127  async def async_step_sensor(
128  self, user_input: dict[str, Any] | None = None
129  ) -> ConfigFlowResult:
130  """Handle file sensor config flow."""
131  return await self._async_handle_step_async_handle_step(Platform.SENSOR.value, user_input)
132 
133 
135  """Handle File options."""
136 
137  async def async_step_init(
138  self, user_input: dict[str, Any] | None = None
139  ) -> ConfigFlowResult:
140  """Manage File options."""
141  if user_input:
142  return self.async_create_entryasync_create_entry(data=user_input)
143 
144  platform = self.config_entryconfig_entryconfig_entry.data[CONF_PLATFORM]
145  return self.async_show_formasync_show_form(
146  step_id="init",
147  data_schema=self.add_suggested_values_to_schemaadd_suggested_values_to_schema(
148  FILE_OPTIONS_SCHEMAS[platform], self.config_entryconfig_entryconfig_entry.options or {}
149  ),
150  )
ConfigFlowResult async_step_notify(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:123
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:90
ConfigFlowResult async_step_sensor(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:129
FileOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
Definition: config_flow.py:78
ConfigFlowResult _async_handle_step(self, str platform, dict[str, Any]|None user_input=None)
Definition: config_flow.py:99
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:139
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)
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)
vol.Schema add_suggested_values_to_schema(self, vol.Schema data_schema, Mapping[str, Any]|None suggested_values)
_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_show_menu(self, *str|None step_id=None, Container[str] menu_options, Mapping[str, str]|None description_placeholders=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)