From 2bb71cf6bc17ec552406da5fb6a0fcf63976ca89 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 3 Apr 2022 17:21:53 +0200 Subject: [PATCH] Motion Blinds opening closing (#68837) --- .../components/motion_blinds/cover.py | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/motion_blinds/cover.py b/homeassistant/components/motion_blinds/cover.py index 80f5b4d60c4..e7fd2070642 100644 --- a/homeassistant/components/motion_blinds/cover.py +++ b/homeassistant/components/motion_blinds/cover.py @@ -1,4 +1,5 @@ """Support for Motion Blinds using their WLAN API.""" +from enum import IntEnum import logging from motionblinds import DEVICE_TYPES_WIFI, BlindType @@ -38,6 +39,14 @@ from .const import ( _LOGGER = logging.getLogger(__name__) +class State(IntEnum): + """Moving status of the blind.""" + + Closing = -1 + Not_Moving = 0 + Opening = 1 + + POSITION_DEVICE_MAP = { BlindType.RollerBlind: CoverDeviceClass.SHADE, BlindType.RomanBlind: CoverDeviceClass.SHADE, @@ -168,6 +177,7 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): self._blind = blind self._api_lock = coordinator.api_lock + self._moving = State.Not_Moving self._requesting_position = False self._previous_positions = [] @@ -224,6 +234,27 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): return None return self._blind.position == 100 + @property + def is_opening(self): + """Return if the cover is opening or not.""" + if self.is_closed is None: + return None + return self._moving == State.Opening + + @property + def is_closing(self): + """Return if the cover is closing or not.""" + if self.is_closed is None: + return None + return self._moving == State.Closing + + def _set_moving_state(self, new_position, old_position): + """Set the moving status for a position move.""" + if new_position > old_position: + self._moving = State.Closing + else: + self._moving = State.Opening + async def async_added_to_hass(self): """Subscribe to multicast pushes and register signal handler.""" self._blind.Register_callback(self.unique_id, self.schedule_update_ha_state) @@ -244,8 +275,6 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Update_trigger) - self.async_write_ha_state() - if len(self._previous_positions) < 2 or not all( self.current_cover_position == prev_position for prev_position in self._previous_positions @@ -255,9 +284,12 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): self.hass, UPDATE_INTERVAL_MOVING, self.async_scheduled_update_request ) else: + self._moving = State.Not_Moving self._previous_positions = [] self._requesting_position = False + self.async_write_ha_state() + async def async_request_position_till_stop(self): """Request the position of the blind every UPDATE_INTERVAL_MOVING seconds until it stops moving.""" self._previous_positions = [] @@ -265,6 +297,7 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): return self._requesting_position = True + self.async_write_ha_state() async_call_later( self.hass, UPDATE_INTERVAL_MOVING, self.async_scheduled_update_request ) @@ -273,12 +306,14 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): """Open the cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Open) + self._moving = State.Opening await self.async_request_position_till_stop() async def async_close_cover(self, **kwargs): """Close cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Close) + self._moving = State.Closing await self.async_request_position_till_stop() async def async_set_cover_position(self, **kwargs): @@ -288,21 +323,19 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity): await self.hass.async_add_executor_job( self._blind.Set_position, 100 - position ) + self._set_moving_state(position, self._blind.position) await self.async_request_position_till_stop() async def async_set_absolute_position(self, **kwargs): """Move the cover to a specific absolute position (see TDBU).""" - position = kwargs[ATTR_ABSOLUTE_POSITION] - async with self._api_lock: - await self.hass.async_add_executor_job( - self._blind.Set_position, 100 - position - ) - await self.async_request_position_till_stop() + await self.async_set_cover_position(**kwargs) async def async_stop_cover(self, **kwargs): """Stop the cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Stop) + self._moving = State.Not_Moving + self.async_write_ha_state() class MotionTiltDevice(MotionPositionDevice): @@ -339,6 +372,8 @@ class MotionTiltDevice(MotionPositionDevice): """Stop the cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Stop) + self._moving = State.Not_Moving + self.async_write_ha_state() class MotionTDBUDevice(MotionPositionDevice): @@ -394,12 +429,14 @@ class MotionTDBUDevice(MotionPositionDevice): """Open the cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Open, self._motor_key) + self._moving = State.Opening await self.async_request_position_till_stop() async def async_close_cover(self, **kwargs): """Close cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Close, self._motor_key) + self._moving = State.Closing await self.async_request_position_till_stop() async def async_set_cover_position(self, **kwargs): @@ -409,6 +446,7 @@ class MotionTDBUDevice(MotionPositionDevice): await self.hass.async_add_executor_job( self._blind.Set_scaled_position, 100 - position, self._motor_key ) + self._set_moving_state(position, self._blind.scaled_position[self._motor_key]) await self.async_request_position_till_stop() async def async_set_absolute_position(self, **kwargs): @@ -420,10 +458,12 @@ class MotionTDBUDevice(MotionPositionDevice): await self.hass.async_add_executor_job( self._blind.Set_position, 100 - position, self._motor_key, target_width ) - + self._set_moving_state(position, self._blind.position[self._motor_key]) await self.async_request_position_till_stop() async def async_stop_cover(self, **kwargs): """Stop the cover.""" async with self._api_lock: await self.hass.async_add_executor_job(self._blind.Stop, self._motor_key) + self._moving = State.Not_Moving + self.async_write_ha_state()