1 """Support for Cover devices."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from datetime
import timedelta
7 from enum
import IntFlag, StrEnum
10 from typing
import Any, final
12 from propcache
import cached_property
13 import voluptuous
as vol
18 SERVICE_CLOSE_COVER_TILT,
20 SERVICE_OPEN_COVER_TILT,
21 SERVICE_SET_COVER_POSITION,
22 SERVICE_SET_COVER_TILT_POSITION,
24 SERVICE_STOP_COVER_TILT,
26 SERVICE_TOGGLE_COVER_TILT,
35 DeprecatedConstantEnum,
36 all_with_deprecated_constants,
37 check_if_deprecated_constant,
38 dir_with_deprecated_constants,
46 from .const
import DOMAIN, INTENT_CLOSE_COVER, INTENT_OPEN_COVER
48 _LOGGER = logging.getLogger(__name__)
50 DATA_COMPONENT: HassKey[EntityComponent[CoverEntity]] =
HassKey(DOMAIN)
51 ENTITY_ID_FORMAT = DOMAIN +
".{}"
52 PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
53 PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
58 """State of Cover entities."""
76 """Device class for cover."""
91 DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.Coerce(CoverDeviceClass))
95 DEVICE_CLASSES = [cls.value
for cls
in CoverDeviceClass]
97 CoverDeviceClass.AWNING,
"2025.1"
100 CoverDeviceClass.BLIND,
"2025.1"
103 CoverDeviceClass.CURTAIN,
"2025.1"
106 CoverDeviceClass.DAMPER,
"2025.1"
110 CoverDeviceClass.GARAGE,
"2025.1"
114 CoverDeviceClass.SHADE,
"2025.1"
117 CoverDeviceClass.SHUTTER,
"2025.1"
120 CoverDeviceClass.WINDOW,
"2025.1"
127 """Supported features of the cover entity."""
136 SET_TILT_POSITION = 128
144 CoverEntityFeature.SET_POSITION,
"2025.1"
148 CoverEntityFeature.OPEN_TILT,
"2025.1"
151 CoverEntityFeature.CLOSE_TILT,
"2025.1"
154 CoverEntityFeature.STOP_TILT,
"2025.1"
157 CoverEntityFeature.SET_TILT_POSITION,
"2025.1"
160 ATTR_CURRENT_POSITION =
"current_position"
161 ATTR_CURRENT_TILT_POSITION =
"current_tilt_position"
162 ATTR_POSITION =
"position"
163 ATTR_TILT_POSITION =
"tilt_position"
167 def is_closed(hass: HomeAssistant, entity_id: str) -> bool:
168 """Return if the cover is closed based on the statemachine."""
169 return hass.states.is_state(entity_id, CoverState.CLOSED)
172 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
173 """Track states and offer events for covers."""
174 component = hass.data[DATA_COMPONENT] = EntityComponent[CoverEntity](
175 _LOGGER, DOMAIN, hass, SCAN_INTERVAL
178 await component.async_setup(config)
180 component.async_register_entity_service(
181 SERVICE_OPEN_COVER,
None,
"async_open_cover", [CoverEntityFeature.OPEN]
184 component.async_register_entity_service(
185 SERVICE_CLOSE_COVER,
None,
"async_close_cover", [CoverEntityFeature.CLOSE]
188 component.async_register_entity_service(
189 SERVICE_SET_COVER_POSITION,
191 vol.Required(ATTR_POSITION): vol.All(
192 vol.Coerce(int), vol.Range(min=0, max=100)
195 "async_set_cover_position",
196 [CoverEntityFeature.SET_POSITION],
199 component.async_register_entity_service(
200 SERVICE_STOP_COVER,
None,
"async_stop_cover", [CoverEntityFeature.STOP]
203 component.async_register_entity_service(
207 [CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE],
210 component.async_register_entity_service(
211 SERVICE_OPEN_COVER_TILT,
213 "async_open_cover_tilt",
214 [CoverEntityFeature.OPEN_TILT],
217 component.async_register_entity_service(
218 SERVICE_CLOSE_COVER_TILT,
220 "async_close_cover_tilt",
221 [CoverEntityFeature.CLOSE_TILT],
224 component.async_register_entity_service(
225 SERVICE_STOP_COVER_TILT,
227 "async_stop_cover_tilt",
228 [CoverEntityFeature.STOP_TILT],
231 component.async_register_entity_service(
232 SERVICE_SET_COVER_TILT_POSITION,
234 vol.Required(ATTR_TILT_POSITION): vol.All(
235 vol.Coerce(int), vol.Range(min=0, max=100)
238 "async_set_cover_tilt_position",
239 [CoverEntityFeature.SET_TILT_POSITION],
242 component.async_register_entity_service(
243 SERVICE_TOGGLE_COVER_TILT,
246 [CoverEntityFeature.OPEN_TILT | CoverEntityFeature.CLOSE_TILT],
253 """Set up a config entry."""
258 """Unload a config entry."""
263 """A class that describes cover entities."""
265 device_class: CoverDeviceClass |
None =
None
268 CACHED_PROPERTIES_WITH_ATTR_ = {
269 "current_cover_position",
270 "current_cover_tilt_position",
279 """Base class for cover entities."""
281 entity_description: CoverEntityDescription
282 _attr_current_cover_position: int |
None =
None
283 _attr_current_cover_tilt_position: int |
None =
None
284 _attr_device_class: CoverDeviceClass |
None
285 _attr_is_closed: bool |
None
286 _attr_is_closing: bool |
None =
None
287 _attr_is_opening: bool |
None =
None
288 _attr_state:
None =
None
289 _attr_supported_features: CoverEntityFeature |
None
291 _cover_is_last_toggle_direction_open =
True
295 """Return current position of cover.
297 None is unknown, 0 is closed, 100 is fully open.
299 return self._attr_current_cover_position
303 """Return current position of cover tilt.
305 None is unknown, 0 is closed, 100 is fully open.
307 return self._attr_current_cover_tilt_position
311 """Return the class of this entity."""
312 if hasattr(self,
"_attr_device_class"):
313 return self._attr_device_class
314 if hasattr(self,
"entity_description"):
315 return self.entity_description.device_class
321 """Return the state of the cover."""
324 return CoverState.OPENING
327 return CoverState.CLOSING
329 if (closed := self.
is_closedis_closed)
is None:
332 return CoverState.CLOSED
if closed
else CoverState.OPEN
337 """Return the state attributes."""
341 data[ATTR_CURRENT_POSITION] = current
344 data[ATTR_CURRENT_TILT_POSITION] = current_tilt
350 """Flag supported features."""
351 if (features := self._attr_supported_features)
is not None:
352 if type(features)
is int:
358 supported_features = (
359 CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
363 supported_features |= CoverEntityFeature.SET_POSITION
366 supported_features |= (
367 CoverEntityFeature.OPEN_TILT
368 | CoverEntityFeature.CLOSE_TILT
369 | CoverEntityFeature.STOP_TILT
370 | CoverEntityFeature.SET_TILT_POSITION
373 return supported_features
377 """Return if the cover is opening or not."""
378 return self._attr_is_opening
382 """Return if the cover is closing or not."""
383 return self._attr_is_closing
387 """Return if the cover is closed or not."""
388 return self._attr_is_closed
391 """Open the cover."""
392 raise NotImplementedError
395 """Open the cover."""
396 await self.
hasshass.async_add_executor_job(ft.partial(self.
open_coveropen_cover, **kwargs))
400 raise NotImplementedError
404 await self.
hasshass.async_add_executor_job(ft.partial(self.
close_coverclose_cover, **kwargs))
407 """Toggle the entity."""
413 function = self._get_toggle_function(fns)
417 """Toggle the entity."""
423 function = self._get_toggle_function(fns)
424 await function(**kwargs)
427 """Move the cover to a specific position."""
430 """Move the cover to a specific position."""
431 await self.
hasshass.async_add_executor_job(
436 """Stop the cover."""
439 """Stop the cover."""
440 await self.
hasshass.async_add_executor_job(ft.partial(self.
stop_coverstop_cover, **kwargs))
443 """Open the cover tilt."""
446 """Open the cover tilt."""
447 await self.
hasshass.async_add_executor_job(
452 """Close the cover tilt."""
455 """Close the cover tilt."""
456 await self.
hasshass.async_add_executor_job(
461 """Move the cover tilt to a specific position."""
464 """Move the cover tilt to a specific position."""
465 await self.
hasshass.async_add_executor_job(
470 """Stop the cover."""
473 """Stop the cover."""
474 await self.
hasshass.async_add_executor_job(
479 """Toggle the entity."""
486 """Toggle the entity."""
492 def _get_toggle_function[**_P, _R](
493 self, fns: dict[str, Callable[_P, _R]]
494 ) -> Callable[_P, _R]:
522 __getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals())
523 __dir__ = ft.partial(
524 dir_with_deprecated_constants, module_globals_keys=[*globals().keys()]
None close_cover(self, **Any kwargs)
int|None current_cover_tilt_position(self)
CoverDeviceClass|None device_class(self)
bool|None is_closed(self)
bool|None is_opening(self)
None async_toggle_tilt(self, **Any kwargs)
None open_cover(self, **Any kwargs)
current_cover_tilt_position
None async_toggle(self, **Any kwargs)
None async_open_cover_tilt(self, **Any kwargs)
None async_open_cover(self, **Any kwargs)
CoverEntityFeature supported_features(self)
None async_close_cover(self, **Any kwargs)
dict[str, Any] state_attributes(self)
None async_set_cover_tilt_position(self, **Any kwargs)
None async_set_cover_position(self, **Any kwargs)
None async_stop_cover_tilt(self, **Any kwargs)
None stop_cover(self, **Any kwargs)
int|None current_cover_position(self)
None toggle_tilt(self, **Any kwargs)
None close_cover_tilt(self, **Any kwargs)
None stop_cover_tilt(self, **Any kwargs)
None async_stop_cover(self, **Any kwargs)
None set_cover_tilt_position(self, **Any kwargs)
None toggle(self, **Any kwargs)
None async_close_cover_tilt(self, **Any kwargs)
bool|None is_closing(self)
_cover_is_last_toggle_direction_open
None set_cover_position(self, **Any kwargs)
None open_cover_tilt(self, **Any kwargs)
None _report_deprecated_supported_features_values(self, IntFlag replacement)
int|None supported_features(self)
bool is_closed(HomeAssistant hass, str entity_id)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
list[str] all_with_deprecated_constants(dict[str, Any] module_globals)