diff --git a/custom_components/bosch_shc/cover.py b/custom_components/bosch_shc/cover.py index efffe58..a7f2025 100644 --- a/custom_components/bosch_shc/cover.py +++ b/custom_components/bosch_shc/cover.py @@ -68,6 +68,36 @@ class ShutterControlCover(SHCEntity, CoverEntity): | CoverEntityFeature.STOP | CoverEntityFeature.SET_POSITION ) + _current_operation_state = None + _l1_position = _l2_position = None + + def _update_attr(self) -> None: + """Recomputes the attributes values either at init or when the device state changes.""" + self._attr_current_cover_position = round(self._device.level * 100.0) + self._current_operation_state = self._device.operation_state + + if self._l1_position is None: + self._l2_position = self._l1_position = self._attr_current_cover_position + + # calculate movement direction between current cover position and second last reported position + if ( + self._current_operation_state + == SHCShutterControl.ShutterControlService.State.MOVING + ): + if self._l2_position > self._attr_current_cover_position: + self._attr_is_closing = True + else: + self._attr_is_opening = True + + if ( + self._current_operation_state + == SHCShutterControl.ShutterControlService.State.STOPPED + ): + self._attr_is_closing = False + self._attr_is_opening = False + + self._l2_position = self._l1_position + self._l1_position = self._attr_current_cover_position @property def device_class(self) -> CoverDeviceClass | None: @@ -84,20 +114,28 @@ def current_cover_position(self): def stop_cover(self, **kwargs): """Stop the cover.""" + self._attr_is_opening = False + self._attr_is_closing = False self._device.stop() @property def is_closed(self): """Return if the cover is closed or not.""" - return self.current_cover_position == 0 + return self._l2_position == 0 def open_cover(self, **kwargs): """Open the cover.""" - self._device.level = 1.0 + # opens effectively only if cover is not already opening and not fully opened + if not self._attr_is_opening and self.current_cover_position != 100: + self._attr_is_opening = True + self._device.level = 1.0 def close_cover(self, **kwargs): """Close cover.""" - self._device.level = 0.0 + # closes effectively only if cover is not already closing and not fully closed + if not self._attr_is_closing and self.current_cover_position != 0: + self._attr_is_closing = True + self._device.level = 0.0 def set_cover_position(self, **kwargs): """Move the cover to a specific position.""" diff --git a/custom_components/bosch_shc/entity.py b/custom_components/bosch_shc/entity.py index 6f3d95d..99466e8 100644 --- a/custom_components/bosch_shc/entity.py +++ b/custom_components/bosch_shc/entity.py @@ -79,18 +79,24 @@ def __init__(self, device: SHCDevice, entry_id: str) -> None: self._entry_id = entry_id self._attr_name = f"{device.name}" self._attr_unique_id = f"{device.root_device_id}_{device.id}" + self._update_attr() + + def _update_attr(self) -> None: + pass async def async_added_to_hass(self): """Subscribe to SHC events.""" await super().async_added_to_hass() def on_state_changed(): + self._update_attr() self.schedule_update_ha_state() def update_entity_information(): if self._device.deleted: self.hass.add_job(async_remove_devices(self.hass, self, self._entry_id)) else: + self._update_attr() self.schedule_update_ha_state() for service in self._device.device_services: diff --git a/custom_components/bosch_shc/manifest.json b/custom_components/bosch_shc/manifest.json index d7beaea..8cf359c 100644 --- a/custom_components/bosch_shc/manifest.json +++ b/custom_components/bosch_shc/manifest.json @@ -8,6 +8,6 @@ "iot_class": "local_push", "issue_tracker": "https://github.com/tschamm/boschshc-hass/issues", "requirements": ["boschshcpy==0.2.105"], - "version": "0.4.96", + "version": "0.4.97-dev0", "zeroconf": [{ "type": "_http._tcp.local.", "name": "bosch shc*" }] }