Home Assistant Unofficial Reference 2024.12.1
cover.py
Go to the documentation of this file.
1 """Support for covers through the SmartThings cloud API."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Sequence
6 from typing import Any
7 
8 from pysmartthings import Attribute, Capability
9 
11  ATTR_POSITION,
12  DOMAIN as COVER_DOMAIN,
13  CoverDeviceClass,
14  CoverEntity,
15  CoverEntityFeature,
16  CoverState,
17 )
18 from homeassistant.config_entries import ConfigEntry
19 from homeassistant.const import ATTR_BATTERY_LEVEL
20 from homeassistant.core import HomeAssistant
21 from homeassistant.helpers.entity_platform import AddEntitiesCallback
22 
23 from .const import DATA_BROKERS, DOMAIN
24 from .entity import SmartThingsEntity
25 
26 VALUE_TO_STATE = {
27  "closed": CoverState.CLOSED,
28  "closing": CoverState.CLOSING,
29  "open": CoverState.OPEN,
30  "opening": CoverState.OPENING,
31  "partially open": CoverState.OPEN,
32  "unknown": None,
33 }
34 
35 
37  hass: HomeAssistant,
38  config_entry: ConfigEntry,
39  async_add_entities: AddEntitiesCallback,
40 ) -> None:
41  """Add covers for a config entry."""
42  broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
44  [
45  SmartThingsCover(device)
46  for device in broker.devices.values()
47  if broker.any_assigned(device.device_id, COVER_DOMAIN)
48  ],
49  True,
50  )
51 
52 
53 def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
54  """Return all capabilities supported if minimum required are present."""
55  min_required = [
56  Capability.door_control,
57  Capability.garage_door_control,
58  Capability.window_shade,
59  ]
60  # Must have one of the min_required
61  if any(capability in capabilities for capability in min_required):
62  # Return all capabilities supported/consumed
63  return [
64  *min_required,
65  Capability.battery,
66  Capability.switch_level,
67  Capability.window_shade_level,
68  ]
69 
70  return None
71 
72 
74  """Define a SmartThings cover."""
75 
76  def __init__(self, device):
77  """Initialize the cover class."""
78  super().__init__(device)
79  self._current_cover_position_current_cover_position = None
80  self._state_state = None
81  self._attr_supported_features_attr_supported_features = (
82  CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
83  )
84  if (
85  Capability.switch_level in device.capabilities
86  or Capability.window_shade_level in device.capabilities
87  ):
88  self._attr_supported_features_attr_supported_features |= CoverEntityFeature.SET_POSITION
89 
90  if Capability.door_control in device.capabilities:
91  self._attr_device_class_attr_device_class = CoverDeviceClass.DOOR
92  elif Capability.window_shade in device.capabilities:
93  self._attr_device_class_attr_device_class = CoverDeviceClass.SHADE
94  elif Capability.garage_door_control in device.capabilities:
95  self._attr_device_class_attr_device_class = CoverDeviceClass.GARAGE
96 
97  async def async_close_cover(self, **kwargs: Any) -> None:
98  """Close cover."""
99  # Same command for all 3 supported capabilities
100  await self._device_device.close(set_status=True)
101  # State is set optimistically in the commands above, therefore update
102  # the entity state ahead of receiving the confirming push updates
103  self.async_schedule_update_ha_stateasync_schedule_update_ha_state(True)
104 
105  async def async_open_cover(self, **kwargs: Any) -> None:
106  """Open the cover."""
107  # Same for all capability types
108  await self._device_device.open(set_status=True)
109  # State is set optimistically in the commands above, therefore update
110  # the entity state ahead of receiving the confirming push updates
111  self.async_schedule_update_ha_stateasync_schedule_update_ha_state(True)
112 
113  async def async_set_cover_position(self, **kwargs: Any) -> None:
114  """Move the cover to a specific position."""
115  if not self.supported_featuressupported_featuressupported_features & CoverEntityFeature.SET_POSITION:
116  return
117  # Do not set_status=True as device will report progress.
118  if Capability.window_shade_level in self._device_device.capabilities:
119  await self._device_device.set_window_shade_level(
120  kwargs[ATTR_POSITION], set_status=False
121  )
122  else:
123  await self._device_device.set_level(kwargs[ATTR_POSITION], set_status=False)
124 
125  async def async_update(self) -> None:
126  """Update the attrs of the cover."""
127  if Capability.door_control in self._device_device.capabilities:
128  self._state_state = VALUE_TO_STATE.get(self._device_device.status.door)
129  elif Capability.window_shade in self._device_device.capabilities:
130  self._state_state = VALUE_TO_STATE.get(self._device_device.status.window_shade)
131  elif Capability.garage_door_control in self._device_device.capabilities:
132  self._state_state = VALUE_TO_STATE.get(self._device_device.status.door)
133 
134  if Capability.window_shade_level in self._device_device.capabilities:
135  self._attr_current_cover_position_attr_current_cover_position = self._device_device.status.shade_level
136  elif Capability.switch_level in self._device_device.capabilities:
137  self._attr_current_cover_position_attr_current_cover_position = self._device_device.status.level
138 
139  self._attr_extra_state_attributes_attr_extra_state_attributes = {}
140  battery = self._device_device.status.attributes[Attribute.battery].value
141  if battery is not None:
142  self._attr_extra_state_attributes_attr_extra_state_attributes[ATTR_BATTERY_LEVEL] = battery
143 
144  @property
145  def is_opening(self) -> bool:
146  """Return if the cover is opening or not."""
147  return self._state_state == CoverState.OPENING
148 
149  @property
150  def is_closing(self) -> bool:
151  """Return if the cover is closing or not."""
152  return self._state_state == CoverState.CLOSING
153 
154  @property
155  def is_closed(self) -> bool | None:
156  """Return if the cover is closed or not."""
157  if self._state_state == CoverState.CLOSED:
158  return True
159  return None if self._state_state is None else False
CoverEntityFeature supported_features(self)
Definition: __init__.py:349
None async_schedule_update_ha_state(self, bool force_refresh=False)
Definition: entity.py:1265
int|None supported_features(self)
Definition: entity.py:861
None open(self, **Any kwargs)
Definition: lock.py:86
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: cover.py:40
Sequence[str]|None get_capabilities(Sequence[str] capabilities)
Definition: cover.py:53