Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for esphome selects."""
2 
3 from __future__ import annotations
4 
5 from aioesphomeapi import EntityInfo, SelectInfo, SelectState
6 
8  AssistPipelineSelect,
9  VadSensitivitySelect,
10 )
11 from homeassistant.components.assist_satellite import AssistSatelliteConfiguration
12 from homeassistant.components.select import SelectEntity, SelectEntityDescription
13 from homeassistant.const import EntityCategory
14 from homeassistant.core import HomeAssistant, callback
15 from homeassistant.helpers import restore_state
16 from homeassistant.helpers.entity_platform import AddEntitiesCallback
17 
18 from .const import DOMAIN
19 from .entity import (
20  EsphomeAssistEntity,
21  EsphomeEntity,
22  convert_api_error_ha_error,
23  esphome_state_property,
24  platform_async_setup_entry,
25 )
26 from .entry_data import ESPHomeConfigEntry, RuntimeEntryData
27 
28 
30  hass: HomeAssistant,
31  entry: ESPHomeConfigEntry,
32  async_add_entities: AddEntitiesCallback,
33 ) -> None:
34  """Set up esphome selects based on a config entry."""
36  hass,
37  entry,
38  async_add_entities,
39  info_type=SelectInfo,
40  entity_type=EsphomeSelect,
41  state_type=SelectState,
42  )
43 
44  entry_data = entry.runtime_data
45  assert entry_data.device_info is not None
46  if entry_data.device_info.voice_assistant_feature_flags_compat(
47  entry_data.api_version
48  ):
50  [
51  EsphomeAssistPipelineSelect(hass, entry_data),
52  EsphomeVadSensitivitySelect(hass, entry_data),
53  EsphomeAssistSatelliteWakeWordSelect(hass, entry_data),
54  ]
55  )
56 
57 
58 class EsphomeSelect(EsphomeEntity[SelectInfo, SelectState], SelectEntity):
59  """A select implementation for esphome."""
60 
61  @callback
62  def _on_static_info_update(self, static_info: EntityInfo) -> None:
63  """Set attrs from static info."""
64  super()._on_static_info_update(static_info)
65  self._attr_options_attr_options = self._static_info_static_info.options
66 
67  @property
68  @esphome_state_property
69  def current_option(self) -> str | None:
70  """Return the state of the entity."""
71  state = self._state_state
72  return None if state.missing_state else state.state
73 
74  @convert_api_error_ha_error
75  async def async_select_option(self, option: str) -> None:
76  """Change the selected option."""
77  self._client_client.select_command(self._key_key, option)
78 
79 
81  """Pipeline selector for esphome devices."""
82 
83  def __init__(self, hass: HomeAssistant, entry_data: RuntimeEntryData) -> None:
84  """Initialize a pipeline selector."""
85  EsphomeAssistEntity.__init__(self, entry_data)
86  AssistPipelineSelect.__init__(self, hass, DOMAIN, self._device_info_device_info.mac_address)
87 
88 
90  """VAD sensitivity selector for ESPHome devices."""
91 
92  def __init__(self, hass: HomeAssistant, entry_data: RuntimeEntryData) -> None:
93  """Initialize a VAD sensitivity selector."""
94  EsphomeAssistEntity.__init__(self, entry_data)
95  VadSensitivitySelect.__init__(self, hass, self._device_info_device_info.mac_address)
96 
97 
99  EsphomeAssistEntity, SelectEntity, restore_state.RestoreEntity
100 ):
101  """Wake word selector for esphome devices."""
102 
103  entity_description = SelectEntityDescription(
104  key="wake_word",
105  translation_key="wake_word",
106  entity_category=EntityCategory.CONFIG,
107  )
108  _attr_should_poll = False
109  _attr_current_option: str | None = None
110  _attr_options: list[str] = []
111 
112  def __init__(self, hass: HomeAssistant, entry_data: RuntimeEntryData) -> None:
113  """Initialize a wake word selector."""
114  EsphomeAssistEntity.__init__(self, entry_data)
115 
116  unique_id_prefix = self._device_info_device_info.mac_address
117  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{unique_id_prefix}-wake_word"
118 
119  # name -> id
120  self._wake_words_wake_words: dict[str, str] = {}
121 
122  @property
123  def available(self) -> bool:
124  """Return if entity is available."""
125  return bool(self._attr_options_attr_options)
126 
127  async def async_added_to_hass(self) -> None:
128  """Run when entity about to be added to hass."""
129  await super().async_added_to_hass()
130 
131  # Update options when config is updated
132  self.async_on_removeasync_on_remove(
133  self._entry_data.async_register_assist_satellite_config_updated_callback(
134  self.async_satellite_config_updatedasync_satellite_config_updated
135  )
136  )
137 
138  async def async_select_option(self, option: str) -> None:
139  """Select an option."""
140  if wake_word_id := self._wake_words_wake_words.get(option):
141  # _attr_current_option will be updated on
142  # async_satellite_config_updated after the device sets the wake
143  # word.
144  self._entry_data.async_assist_satellite_set_wake_word(wake_word_id)
145 
147  self, config: AssistSatelliteConfiguration
148  ) -> None:
149  """Update options with available wake words."""
150  if (not config.available_wake_words) or (config.max_active_wake_words < 1):
151  self._attr_current_option_attr_current_option = None
152  self._wake_words_wake_words.clear()
153  self.async_write_ha_stateasync_write_ha_state()
154  return
155 
156  self._wake_words_wake_words = {w.wake_word: w.id for w in config.available_wake_words}
157  self._attr_options_attr_options = sorted(self._wake_words_wake_words)
158 
159  if config.active_wake_words:
160  # Select first active wake word
161  wake_word_id = config.active_wake_words[0]
162  for wake_word in config.available_wake_words:
163  if wake_word.id == wake_word_id:
164  self._attr_current_option_attr_current_option = wake_word.wake_word
165  else:
166  # Select first available wake word
167  self._attr_current_option_attr_current_option = config.available_wake_words[0].wake_word
168 
169  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, HomeAssistant hass, RuntimeEntryData entry_data)
Definition: select.py:83
None __init__(self, HomeAssistant hass, RuntimeEntryData entry_data)
Definition: select.py:112
None async_satellite_config_updated(self, AssistSatelliteConfiguration config)
Definition: select.py:148
None _on_static_info_update(self, EntityInfo static_info)
Definition: select.py:62
None __init__(self, HomeAssistant hass, RuntimeEntryData entry_data)
Definition: select.py:92
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None platform_async_setup_entry(HomeAssistant hass, ESPHomeConfigEntry entry, AddEntitiesCallback async_add_entities, *type[_InfoT] info_type, type[_EntityT] entity_type, type[_StateT] state_type)
Definition: entity.py:89
None async_setup_entry(HomeAssistant hass, ESPHomeConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: select.py:33