Home Assistant Unofficial Reference 2024.12.1
cover.py
Go to the documentation of this file.
1 """Cover for Shelly."""
2 
3 from __future__ import annotations
4 
5 from typing import Any, cast
6 
7 from aioshelly.block_device import Block
8 from aioshelly.const import RPC_GENERATIONS
9 
11  ATTR_POSITION,
12  ATTR_TILT_POSITION,
13  CoverDeviceClass,
14  CoverEntity,
15  CoverEntityFeature,
16 )
17 from homeassistant.core import HomeAssistant, callback
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 
20 from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
21 from .entity import ShellyBlockEntity, ShellyRpcEntity
22 from .utils import get_device_entry_gen, get_rpc_key_ids
23 
24 
26  hass: HomeAssistant,
27  config_entry: ShellyConfigEntry,
28  async_add_entities: AddEntitiesCallback,
29 ) -> None:
30  """Set up covers for device."""
31  if get_device_entry_gen(config_entry) in RPC_GENERATIONS:
32  return async_setup_rpc_entry(hass, config_entry, async_add_entities)
33 
34  return async_setup_block_entry(hass, config_entry, async_add_entities)
35 
36 
37 @callback
39  hass: HomeAssistant,
40  config_entry: ShellyConfigEntry,
41  async_add_entities: AddEntitiesCallback,
42 ) -> None:
43  """Set up cover for device."""
44  coordinator = config_entry.runtime_data.block
45  assert coordinator and coordinator.device.blocks
46  blocks = [block for block in coordinator.device.blocks if block.type == "roller"]
47 
48  if not blocks:
49  return
50 
51  async_add_entities(BlockShellyCover(coordinator, block) for block in blocks)
52 
53 
54 @callback
56  hass: HomeAssistant,
57  config_entry: ShellyConfigEntry,
58  async_add_entities: AddEntitiesCallback,
59 ) -> None:
60  """Set up entities for RPC device."""
61  coordinator = config_entry.runtime_data.rpc
62  assert coordinator
63  cover_key_ids = get_rpc_key_ids(coordinator.device.status, "cover")
64 
65  if not cover_key_ids:
66  return
67 
68  async_add_entities(RpcShellyCover(coordinator, id_) for id_ in cover_key_ids)
69 
70 
72  """Entity that controls a cover on block based Shelly devices."""
73 
74  _attr_device_class = CoverDeviceClass.SHUTTER
75  _attr_supported_features: CoverEntityFeature = (
76  CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
77  )
78 
79  def __init__(self, coordinator: ShellyBlockCoordinator, block: Block) -> None:
80  """Initialize block cover."""
81  super().__init__(coordinator, block)
82  self.control_resultcontrol_result: dict[str, Any] | None = None
83  if self.coordinator.device.settings["rollers"][0]["positioning"]:
84  self._attr_supported_features |= CoverEntityFeature.SET_POSITION
85 
86  @property
87  def is_closed(self) -> bool:
88  """If cover is closed."""
89  if self.control_resultcontrol_result:
90  return cast(bool, self.control_resultcontrol_result["current_pos"] == 0)
91 
92  return cast(int, self.blockblock.rollerPos) == 0
93 
94  @property
95  def current_cover_position(self) -> int:
96  """Position of the cover."""
97  if self.control_resultcontrol_result:
98  return cast(int, self.control_resultcontrol_result["current_pos"])
99 
100  return cast(int, self.blockblock.rollerPos)
101 
102  @property
103  def is_closing(self) -> bool:
104  """Return if the cover is closing."""
105  if self.control_resultcontrol_result:
106  return cast(bool, self.control_resultcontrol_result["state"] == "close")
107 
108  return self.blockblock.roller == "close"
109 
110  @property
111  def is_opening(self) -> bool:
112  """Return if the cover is opening."""
113  if self.control_resultcontrol_result:
114  return cast(bool, self.control_resultcontrol_result["state"] == "open")
115 
116  return self.blockblock.roller == "open"
117 
118  async def async_close_cover(self, **kwargs: Any) -> None:
119  """Close cover."""
120  self.control_resultcontrol_result = await self.set_stateset_state(go="close")
121  self.async_write_ha_stateasync_write_ha_state()
122 
123  async def async_open_cover(self, **kwargs: Any) -> None:
124  """Open cover."""
125  self.control_resultcontrol_result = await self.set_stateset_state(go="open")
126  self.async_write_ha_stateasync_write_ha_state()
127 
128  async def async_set_cover_position(self, **kwargs: Any) -> None:
129  """Move the cover to a specific position."""
130  self.control_resultcontrol_result = await self.set_stateset_state(
131  go="to_pos", roller_pos=kwargs[ATTR_POSITION]
132  )
133  self.async_write_ha_stateasync_write_ha_state()
134 
135  async def async_stop_cover(self, **_kwargs: Any) -> None:
136  """Stop the cover."""
137  self.control_resultcontrol_result = await self.set_stateset_state(go="stop")
138  self.async_write_ha_stateasync_write_ha_state()
139 
140  @callback
141  def _update_callback(self) -> None:
142  """When device updates, clear control result that overrides state."""
143  self.control_resultcontrol_result = None
144  super()._update_callback()
145 
146 
148  """Entity that controls a cover on RPC based Shelly devices."""
149 
150  _attr_device_class = CoverDeviceClass.SHUTTER
151  _attr_supported_features: CoverEntityFeature = (
152  CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
153  )
154 
155  def __init__(self, coordinator: ShellyRpcCoordinator, id_: int) -> None:
156  """Initialize rpc cover."""
157  super().__init__(coordinator, f"cover:{id_}")
158  self._id_id = id_
159  if self.statusstatus["pos_control"]:
160  self._attr_supported_features |= CoverEntityFeature.SET_POSITION
161  if coordinator.device.config[f"cover:{id_}"].get("slat", {}).get("enable"):
162  self._attr_supported_features |= (
163  CoverEntityFeature.OPEN_TILT
164  | CoverEntityFeature.CLOSE_TILT
165  | CoverEntityFeature.STOP_TILT
166  | CoverEntityFeature.SET_TILT_POSITION
167  )
168 
169  @property
170  def is_closed(self) -> bool | None:
171  """If cover is closed."""
172  return cast(bool, self.statusstatus["state"] == "closed")
173 
174  @property
175  def current_cover_position(self) -> int | None:
176  """Position of the cover."""
177  if not self.statusstatus["pos_control"]:
178  return None
179 
180  return cast(int, self.statusstatus["current_pos"])
181 
182  @property
183  def current_cover_tilt_position(self) -> int | None:
184  """Return current position of cover tilt."""
185  if "slat_pos" not in self.statusstatus:
186  return None
187 
188  return cast(int, self.statusstatus["slat_pos"])
189 
190  @property
191  def is_closing(self) -> bool:
192  """Return if the cover is closing."""
193  return cast(bool, self.statusstatus["state"] == "closing")
194 
195  @property
196  def is_opening(self) -> bool:
197  """Return if the cover is opening."""
198  return cast(bool, self.statusstatus["state"] == "opening")
199 
200  async def async_close_cover(self, **kwargs: Any) -> None:
201  """Close cover."""
202  await self.call_rpccall_rpc("Cover.Close", {"id": self._id_id})
203 
204  async def async_open_cover(self, **kwargs: Any) -> None:
205  """Open cover."""
206  await self.call_rpccall_rpc("Cover.Open", {"id": self._id_id})
207 
208  async def async_set_cover_position(self, **kwargs: Any) -> None:
209  """Move the cover to a specific position."""
210  await self.call_rpccall_rpc(
211  "Cover.GoToPosition", {"id": self._id_id, "pos": kwargs[ATTR_POSITION]}
212  )
213 
214  async def async_stop_cover(self, **_kwargs: Any) -> None:
215  """Stop the cover."""
216  await self.call_rpccall_rpc("Cover.Stop", {"id": self._id_id})
217 
218  async def async_open_cover_tilt(self, **kwargs: Any) -> None:
219  """Open the cover tilt."""
220  await self.call_rpccall_rpc("Cover.GoToPosition", {"id": self._id_id, "slat_pos": 100})
221 
222  async def async_close_cover_tilt(self, **kwargs: Any) -> None:
223  """Close the cover tilt."""
224  await self.call_rpccall_rpc("Cover.GoToPosition", {"id": self._id_id, "slat_pos": 0})
225 
226  async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
227  """Move the cover tilt to a specific position."""
228  await self.call_rpccall_rpc(
229  "Cover.GoToPosition",
230  {"id": self._id_id, "slat_pos": kwargs[ATTR_TILT_POSITION]},
231  )
232 
233  async def async_stop_cover_tilt(self, **kwargs: Any) -> None:
234  """Stop the cover."""
235  await self.call_rpccall_rpc("Cover.Stop", {"id": self._id_id})
None async_set_cover_position(self, **Any kwargs)
Definition: cover.py:128
None __init__(self, ShellyBlockCoordinator coordinator, Block block)
Definition: cover.py:79
None async_set_cover_position(self, **Any kwargs)
Definition: cover.py:208
None async_open_cover_tilt(self, **Any kwargs)
Definition: cover.py:218
None __init__(self, ShellyRpcCoordinator coordinator, int id_)
Definition: cover.py:155
None async_close_cover_tilt(self, **Any kwargs)
Definition: cover.py:222
None async_stop_cover_tilt(self, **Any kwargs)
Definition: cover.py:233
None async_set_cover_tilt_position(self, **Any kwargs)
Definition: cover.py:226
None async_stop_cover(self, **Any _kwargs)
Definition: cover.py:214
Any call_rpc(self, str method, Any params)
Definition: entity.py:384
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:29
None async_setup_rpc_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:59
None async_setup_block_entry(HomeAssistant hass, ShellyConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:42
list[int] get_rpc_key_ids(dict[str, Any] keys_dict, str key)
Definition: utils.py:369
int get_device_entry_gen(ConfigEntry entry)
Definition: utils.py:353