Home Assistant Unofficial Reference 2024.12.1
cover.py
Go to the documentation of this file.
1 """Support for Soma Covers."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
8  ATTR_POSITION,
9  ATTR_TILT_POSITION,
10  CoverDeviceClass,
11  CoverEntity,
12  CoverEntityFeature,
13 )
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.core import HomeAssistant
16 from homeassistant.exceptions import HomeAssistantError
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 
19 from .const import API, DEVICES, DOMAIN
20 from .entity import SomaEntity
21 from .utils import is_api_response_success
22 
23 
25  hass: HomeAssistant,
26  config_entry: ConfigEntry,
27  async_add_entities: AddEntitiesCallback,
28 ) -> None:
29  """Set up the Soma cover platform."""
30 
31  api = hass.data[DOMAIN][API]
32  devices = hass.data[DOMAIN][DEVICES]
33  entities: list[SomaTilt | SomaShade] = []
34 
35  for device in devices:
36  # Assume a shade device if the type is not present in the api response (Connect <2.2.6)
37  if "type" in device and device["type"].lower() == "tilt":
38  entities.append(SomaTilt(device, api))
39  else:
40  entities.append(SomaShade(device, api))
41 
42  async_add_entities(entities, True)
43 
44 
46  """Representation of a Soma Tilt device."""
47 
48  _attr_name = None
49  _attr_device_class = CoverDeviceClass.BLIND
50  _attr_supported_features = (
51  CoverEntityFeature.OPEN_TILT
52  | CoverEntityFeature.CLOSE_TILT
53  | CoverEntityFeature.STOP_TILT
54  | CoverEntityFeature.SET_TILT_POSITION
55  )
56  CLOSED_UP_THRESHOLD = 80
57  CLOSED_DOWN_THRESHOLD = 20
58 
59  @property
60  def current_cover_tilt_position(self) -> int:
61  """Return the current cover tilt position."""
62  return self.current_positioncurrent_positioncurrent_position
63 
64  @property
65  def is_closed(self) -> bool:
66  """Return if the cover tilt is closed."""
67  if (
68  self.current_positioncurrent_positioncurrent_position < self.CLOSED_DOWN_THRESHOLDCLOSED_DOWN_THRESHOLD
69  or self.current_positioncurrent_positioncurrent_position > self.CLOSED_UP_THRESHOLDCLOSED_UP_THRESHOLD
70  ):
71  return True
72  return False
73 
74  def close_cover_tilt(self, **kwargs: Any) -> None:
75  """Close the cover tilt."""
76  response = self.apiapi.set_shade_position(self.devicedevice["mac"], 100)
77  if not is_api_response_success(response):
78  raise HomeAssistantError(
79  f'Error while closing the cover ({self.name}): {response["msg"]}'
80  )
81  self.set_positionset_position(0)
82 
83  def open_cover_tilt(self, **kwargs: Any) -> None:
84  """Open the cover tilt."""
85  response = self.apiapi.set_shade_position(self.devicedevice["mac"], -100)
86  if not is_api_response_success(response):
87  raise HomeAssistantError(
88  f'Error while opening the cover ({self.name}): {response["msg"]}'
89  )
90  self.set_positionset_position(100)
91 
92  def stop_cover_tilt(self, **kwargs: Any) -> None:
93  """Stop the cover tilt."""
94  response = self.apiapi.stop_shade(self.devicedevice["mac"])
95  if not is_api_response_success(response):
96  raise HomeAssistantError(
97  f'Error while stopping the cover ({self.name}): {response["msg"]}'
98  )
99  # Set cover position to some value where up/down are both enabled
100  self.set_positionset_position(50)
101 
102  def set_cover_tilt_position(self, **kwargs: Any) -> None:
103  """Move the cover tilt to a specific position."""
104  # 0 -> Closed down (api: 100)
105  # 50 -> Fully open (api: 0)
106  # 100 -> Closed up (api: -100)
107  target_api_position = 100 - ((kwargs[ATTR_TILT_POSITION] / 50) * 100)
108  response = self.apiapi.set_shade_position(self.devicedevice["mac"], target_api_position)
109  if not is_api_response_success(response):
110  raise HomeAssistantError(
111  f"Error while setting the cover position ({self.name}):"
112  f' {response["msg"]}'
113  )
114  self.set_positionset_position(kwargs[ATTR_TILT_POSITION])
115 
116  async def async_update(self) -> None:
117  """Update the entity with the latest data."""
118  response = await self.get_shade_state_from_apiget_shade_state_from_api()
119 
120  api_position = int(response["position"])
121 
122  if "closed_upwards" in response:
123  self.current_positioncurrent_positioncurrent_position = 50 + ((api_position * 50) / 100)
124  else:
125  self.current_positioncurrent_positioncurrent_position = 50 - ((api_position * 50) / 100)
126 
127 
129  """Representation of a Soma Shade device."""
130 
131  _attr_name = None
132  _attr_device_class = CoverDeviceClass.SHADE
133  _attr_supported_features = (
134  CoverEntityFeature.OPEN
135  | CoverEntityFeature.CLOSE
136  | CoverEntityFeature.STOP
137  | CoverEntityFeature.SET_POSITION
138  )
139 
140  @property
141  def current_cover_position(self) -> int:
142  """Return the current cover position."""
143  return self.current_positioncurrent_positioncurrent_position
144 
145  @property
146  def is_closed(self) -> bool:
147  """Return if the cover is closed."""
148  return self.current_positioncurrent_positioncurrent_position == 0
149 
150  def close_cover(self, **kwargs: Any) -> None:
151  """Close the cover."""
152  response = self.apiapi.set_shade_position(self.devicedevice["mac"], 100)
153  if not is_api_response_success(response):
154  raise HomeAssistantError(
155  f'Error while closing the cover ({self.name}): {response["msg"]}'
156  )
157 
158  def open_cover(self, **kwargs: Any) -> None:
159  """Open the cover."""
160  response = self.apiapi.set_shade_position(self.devicedevice["mac"], 0)
161  if not is_api_response_success(response):
162  raise HomeAssistantError(
163  f'Error while opening the cover ({self.name}): {response["msg"]}'
164  )
165 
166  def stop_cover(self, **kwargs: Any) -> None:
167  """Stop the cover."""
168  response = self.apiapi.stop_shade(self.devicedevice["mac"])
169  if not is_api_response_success(response):
170  raise HomeAssistantError(
171  f'Error while stopping the cover ({self.name}): {response["msg"]}'
172  )
173  # Set cover position to some value where up/down are both enabled
174  self.set_positionset_position(50)
175 
176  def set_cover_position(self, **kwargs: Any) -> None:
177  """Move the cover shutter to a specific position."""
178  self.current_positioncurrent_positioncurrent_position = kwargs[ATTR_POSITION]
179  response = self.apiapi.set_shade_position(
180  self.devicedevice["mac"], 100 - kwargs[ATTR_POSITION]
181  )
182  if not is_api_response_success(response):
183  raise HomeAssistantError(
184  f"Error while setting the cover position ({self.name}):"
185  f' {response["msg"]}'
186  )
187 
188  async def async_update(self) -> None:
189  """Update the cover with the latest data."""
190  response = await self.get_shade_state_from_apiget_shade_state_from_api()
191 
192  self.current_positioncurrent_positioncurrent_position = 100 - int(response["position"])
None open_cover(self, **Any kwargs)
Definition: cover.py:158
None close_cover(self, **Any kwargs)
Definition: cover.py:150
None set_cover_position(self, **Any kwargs)
Definition: cover.py:176
None stop_cover(self, **Any kwargs)
Definition: cover.py:166
None stop_cover_tilt(self, **Any kwargs)
Definition: cover.py:92
None close_cover_tilt(self, **Any kwargs)
Definition: cover.py:74
None set_cover_tilt_position(self, **Any kwargs)
Definition: cover.py:102
None open_cover_tilt(self, **Any kwargs)
Definition: cover.py:83
None set_position(self, int position)
Definition: entity.py:95
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:28
bool is_api_response_success(dict api_response)
Definition: utils.py:4