1 """Component to allow selecting an option from a list as platforms."""
3 from __future__
import annotations
5 from datetime
import timedelta
7 from typing
import Any, final
9 from propcache
import cached_property
10 import voluptuous
as vol
29 SERVICE_SELECT_OPTION,
30 SERVICE_SELECT_PREVIOUS,
33 _LOGGER = logging.getLogger(__name__)
35 DATA_COMPONENT: HassKey[EntityComponent[SelectEntity]] =
HassKey(DOMAIN)
36 ENTITY_ID_FORMAT = DOMAIN +
".{}"
37 PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
38 PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
48 "PLATFORM_SCHEMA_BASE",
51 "SelectEntityDescription",
52 "SERVICE_SELECT_FIRST",
53 "SERVICE_SELECT_LAST",
54 "SERVICE_SELECT_NEXT",
55 "SERVICE_SELECT_OPTION",
56 "SERVICE_SELECT_PREVIOUS",
62 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
63 """Set up Select entities."""
64 component = hass.data[DATA_COMPONENT] = EntityComponent[SelectEntity](
65 _LOGGER, DOMAIN, hass, SCAN_INTERVAL
67 await component.async_setup(config)
69 component.async_register_entity_service(
72 SelectEntity.async_first.__name__,
75 component.async_register_entity_service(
78 SelectEntity.async_last.__name__,
81 component.async_register_entity_service(
83 {vol.Optional(ATTR_CYCLE, default=
True): bool},
84 SelectEntity.async_next.__name__,
87 component.async_register_entity_service(
88 SERVICE_SELECT_OPTION,
89 {vol.Required(ATTR_OPTION): cv.string},
90 SelectEntity.async_handle_select_option.__name__,
93 component.async_register_entity_service(
94 SERVICE_SELECT_PREVIOUS,
95 {vol.Optional(ATTR_CYCLE, default=
True): bool},
96 SelectEntity.async_previous.__name__,
103 """Set up a config entry."""
108 """Unload a config entry."""
113 """A class that describes select entities."""
115 options: list[str] |
None =
None
118 CACHED_PROPERTIES_WITH_ATTR_ = {
125 """Representation of a Select entity."""
127 _entity_component_unrecorded_attributes = frozenset({ATTR_OPTIONS})
129 entity_description: SelectEntityDescription
130 _attr_current_option: str |
None
131 _attr_options: list[str]
132 _attr_state:
None =
None
136 """Return capability attributes."""
138 ATTR_OPTIONS: self.
optionsoptions,
144 """Return the entity state."""
146 if current_option
is None or current_option
not in self.
optionsoptions:
148 return current_option
152 """Return a set of selectable options."""
153 if hasattr(self,
"_attr_options"):
154 return self._attr_options
156 hasattr(self,
"entity_description")
157 and self.entity_description.options
is not None
159 return self.entity_description.options
164 """Return the selected entity option to represent the entity state."""
165 return self._attr_current_option
170 """Raise ServiceValidationError on invalid option."""
172 if not options
or option
not in options:
173 friendly_options: str =
", ".join(options
or [])
175 translation_domain=DOMAIN,
176 translation_key=
"not_valid_option",
177 translation_placeholders={
180 "options": friendly_options,
186 """Service call wrapper to set a new value."""
191 """Change the selected option."""
192 raise NotImplementedError
195 """Change the selected option."""
196 await self.
hasshass.async_add_executor_job(self.
select_optionselect_option, option)
200 """Select first option."""
205 """Select last option."""
210 """Select next option.
212 If there is no current option, first item is the next.
221 """Select previous option.
223 If there is no current option, last item is the previous.
232 """Offset current index."""
236 if current_option
is not None and current_option
in self.
optionsoptions:
237 current_index = self.
optionsoptions.index(current_option)
239 new_index = current_index + offset
241 new_index = new_index % len(options)
244 elif new_index >= len(options):
245 new_index = len(options) - 1
251 """Select new option by index."""
253 new_index = idx % len(options)
str|None current_option(self)
None async_previous(self, bool cycle)
None async_next(self, bool cycle)
None _valid_option_or_raise(self, str option)
None select_option(self, str option)
dict[str, Any] capability_attributes(self)
None _async_offset_index(self, int offset, bool cycle)
None _async_select_index(self, int idx)
None async_handle_select_option(self, str option)
None async_select_option(self, str option)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)