Home Assistant Unofficial Reference 2024.12.1
number.py
Go to the documentation of this file.
1 """Support for numbers which integrates with other components."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 import voluptuous as vol
9 
11  ATTR_VALUE,
12  DEFAULT_MAX_VALUE,
13  DEFAULT_MIN_VALUE,
14  DEFAULT_STEP,
15  DOMAIN as NUMBER_DOMAIN,
16  NumberEntity,
17 )
18 from homeassistant.config_entries import ConfigEntry
19 from homeassistant.const import (
20  CONF_DEVICE_ID,
21  CONF_NAME,
22  CONF_OPTIMISTIC,
23  CONF_STATE,
24  CONF_UNIQUE_ID,
25  CONF_UNIT_OF_MEASUREMENT,
26 )
27 from homeassistant.core import HomeAssistant, callback
28 from homeassistant.helpers import config_validation as cv, selector
29 from homeassistant.helpers.device import async_device_info_to_link_from_device_id
30 from homeassistant.helpers.entity_platform import AddEntitiesCallback
31 from homeassistant.helpers.script import Script
32 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
33 
34 from . import TriggerUpdateCoordinator
35 from .const import CONF_MAX, CONF_MIN, CONF_STEP, DOMAIN
36 from .template_entity import (
37  TEMPLATE_ENTITY_AVAILABILITY_SCHEMA,
38  TEMPLATE_ENTITY_ICON_SCHEMA,
39  TemplateEntity,
40 )
41 from .trigger_entity import TriggerEntity
42 
43 _LOGGER = logging.getLogger(__name__)
44 
45 CONF_SET_VALUE = "set_value"
46 
47 DEFAULT_NAME = "Template Number"
48 DEFAULT_OPTIMISTIC = False
49 
50 NUMBER_SCHEMA = (
51  vol.Schema(
52  {
53  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.template,
54  vol.Required(CONF_STATE): cv.template,
55  vol.Required(CONF_SET_VALUE): cv.SCRIPT_SCHEMA,
56  vol.Required(CONF_STEP): cv.template,
57  vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): cv.template,
58  vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): cv.template,
59  vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
60  vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
61  vol.Optional(CONF_UNIQUE_ID): cv.string,
62  }
63  )
64  .extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA.schema)
65  .extend(TEMPLATE_ENTITY_ICON_SCHEMA.schema)
66 )
67 NUMBER_CONFIG_SCHEMA = vol.Schema(
68  {
69  vol.Required(CONF_NAME): cv.template,
70  vol.Required(CONF_STATE): cv.template,
71  vol.Required(CONF_STEP): cv.template,
72  vol.Required(CONF_SET_VALUE): cv.SCRIPT_SCHEMA,
73  vol.Optional(CONF_MIN): cv.template,
74  vol.Optional(CONF_MAX): cv.template,
75  vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
76  vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
77  }
78 )
79 
80 
82  hass: HomeAssistant, definitions: list[dict[str, Any]], unique_id_prefix: str | None
83 ) -> list[TemplateNumber]:
84  """Create the Template number."""
85  entities = []
86  for definition in definitions:
87  unique_id = definition.get(CONF_UNIQUE_ID)
88  if unique_id and unique_id_prefix:
89  unique_id = f"{unique_id_prefix}-{unique_id}"
90  entities.append(TemplateNumber(hass, definition, unique_id))
91  return entities
92 
93 
95  hass: HomeAssistant,
96  config: ConfigType,
97  async_add_entities: AddEntitiesCallback,
98  discovery_info: DiscoveryInfoType | None = None,
99 ) -> None:
100  """Set up the template number."""
101  if discovery_info is None:
102  _LOGGER.warning(
103  "Template number entities can only be configured under template:"
104  )
105  return
106 
107  if "coordinator" in discovery_info:
109  TriggerNumberEntity(hass, discovery_info["coordinator"], config)
110  for config in discovery_info["entities"]
111  )
112  return
113 
116  hass, discovery_info["entities"], discovery_info["unique_id"]
117  )
118  )
119 
120 
122  hass: HomeAssistant,
123  config_entry: ConfigEntry,
124  async_add_entities: AddEntitiesCallback,
125 ) -> None:
126  """Initialize config entry."""
127  _options = dict(config_entry.options)
128  _options.pop("template_type")
129  validated_config = NUMBER_CONFIG_SCHEMA(_options)
130  async_add_entities([TemplateNumber(hass, validated_config, config_entry.entry_id)])
131 
132 
133 @callback
135  hass: HomeAssistant, name: str, config: dict[str, Any]
136 ) -> TemplateNumber:
137  """Create a preview number."""
138  validated_config = NUMBER_CONFIG_SCHEMA(config | {CONF_NAME: name})
139  return TemplateNumber(hass, validated_config, None)
140 
141 
143  """Representation of a template number."""
144 
145  _attr_should_poll = False
146 
147  def __init__(
148  self,
149  hass: HomeAssistant,
150  config,
151  unique_id: str | None,
152  ) -> None:
153  """Initialize the number."""
154  super().__init__(hass, config=config, unique_id=unique_id)
155  assert self._attr_name_attr_name is not None
156  self._value_template_value_template = config[CONF_STATE]
157  self._command_set_value_command_set_value = Script(
158  hass, config[CONF_SET_VALUE], self._attr_name_attr_name, DOMAIN
159  )
160 
161  self._step_template_step_template = config[CONF_STEP]
162  self._min_value_template_min_value_template = config[CONF_MIN]
163  self._max_value_template_max_value_template = config[CONF_MAX]
164  self._attr_assumed_state_attr_assumed_state = self._optimistic_optimistic = config.get(CONF_OPTIMISTIC)
165  self._attr_native_unit_of_measurement_attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
166  self._attr_native_step_attr_native_step = DEFAULT_STEP
167  self._attr_native_min_value_attr_native_min_value = DEFAULT_MIN_VALUE
168  self._attr_native_max_value_attr_native_max_value = DEFAULT_MAX_VALUE
170  hass,
171  config.get(CONF_DEVICE_ID),
172  )
173 
174  @callback
175  def _async_setup_templates(self) -> None:
176  """Set up templates."""
177  self.add_template_attributeadd_template_attribute(
178  "_attr_native_value",
179  self._value_template_value_template,
180  validator=vol.Coerce(float),
181  none_on_template_error=True,
182  )
183  self.add_template_attributeadd_template_attribute(
184  "_attr_native_step",
185  self._step_template_step_template,
186  validator=vol.Coerce(float),
187  none_on_template_error=True,
188  )
189  if self._min_value_template_min_value_template is not None:
190  self.add_template_attributeadd_template_attribute(
191  "_attr_native_min_value",
192  self._min_value_template_min_value_template,
193  validator=vol.Coerce(float),
194  none_on_template_error=True,
195  )
196  if self._max_value_template_max_value_template is not None:
197  self.add_template_attributeadd_template_attribute(
198  "_attr_native_max_value",
199  self._max_value_template_max_value_template,
200  validator=vol.Coerce(float),
201  none_on_template_error=True,
202  )
203  super()._async_setup_templates()
204 
205  async def async_set_native_value(self, value: float) -> None:
206  """Set value of the number."""
207  if self._optimistic_optimistic:
208  self._attr_native_value_attr_native_value = value
209  self.async_write_ha_stateasync_write_ha_state()
210  if self._command_set_value_command_set_value:
211  await self.async_run_scriptasync_run_script(
212  self._command_set_value_command_set_value,
213  run_variables={ATTR_VALUE: value},
214  context=self._context_context,
215  )
216 
217 
219  """Number entity based on trigger data."""
220 
221  domain = NUMBER_DOMAIN
222  extra_template_keys = (
223  CONF_STATE,
224  CONF_STEP,
225  CONF_MIN,
226  CONF_MAX,
227  )
228 
229  def __init__(
230  self,
231  hass: HomeAssistant,
232  coordinator: TriggerUpdateCoordinator,
233  config: dict,
234  ) -> None:
235  """Initialize the entity."""
236  super().__init__(hass, coordinator, config)
237 
238  self._command_set_value_command_set_value = Script(
239  hass,
240  config[CONF_SET_VALUE],
241  self._rendered.get(CONF_NAME, DEFAULT_NAME),
242  DOMAIN,
243  )
244 
245  self._attr_native_unit_of_measurement_attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
246 
247  @property
248  def native_value(self) -> float | None:
249  """Return the currently selected option."""
250  return vol.Any(vol.Coerce(float), None)(self._rendered.get(CONF_STATE))
251 
252  @property
253  def native_min_value(self) -> int:
254  """Return the minimum value."""
255  return vol.Any(vol.Coerce(float), None)(
256  self._rendered.get(CONF_MIN, super().native_min_value)
257  )
258 
259  @property
260  def native_max_value(self) -> int:
261  """Return the maximum value."""
262  return vol.Any(vol.Coerce(float), None)(
263  self._rendered.get(CONF_MAX, super().native_max_value)
264  )
265 
266  @property
267  def native_step(self) -> int:
268  """Return the increment/decrement step."""
269  return vol.Any(vol.Coerce(float), None)(
270  self._rendered.get(CONF_STEP, super().native_step)
271  )
272 
273  async def async_set_native_value(self, value: float) -> None:
274  """Set value of the number."""
275  if self._config[CONF_OPTIMISTIC]:
276  self._attr_native_value_attr_native_value = value
277  self.async_write_ha_stateasync_write_ha_state()
278  await self._command_set_value_command_set_value.async_run(
279  {ATTR_VALUE: value}, context=self._context_context
280  )
None __init__(self, HomeAssistant hass, config, str|None unique_id)
Definition: number.py:152
None __init__(self, HomeAssistant hass, TriggerUpdateCoordinator coordinator, dict config)
Definition: number.py:234
None async_run_script(self, Script script, *_VarsType|None run_variables=None, Context|None context=None)
None add_template_attribute(self, str attribute, Template template, Callable[[Any], Any]|None validator=None, Callable[[Any], None]|None on_update=None, bool none_on_template_error=False)
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
list[TemplateNumber] _async_create_entities(HomeAssistant hass, list[dict[str, Any]] definitions, str|None unique_id_prefix)
Definition: number.py:83
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: number.py:99
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: number.py:125
TemplateNumber async_create_preview_number(HomeAssistant hass, str name, dict[str, Any] config)
Definition: number.py:136
dr.DeviceInfo|None async_device_info_to_link_from_device_id(HomeAssistant hass, str|None device_id)
Definition: device.py:44