1 """Support for Homekit covers."""
3 from __future__
import annotations
7 from aiohomekit.model.characteristics
import CharacteristicsTypes
8 from aiohomekit.model.services
import Service, ServicesTypes
9 from propcache
import cached_property
24 from .
import KNOWN_DEVICES
25 from .connection
import HKDevice
26 from .entity
import HomeKitEntity
28 STATE_STOPPED =
"stopped"
30 CURRENT_GARAGE_STATE_MAP = {
33 2: CoverState.OPENING,
34 3: CoverState.CLOSING,
38 TARGET_GARAGE_STATE_MAP = {
44 CURRENT_WINDOW_STATE_MAP = {
45 0: CoverState.CLOSING,
46 1: CoverState.OPENING,
53 config_entry: ConfigEntry,
54 async_add_entities: AddEntitiesCallback,
56 """Set up Homekit covers."""
57 hkid: str = config_entry.data[
"AccessoryPairingID"]
58 conn: HKDevice = hass.data[KNOWN_DEVICES][hkid]
61 def async_add_service(service: Service) -> bool:
62 if not (entity_class := ENTITY_TYPES.get(service.type)):
64 info = {
"aid": service.accessory.aid,
"iid": service.iid}
65 entity: HomeKitEntity = entity_class(conn, info)
66 conn.async_migrate_unique_id(
67 entity.old_unique_id, entity.unique_id, Platform.COVER
72 conn.add_listener(async_add_service)
76 """Representation of a HomeKit Garage Door."""
78 _attr_device_class = CoverDeviceClass.GARAGE
79 _attr_supported_features = CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
82 """Define the homekit characteristics the entity cares about."""
84 CharacteristicsTypes.DOOR_STATE_CURRENT,
85 CharacteristicsTypes.DOOR_STATE_TARGET,
86 CharacteristicsTypes.OBSTRUCTION_DETECTED,
91 """Return the current state of the garage door."""
92 value = self.
serviceservice.value(CharacteristicsTypes.DOOR_STATE_CURRENT)
93 return CURRENT_GARAGE_STATE_MAP[value]
97 """Return true if cover is closed, else False."""
102 """Return if the cover is closing or not."""
107 """Return if the cover is opening or not."""
111 """Send open command."""
115 """Send close command."""
119 """Send state command."""
121 {CharacteristicsTypes.DOOR_STATE_TARGET: TARGET_GARAGE_STATE_MAP[state]}
126 """Return the optional state attributes."""
127 obstruction_detected = self.
serviceservice.value(
128 CharacteristicsTypes.OBSTRUCTION_DETECTED
130 return {
"obstruction-detected": obstruction_detected
is True}
134 """Representation of a HomeKit Window or Window Covering."""
138 """Reconfigure entity."""
143 """Define the homekit characteristics the entity cares about."""
145 CharacteristicsTypes.POSITION_STATE,
146 CharacteristicsTypes.POSITION_CURRENT,
147 CharacteristicsTypes.POSITION_TARGET,
148 CharacteristicsTypes.POSITION_HOLD,
149 CharacteristicsTypes.VERTICAL_TILT_CURRENT,
150 CharacteristicsTypes.VERTICAL_TILT_TARGET,
151 CharacteristicsTypes.HORIZONTAL_TILT_CURRENT,
152 CharacteristicsTypes.HORIZONTAL_TILT_TARGET,
153 CharacteristicsTypes.OBSTRUCTION_DETECTED,
158 """Flag supported features."""
160 CoverEntityFeature.OPEN
161 | CoverEntityFeature.CLOSE
162 | CoverEntityFeature.SET_POSITION
165 if self.
serviceservice.has(CharacteristicsTypes.POSITION_HOLD):
166 features |= CoverEntityFeature.STOP
169 CharacteristicsTypes.VERTICAL_TILT_CURRENT
170 )
or self.
serviceservice.has(CharacteristicsTypes.HORIZONTAL_TILT_CURRENT):
172 CoverEntityFeature.OPEN_TILT
173 | CoverEntityFeature.CLOSE_TILT
174 | CoverEntityFeature.SET_TILT_POSITION
181 """Return the current position of cover."""
182 return self.
serviceservice.value(CharacteristicsTypes.POSITION_CURRENT)
186 """Return true if cover is closed, else False."""
191 """Return if the cover is closing or not."""
192 value = self.
serviceservice.value(CharacteristicsTypes.POSITION_STATE)
193 state = CURRENT_WINDOW_STATE_MAP[value]
194 return state == CoverState.CLOSING
198 """Return if the cover is opening or not."""
199 value = self.
serviceservice.value(CharacteristicsTypes.POSITION_STATE)
200 state = CURRENT_WINDOW_STATE_MAP[value]
201 return state == CoverState.OPENING
205 """Return True if the service has a horizontal tilt characteristic."""
207 self.
serviceservice.value(CharacteristicsTypes.HORIZONTAL_TILT_CURRENT)
is not None
212 """Return True if the service has a vertical tilt characteristic."""
214 self.
serviceservice.value(CharacteristicsTypes.VERTICAL_TILT_CURRENT)
is not None
219 """Return current position of cover tilt."""
221 char = self.
serviceservice[CharacteristicsTypes.VERTICAL_TILT_CURRENT]
223 char = self.
serviceservice[CharacteristicsTypes.HORIZONTAL_TILT_CURRENT]
228 tilt_position = char.value
229 min_value = char.minValue
230 max_value = char.maxValue
231 total_range =
int(max_value
or 0) -
int(min_value
or 0)
234 tilt_position
is None
242 if min_value == -90
and max_value == 0:
243 return abs(
int(100 / total_range * (tilt_position - max_value)))
245 return abs(
int(100 / total_range * (tilt_position - min_value)))
248 """Send hold command."""
252 """Send open command."""
256 """Send close command."""
260 """Send position command."""
261 position = kwargs[ATTR_POSITION]
263 {CharacteristicsTypes.POSITION_TARGET: position}
267 """Move the cover tilt to a specific position."""
268 tilt_position = kwargs[ATTR_TILT_POSITION]
271 char = self.
serviceservice[CharacteristicsTypes.VERTICAL_TILT_TARGET]
273 char = self.
serviceservice[CharacteristicsTypes.HORIZONTAL_TILT_TARGET]
276 min_value = char.minValue
277 max_value = char.maxValue
278 if min_value
is None or max_value
is None:
280 "Entity does not provide minValue and maxValue for the tilt"
284 if min_value == -90
and max_value == 0:
286 tilt_position / 100 * (min_value - max_value) + max_value
290 tilt_position / 100 * (max_value - min_value) + min_value
297 """Return the optional state attributes."""
298 obstruction_detected = self.
serviceservice.value(
299 CharacteristicsTypes.OBSTRUCTION_DETECTED
301 if not obstruction_detected:
303 return {
"obstruction-detected": obstruction_detected}
307 """Representation of a HomeKit Window."""
309 _attr_device_class = CoverDeviceClass.WINDOW
313 ServicesTypes.GARAGE_DOOR_OPENER: HomeKitGarageDoorCover,
314 ServicesTypes.WINDOW_COVERING: HomeKitWindowCover,
315 ServicesTypes.WINDOW: HomeKitWindow,
current_cover_tilt_position
None async_set_cover_position(self, **Any kwargs)
int|None current_cover_position(self)
dict[str, Any] extra_state_attributes(self)
list[str] get_characteristic_types(self)
None async_open_cover(self, **Any kwargs)
None async_close_cover(self, **Any kwargs)
None set_door_state(self, str state)
None async_close_cover(self, **Any kwargs)
None async_set_cover_tilt_position(self, **Any kwargs)
list[str] get_characteristic_types(self)
bool is_vertical_tilt(self)
None async_set_cover_position(self, **Any kwargs)
None async_open_cover(self, **Any kwargs)
CoverEntityFeature supported_features(self)
None async_stop_cover(self, **Any kwargs)
None _async_reconfigure(self)
bool is_horizontal_tilt(self)
int current_cover_position(self)
dict[str, Any] extra_state_attributes(self)
None async_put_characteristics(self, dict[str, Any] characteristics)
None _async_clear_property_cache(self, tuple[str,...] properties)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)