Home Assistant Unofficial Reference 2024.12.1
number.py
Go to the documentation of this file.
1 """Support for Z-Wave controls using the number platform."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Mapping
6 from typing import Any, cast
7 
8 from zwave_js_server.client import Client as ZwaveClient
9 from zwave_js_server.const import TARGET_VALUE_PROPERTY
10 from zwave_js_server.model.driver import Driver
11 from zwave_js_server.model.value import Value
12 
13 from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN, NumberEntity
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import EntityCategory
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.exceptions import HomeAssistantError
18 from homeassistant.helpers.dispatcher import async_dispatcher_connect
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 
21 from .const import ATTR_RESERVED_VALUES, DATA_CLIENT, DOMAIN
22 from .discovery import ZwaveDiscoveryInfo
23 from .entity import ZWaveBaseEntity
24 
25 PARALLEL_UPDATES = 0
26 
27 
29  hass: HomeAssistant,
30  config_entry: ConfigEntry,
31  async_add_entities: AddEntitiesCallback,
32 ) -> None:
33  """Set up Z-Wave Number entity from Config Entry."""
34  client: ZwaveClient = config_entry.runtime_data[DATA_CLIENT]
35 
36  @callback
37  def async_add_number(info: ZwaveDiscoveryInfo) -> None:
38  """Add Z-Wave number entity."""
39  driver = client.driver
40  assert driver is not None # Driver is ready before platforms are loaded.
41  entities: list[ZWaveBaseEntity] = []
42  if info.platform_hint == "volume":
43  entities.append(ZwaveVolumeNumberEntity(config_entry, driver, info))
44  elif info.platform_hint == "config_parameter":
45  entities.append(
46  ZWaveConfigParameterNumberEntity(config_entry, driver, info)
47  )
48  else:
49  entities.append(ZwaveNumberEntity(config_entry, driver, info))
50  async_add_entities(entities)
51 
52  config_entry.async_on_unload(
54  hass,
55  f"{DOMAIN}_{config_entry.entry_id}_add_{NUMBER_DOMAIN}",
56  async_add_number,
57  )
58  )
59 
60 
61 class ZwaveNumberEntity(ZWaveBaseEntity, NumberEntity):
62  """Representation of a Z-Wave number entity."""
63 
64  def __init__(
65  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
66  ) -> None:
67  """Initialize a ZwaveNumberEntity entity."""
68  super().__init__(config_entry, driver, info)
69  self._target_value_target_value: Value | None
70  if self.infoinfo.primary_value.metadata.writeable:
71  self._target_value_target_value = self.infoinfo.primary_value
72  else:
73  self._target_value_target_value = self.get_zwave_valueget_zwave_value(TARGET_VALUE_PROPERTY)
74 
75  # Entity class attributes
76  self._attr_name_attr_name_attr_name = self.generate_namegenerate_name(
77  include_value_name=True, alternate_value_name=info.platform_hint
78  )
79 
80  @property
81  def native_min_value(self) -> float:
82  """Return the minimum value."""
83  min_ = self.infoinfo.primary_value.metadata.min
84  return float(0 if min_ is None else min_)
85 
86  @property
87  def native_max_value(self) -> float:
88  """Return the maximum value."""
89  max_ = self.infoinfo.primary_value.metadata.max
90  return float(255 if max_ is None else max_)
91 
92  @property
93  def native_value(self) -> float | None:
94  """Return the entity value."""
95  value = self.infoinfo.primary_value.value
96  return None if value is None else float(value)
97 
98  @property
99  def native_unit_of_measurement(self) -> str | None:
100  """Return the unit of measurement of this entity, if any."""
101  unit = self.infoinfo.primary_value.metadata.unit
102  return None if unit is None else str(unit)
103 
104  async def async_set_native_value(self, value: float) -> None:
105  """Set new value."""
106  if (target_value := self._target_value_target_value) is None:
107  raise HomeAssistantError("Missing target value on device.")
108  await self._async_set_value_async_set_value(target_value, value)
109 
110 
112  """Representation of a Z-Wave config parameter number."""
113 
114  _attr_entity_category = EntityCategory.CONFIG
115 
116  def __init__(
117  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
118  ) -> None:
119  """Initialize a ZWaveConfigParameterNumber entity."""
120  super().__init__(config_entry, driver, info)
121 
122  property_key_name = self.infoinfo.primary_value.property_key_name
123  # Entity class attributes
124  self._attr_name_attr_name_attr_name_attr_name = self.generate_namegenerate_name(
125  alternate_value_name=self.infoinfo.primary_value.property_name,
126  additional_info=[property_key_name] if property_key_name else None,
127  )
128 
129  @property
130  def extra_state_attributes(self) -> Mapping[str, Any] | None:
131  """Return extra state attributes for entity."""
132  if not self.infoinfo.primary_value.metadata.states:
133  return None
134  return {
135  ATTR_RESERVED_VALUES: {
136  int(k): v for k, v in self.infoinfo.primary_value.metadata.states.items()
137  }
138  }
139 
140 
142  """Representation of a volume number entity."""
143 
144  def __init__(
145  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
146  ) -> None:
147  """Initialize a ZwaveVolumeNumberEntity entity."""
148  super().__init__(config_entry, driver, info)
149  max_value = cast(int, self.infoinfo.primary_value.metadata.max)
150  min_value = cast(int, self.infoinfo.primary_value.metadata.min)
151  self.correction_factorcorrection_factor = (max_value - min_value) or 1
152 
153  # Entity class attributes
154  self._attr_native_min_value_attr_native_min_value = 0
155  self._attr_native_max_value_attr_native_max_value = 1
156  self._attr_native_step_attr_native_step = 0.01
157  self._attr_name_attr_name_attr_name = self.generate_namegenerate_name(include_value_name=True)
158 
159  @property
160  def native_value(self) -> float | None:
161  """Return the entity value."""
162  if self.infoinfo.primary_value.value is None:
163  return None
164  return float(self.infoinfo.primary_value.value) / self.correction_factorcorrection_factor
165 
166  async def async_set_native_value(self, value: float) -> None:
167  """Set new value."""
168  await self._async_set_value_async_set_value(
169  self.infoinfo.primary_value, round(value * self.correction_factorcorrection_factor)
170  )
str generate_name(self, bool include_value_name=False, str|None alternate_value_name=None, Sequence[str|None]|None additional_info=None, str|None name_prefix=None)
Definition: entity.py:163
SetValueResult|None _async_set_value(self, ZwaveValue value, Any new_value, dict|None options=None, bool|None wait_for_result=None)
Definition: entity.py:330
ZwaveValue|None get_zwave_value(self, str|int value_property, int|None command_class=None, int|None endpoint=None, int|str|None value_property_key=None, bool add_to_watched_value_ids=True, bool check_all_endpoints=False)
Definition: entity.py:280
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: number.py:118
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: number.py:66
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: number.py:146
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: number.py:32
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103