Home Assistant Unofficial Reference 2024.12.1
cover.py
Go to the documentation of this file.
1 """Cover Platform for the Somfy MyLink component."""
2 
3 import logging
4 from typing import Any
5 
6 from homeassistant.components.cover import CoverDeviceClass, CoverEntity, CoverState
7 from homeassistant.config_entries import ConfigEntry
8 from homeassistant.core import HomeAssistant
9 from homeassistant.helpers.device_registry import DeviceInfo
10 from homeassistant.helpers.entity_platform import AddEntitiesCallback
11 from homeassistant.helpers.restore_state import RestoreEntity
12 
13 from .const import (
14  CONF_REVERSED_TARGET_IDS,
15  DATA_SOMFY_MYLINK,
16  DOMAIN,
17  MANUFACTURER,
18  MYLINK_STATUS,
19 )
20 
21 _LOGGER = logging.getLogger(__name__)
22 
23 MYLINK_COVER_TYPE_TO_DEVICE_CLASS = {
24  0: CoverDeviceClass.BLIND,
25  1: CoverDeviceClass.SHUTTER,
26 }
27 
28 
30  hass: HomeAssistant,
31  config_entry: ConfigEntry,
32  async_add_entities: AddEntitiesCallback,
33 ) -> None:
34  """Discover and configure Somfy covers."""
35  reversed_target_ids = config_entry.options.get(CONF_REVERSED_TARGET_IDS, {})
36 
37  data = hass.data[DOMAIN][config_entry.entry_id]
38  mylink_status = data[MYLINK_STATUS]
39  somfy_mylink = data[DATA_SOMFY_MYLINK]
40  cover_list = []
41 
42  for cover in mylink_status["result"]:
43  cover_config = {
44  "target_id": cover["targetID"],
45  "name": cover["name"],
46  "device_class": MYLINK_COVER_TYPE_TO_DEVICE_CLASS.get(
47  cover.get("type"), CoverDeviceClass.WINDOW
48  ),
49  "reverse": reversed_target_ids.get(cover["targetID"], False),
50  }
51 
52  cover_list.append(SomfyShade(somfy_mylink, **cover_config))
53 
54  _LOGGER.debug(
55  "Adding Somfy Cover: %s with targetID %s",
56  cover_config["name"],
57  cover_config["target_id"],
58  )
59 
60  async_add_entities(cover_list)
61 
62 
64  """Object for controlling a Somfy cover."""
65 
66  _attr_should_poll = False
67  _attr_assumed_state = True
68  _attr_has_entity_name = True
69  _attr_name = None
70 
71  def __init__(
72  self,
73  somfy_mylink,
74  target_id,
75  name="SomfyShade",
76  reverse=False,
77  device_class=CoverDeviceClass.WINDOW,
78  ):
79  """Initialize the cover."""
80  self.somfy_mylinksomfy_mylink = somfy_mylink
81  self._target_id_target_id = target_id
82  self._attr_unique_id_attr_unique_id = target_id
83  self._reverse_reverse = reverse
84  self._attr_is_closed_attr_is_closed = None
85  self._attr_device_class_attr_device_class = device_class
86  self._attr_device_info_attr_device_info = DeviceInfo(
87  identifiers={(DOMAIN, self._target_id_target_id)},
88  manufacturer=MANUFACTURER,
89  name=name,
90  )
91 
92  async def async_close_cover(self, **kwargs: Any) -> None:
93  """Close the cover."""
94  self._attr_is_closing_attr_is_closing = True
95  self.async_write_ha_stateasync_write_ha_state()
96  try:
97  # Blocks until the close command is sent
98  if not self._reverse_reverse:
99  await self.somfy_mylinksomfy_mylink.move_down(self._target_id_target_id)
100  else:
101  await self.somfy_mylinksomfy_mylink.move_up(self._target_id_target_id)
102  self._attr_is_closed_attr_is_closed = True
103  finally:
104  self._attr_is_closing_attr_is_closing = None
105  self.async_write_ha_stateasync_write_ha_state()
106 
107  async def async_open_cover(self, **kwargs: Any) -> None:
108  """Open the cover."""
109  self._attr_is_opening_attr_is_opening = True
110  self.async_write_ha_stateasync_write_ha_state()
111  try:
112  # Blocks until the open command is sent
113  if not self._reverse_reverse:
114  await self.somfy_mylinksomfy_mylink.move_up(self._target_id_target_id)
115  else:
116  await self.somfy_mylinksomfy_mylink.move_down(self._target_id_target_id)
117  self._attr_is_closed_attr_is_closed = False
118  finally:
119  self._attr_is_opening_attr_is_opening = None
120  self.async_write_ha_stateasync_write_ha_state()
121 
122  async def async_stop_cover(self, **kwargs: Any) -> None:
123  """Stop the cover."""
124  await self.somfy_mylinksomfy_mylink.move_stop(self._target_id_target_id)
125 
126  async def async_added_to_hass(self) -> None:
127  """Complete the initialization."""
128  await super().async_added_to_hass()
129  # Restore the last state
130  last_state = await self.async_get_last_stateasync_get_last_state()
131 
132  if last_state is not None and last_state.state in (
133  CoverState.OPEN,
134  CoverState.CLOSED,
135  ):
136  self._attr_is_closed_attr_is_closed = last_state.state == CoverState.CLOSED