Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for Z-Wave controls using the select platform."""
2 
3 from __future__ import annotations
4 
5 from typing import cast
6 
7 from zwave_js_server.client import Client as ZwaveClient
8 from zwave_js_server.const import TARGET_VALUE_PROPERTY, CommandClass
9 from zwave_js_server.const.command_class.lock import TARGET_MODE_PROPERTY
10 from zwave_js_server.const.command_class.sound_switch import TONE_ID_PROPERTY, ToneID
11 from zwave_js_server.model.driver import Driver
12 
13 from homeassistant.components.select import DOMAIN as SELECT_DOMAIN, SelectEntity
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import EntityCategory
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.helpers.dispatcher import async_dispatcher_connect
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 
20 from .const import DATA_CLIENT, DOMAIN
21 from .discovery import ZwaveDiscoveryInfo
22 from .entity import ZWaveBaseEntity
23 
24 PARALLEL_UPDATES = 0
25 
26 
28  hass: HomeAssistant,
29  config_entry: ConfigEntry,
30  async_add_entities: AddEntitiesCallback,
31 ) -> None:
32  """Set up Z-Wave Select entity from Config Entry."""
33  client: ZwaveClient = config_entry.runtime_data[DATA_CLIENT]
34 
35  @callback
36  def async_add_select(info: ZwaveDiscoveryInfo) -> None:
37  """Add Z-Wave select entity."""
38  driver = client.driver
39  assert driver is not None # Driver is ready before platforms are loaded.
40  entities: list[ZWaveBaseEntity] = []
41  if info.platform_hint == "Default tone":
42  entities.append(ZwaveDefaultToneSelectEntity(config_entry, driver, info))
43  elif info.platform_hint == "multilevel_switch":
44  entities.append(
45  ZwaveMultilevelSwitchSelectEntity(config_entry, driver, info)
46  )
47  elif info.platform_hint == "config_parameter":
48  entities.append(
49  ZWaveConfigParameterSelectEntity(config_entry, driver, info)
50  )
51  elif info.platform_hint == "door_lock":
52  entities.append(ZWaveDoorLockSelectEntity(config_entry, driver, info))
53  else:
54  entities.append(ZwaveSelectEntity(config_entry, driver, info))
55  async_add_entities(entities)
56 
57  config_entry.async_on_unload(
59  hass,
60  f"{DOMAIN}_{config_entry.entry_id}_add_{SELECT_DOMAIN}",
61  async_add_select,
62  )
63  )
64 
65 
66 class ZwaveSelectEntity(ZWaveBaseEntity, SelectEntity):
67  """Representation of a Z-Wave select entity."""
68 
69  _attr_entity_category = EntityCategory.CONFIG
70 
71  def __init__(
72  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
73  ) -> None:
74  """Initialize a ZwaveSelectEntity entity."""
75  super().__init__(config_entry, driver, info)
76 
77  # Entity class attributes
78  self._attr_name_attr_name_attr_name = self.generate_namegenerate_name(include_value_name=True)
79  self._attr_options_attr_options = list(self.infoinfo.primary_value.metadata.states.values())
80 
81  @property
82  def current_option(self) -> str | None:
83  """Return the selected entity option to represent the entity state."""
84  if self.infoinfo.primary_value.value is None:
85  return None
86  return str(
87  self.infoinfo.primary_value.metadata.states.get(
88  str(self.infoinfo.primary_value.value), self.infoinfo.primary_value.value
89  )
90  )
91 
92  async def async_select_option(self, option: str) -> None:
93  """Change the selected option."""
94  key = next(
95  key
96  for key, val in self.infoinfo.primary_value.metadata.states.items()
97  if val == option
98  )
99  await self._async_set_value_async_set_value(self.infoinfo.primary_value, int(key))
100 
101 
103  """Representation of a Z-Wave door lock CC mode select entity."""
104 
105  def __init__(
106  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
107  ) -> None:
108  """Initialize a ZWaveDoorLockSelectEntity entity."""
109  super().__init__(config_entry, driver, info)
110  self._target_value_target_value = self.get_zwave_valueget_zwave_value(TARGET_MODE_PROPERTY)
111 
112  async def async_select_option(self, option: str) -> None:
113  """Change the selected option."""
114  assert self._target_value_target_value is not None
115  key = next(
116  key
117  for key, val in self.infoinfo.primary_value.metadata.states.items()
118  if val == option
119  )
120  await self._async_set_value_async_set_value(self._target_value_target_value, int(key))
121 
122 
124  """Representation of a Z-Wave config parameter select."""
125 
126  _attr_entity_category = EntityCategory.CONFIG
127 
128  def __init__(
129  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
130  ) -> None:
131  """Initialize a ZWaveConfigParameterSelect entity."""
132  super().__init__(config_entry, driver, info)
133 
134  property_key_name = self.infoinfo.primary_value.property_key_name
135  # Entity class attributes
136  self._attr_name_attr_name_attr_name_attr_name = self.generate_namegenerate_name(
137  alternate_value_name=self.infoinfo.primary_value.property_name,
138  additional_info=[property_key_name] if property_key_name else None,
139  )
140 
141 
143  """Representation of a Z-Wave default tone select entity."""
144 
145  _attr_entity_category = EntityCategory.CONFIG
146 
147  def __init__(
148  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
149  ) -> None:
150  """Initialize a ZwaveDefaultToneSelectEntity entity."""
151  super().__init__(config_entry, driver, info)
152  self._tones_value_tones_value = self.get_zwave_valueget_zwave_value(
153  TONE_ID_PROPERTY, command_class=CommandClass.SOUND_SWITCH
154  )
155 
156  # Entity class attributes
157  self._attr_name_attr_name_attr_name = self.generate_namegenerate_name(alternate_value_name=info.platform_hint)
158 
159  @property
160  def options(self) -> list[str]:
161  """Return a set of selectable options."""
162  # We know we can assert because this value is part of the discovery schema
163  assert self._tones_value_tones_value
164  return [
165  val
166  for key, val in self._tones_value_tones_value.metadata.states.items()
167  if int(key) not in (ToneID.DEFAULT, ToneID.OFF)
168  ]
169 
170  @property
171  def current_option(self) -> str | None:
172  """Return the selected entity option to represent the entity state."""
173  # We know we can assert because this value is part of the discovery schema
174  assert self._tones_value_tones_value
175  return str(
176  self._tones_value_tones_value.metadata.states.get(
177  str(self.infoinfo.primary_value.value), self.infoinfo.primary_value.value
178  )
179  )
180 
181  async def async_select_option(self, option: str) -> None:
182  """Change the selected option."""
183  # We know we can assert because this value is part of the discovery schema
184  assert self._tones_value_tones_value
185  key = next(
186  key
187  for key, val in self._tones_value_tones_value.metadata.states.items()
188  if val == option
189  )
190  await self._async_set_value_async_set_value(self.infoinfo.primary_value, int(key))
191 
192 
194  """Representation of a Z-Wave Multilevel Switch CC select entity."""
195 
196  def __init__(
197  self, config_entry: ConfigEntry, driver: Driver, info: ZwaveDiscoveryInfo
198  ) -> None:
199  """Initialize a ZwaveSelectEntity entity."""
200  super().__init__(config_entry, driver, info)
201  self._target_value_target_value = self.get_zwave_valueget_zwave_value(TARGET_VALUE_PROPERTY)
202  assert self.infoinfo.platform_data_template
203  self._lookup_map_lookup_map = cast(
204  dict[int, str], self.infoinfo.platform_data_template.static_data
205  )
206 
207  # Entity class attributes
208  self._attr_options_attr_options = list(self._lookup_map_lookup_map.values())
209 
210  @property
211  def current_option(self) -> str | None:
212  """Return the selected entity option to represent the entity state."""
213  if self.infoinfo.primary_value.value is None:
214  return None
215  return str(
216  self._lookup_map_lookup_map.get(
217  int(self.infoinfo.primary_value.value), self.infoinfo.primary_value.value
218  )
219  )
220 
221  async def async_select_option(self, option: str) -> None:
222  """Change the selected option."""
223  assert self._target_value_target_value is not None
224  key = next(key for key, val in self._lookup_map_lookup_map.items() if val == option)
225  await self._async_set_value_async_set_value(self._target_value_target_value, int(key))
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: select.py:130
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: select.py:107
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: select.py:149
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: select.py:198
None __init__(self, ConfigEntry config_entry, Driver driver, ZwaveDiscoveryInfo info)
Definition: select.py:73
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: select.py:31
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103