Home Assistant Unofficial Reference 2024.12.1
cover.py
Go to the documentation of this file.
1 """Elmax cover platform."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from elmax_api.model.command import CoverCommand
9 from elmax_api.model.cover_status import CoverStatus
10 
11 from homeassistant.components.cover import CoverEntity, CoverEntityFeature
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.core import HomeAssistant
14 from homeassistant.helpers.entity_platform import AddEntitiesCallback
15 
16 from .const import DOMAIN
17 from .coordinator import ElmaxCoordinator
18 from .entity import ElmaxEntity
19 
20 _LOGGER = logging.getLogger(__name__)
21 
22 _COMMAND_BY_MOTION_STATUS = { # Maps the stop command to use for every cover motion status
23  CoverStatus.DOWN: CoverCommand.DOWN,
24  CoverStatus.UP: CoverCommand.UP,
25  CoverStatus.IDLE: None,
26 }
27 
28 
30  hass: HomeAssistant,
31  config_entry: ConfigEntry,
32  async_add_entities: AddEntitiesCallback,
33 ) -> None:
34  """Set up the Elmax cover platform."""
35  coordinator: ElmaxCoordinator = hass.data[DOMAIN][config_entry.entry_id]
36  # Add the cover feature only if supported by the current panel.
37  if coordinator.data is None or not coordinator.data.cover_feature:
38  return
39 
40  known_devices = set()
41 
42  def _discover_new_devices():
43  if (panel_status := coordinator.data) is None:
44  return # In case the panel is offline, its status will be None. In that case, simply do nothing
45 
46  # Otherwise, add all the entities we found
47  entities = []
48  for cover in panel_status.covers:
49  # Skip already handled devices
50  if cover.endpoint_id in known_devices:
51  continue
52  entity = ElmaxCover(
53  elmax_device=cover,
54  panel_version=panel_status.release,
55  coordinator=coordinator,
56  )
57  entities.append(entity)
58 
59  if entities:
60  async_add_entities(entities)
61  known_devices.update([e.unique_id for e in entities])
62 
63  # Register a listener for the discovery of new devices
64  config_entry.async_on_unload(coordinator.async_add_listener(_discover_new_devices))
65 
66  # Immediately run a discovery, so we don't need to wait for the next update
67  _discover_new_devices()
68 
69 
71  """Elmax Cover entity implementation."""
72 
73  _attr_supported_features = (
74  CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
75  )
76 
77  def __check_cover_status(self, status_to_check: CoverStatus) -> bool | None:
78  """Check if the current cover entity is in a specific state."""
79  if (
80  state := self.coordinator.get_cover_state(self._device_device.endpoint_id).status
81  ) is None:
82  return None
83  return state == status_to_check
84 
85  @property
86  def is_closed(self) -> bool | None:
87  """Tells if the cover is closed or not."""
88  return self.coordinator.get_cover_state(self._device_device.endpoint_id).position == 0
89 
90  @property
91  def current_cover_position(self) -> int | None:
92  """Return current position of cover.
93 
94  None is unknown, 0 is closed, 100 is fully open.
95  """
96  return self.coordinator.get_cover_state(self._device_device.endpoint_id).position
97 
98  @property
99  def is_opening(self) -> bool | None:
100  """Tells if the cover is opening or not."""
101  return self.__check_cover_status__check_cover_status(CoverStatus.UP)
102 
103  @property
104  def is_closing(self) -> bool | None:
105  """Return if the cover is closing or not."""
106  return self.__check_cover_status__check_cover_status(CoverStatus.DOWN)
107 
108  async def async_stop_cover(self, **kwargs: Any) -> None:
109  """Stop the cover."""
110  # To stop the cover, Elmax requires us to re-issue the same command once again.
111  # To detect the current motion status, we request an immediate refresh to the coordinator
112  await self.coordinator.async_request_refresh()
113  motion_status = self.coordinator.get_cover_state(
114  self._device_device.endpoint_id
115  ).status
116  command = _COMMAND_BY_MOTION_STATUS[motion_status]
117  if command:
118  await self.coordinator.http_client.execute_command(
119  endpoint_id=self._device_device.endpoint_id, command=command
120  )
121  else:
122  _LOGGER.debug("Ignoring stop request as the cover is IDLE")
123 
124  async def async_open_cover(self, **kwargs: Any) -> None:
125  """Open the cover."""
126  await self.coordinator.http_client.execute_command(
127  endpoint_id=self._device_device.endpoint_id, command=CoverCommand.UP
128  )
129 
130  async def async_close_cover(self, **kwargs: Any) -> None:
131  """Close the cover."""
132  await self.coordinator.http_client.execute_command(
133  endpoint_id=self._device_device.endpoint_id, command=CoverCommand.DOWN
134  )
None async_open_cover(self, **Any kwargs)
Definition: cover.py:124
None async_close_cover(self, **Any kwargs)
Definition: cover.py:130
None async_stop_cover(self, **Any kwargs)
Definition: cover.py:108
bool|None __check_cover_status(self, CoverStatus status_to_check)
Definition: cover.py:77
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:33