Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for Threshold integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Mapping
6 from typing import Any
7 
8 import voluptuous as vol
9 
10 from homeassistant.components import websocket_api
11 from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
12 from homeassistant.const import CONF_ENTITY_ID, CONF_NAME
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.exceptions import HomeAssistantError
15 from homeassistant.helpers import selector
17  SchemaCommonFlowHandler,
18  SchemaConfigFlowHandler,
19  SchemaFlowError,
20  SchemaFlowFormStep,
21 )
22 
23 from .binary_sensor import ThresholdSensor
24 from .const import CONF_HYSTERESIS, CONF_LOWER, CONF_UPPER, DEFAULT_HYSTERESIS, DOMAIN
25 
26 
27 async def _validate_mode(
28  handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
29 ) -> dict[str, Any]:
30  """Validate the threshold mode, and set limits to None if not set."""
31  if CONF_LOWER not in user_input and CONF_UPPER not in user_input:
32  raise SchemaFlowError("need_lower_upper")
33  return {CONF_LOWER: None, CONF_UPPER: None, **user_input}
34 
35 
36 OPTIONS_SCHEMA = vol.Schema(
37  {
38  vol.Required(
39  CONF_HYSTERESIS, default=DEFAULT_HYSTERESIS
40  ): selector.NumberSelector(
41  selector.NumberSelectorConfig(
42  mode=selector.NumberSelectorMode.BOX, step="any"
43  ),
44  ),
45  vol.Optional(CONF_LOWER): selector.NumberSelector(
46  selector.NumberSelectorConfig(
47  mode=selector.NumberSelectorMode.BOX, step="any"
48  ),
49  ),
50  vol.Optional(CONF_UPPER): selector.NumberSelector(
51  selector.NumberSelectorConfig(
52  mode=selector.NumberSelectorMode.BOX, step="any"
53  ),
54  ),
55  vol.Required(CONF_ENTITY_ID): selector.EntitySelector(
56  selector.EntitySelectorConfig(domain=SENSOR_DOMAIN)
57  ),
58  }
59 )
60 
61 CONFIG_SCHEMA = vol.Schema(
62  {
63  vol.Required(CONF_NAME): selector.TextSelector(),
64  }
65 ).extend(OPTIONS_SCHEMA.schema)
66 
67 CONFIG_FLOW = {
68  "user": SchemaFlowFormStep(
69  CONFIG_SCHEMA, preview="threshold", validate_user_input=_validate_mode
70  )
71 }
72 
73 OPTIONS_FLOW = {
74  "init": SchemaFlowFormStep(
75  OPTIONS_SCHEMA, preview="threshold", validate_user_input=_validate_mode
76  )
77 }
78 
79 
81  """Handle a config or options flow for Threshold."""
82 
83  config_flow = CONFIG_FLOW
84  options_flow = OPTIONS_FLOW
85 
86  def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
87  """Return config entry title."""
88  name: str = options[CONF_NAME]
89  return name
90 
91  @staticmethod
92  async def async_setup_preview(hass: HomeAssistant) -> None:
93  """Set up preview WS API."""
94  websocket_api.async_register_command(hass, ws_start_preview)
95 
96 
97 @websocket_api.websocket_command( { vol.Required("type"): "threshold/start_preview",
98  vol.Required("flow_id"): str,
99  vol.Required("flow_type"): vol.Any("config_flow", "options_flow"),
100  vol.Required("user_input"): dict,
101  }
102 )
103 @callback
104 def ws_start_preview(
105  hass: HomeAssistant,
107  msg: dict[str, Any],
108 ) -> None:
109  """Generate a preview."""
110 
111  if msg["flow_type"] == "config_flow":
112  entity_id = msg["user_input"][CONF_ENTITY_ID]
113  name = msg["user_input"][CONF_NAME]
114  else:
115  flow_status = hass.config_entries.options.async_get(msg["flow_id"])
116  config_entry = hass.config_entries.async_get_entry(flow_status["handler"])
117  if not config_entry:
118  raise HomeAssistantError("Config entry not found")
119  entity_id = config_entry.options[CONF_ENTITY_ID]
120  name = config_entry.options[CONF_NAME]
121 
122  @callback
123  def async_preview_updated(state: str, attributes: Mapping[str, Any]) -> None:
124  """Forward config entry state events to websocket."""
125  connection.send_message(
126  websocket_api.event_message(
127  msg["id"], {"attributes": attributes, "state": state}
128  )
129  )
130 
131  preview_entity = ThresholdSensor(
132  entity_id,
133  name,
134  msg["user_input"].get(CONF_LOWER),
135  msg["user_input"].get(CONF_UPPER),
136  msg["user_input"].get(CONF_HYSTERESIS),
137  None,
138  None,
139  )
140  preview_entity.hass = hass
141 
142  connection.send_result(msg["id"])
143  connection.subscriptions[msg["id"]] = preview_entity.async_start_preview(
144  async_preview_updated
145  )
146 
str async_config_entry_title(self, Mapping[str, Any] options)
Definition: config_flow.py:86
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None ws_start_preview(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
Definition: config_flow.py:110
dict[str, Any] _validate_mode(SchemaCommonFlowHandler handler, dict[str, Any] user_input)
Definition: config_flow.py:29