diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 5879609644cb..6db9b081bf18 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -29,7 +29,7 @@ from homeassistant.const import ( STATE_OPEN, STATE_OPENING, ) -from homeassistant.core import callback +from homeassistant.core import State, callback from homeassistant.helpers.event import async_track_state_change_event from .accessories import TYPES, HomeAccessory @@ -79,6 +79,8 @@ DOOR_TARGET_HASS_TO_HK = { STATE_CLOSING: HK_DOOR_CLOSED, } +MOVING_STATES = {STATE_OPENING, STATE_CLOSING} + _LOGGER = logging.getLogger(__name__) @@ -301,13 +303,16 @@ class OpeningDevice(OpeningDeviceBase, HomeAccessory): self.async_call_service(DOMAIN, SERVICE_SET_COVER_POSITION, params, value) @callback - def async_update_state(self, new_state): + def async_update_state(self, new_state: State) -> None: """Update cover position and tilt after state changed.""" current_position = new_state.attributes.get(ATTR_CURRENT_POSITION) if isinstance(current_position, (float, int)): current_position = int(current_position) self.char_current_position.set_value(current_position) - self.char_target_position.set_value(current_position) + # Writing target_position on a moving cover + # will break the moving state in HK. + if new_state.state not in MOVING_STATES: + self.char_target_position.set_value(current_position) position_state = _hass_state_to_position_start(new_state.state) self.char_position_state.set_value(position_state) @@ -390,14 +395,16 @@ class WindowCoveringBasic(OpeningDeviceBase, HomeAccessory): self.char_target_position.set_value(position) @callback - def async_update_state(self, new_state): + def async_update_state(self, new_state: State) -> None: """Update cover position after state changed.""" position_mapping = {STATE_OPEN: 100, STATE_CLOSED: 0} hk_position = position_mapping.get(new_state.state) if hk_position is not None: + is_moving = new_state.state in MOVING_STATES + if self.char_current_position.value != hk_position: self.char_current_position.set_value(hk_position) - if self.char_target_position.value != hk_position: + if self.char_target_position.value != hk_position and not is_moving: self.char_target_position.set_value(hk_position) position_state = _hass_state_to_position_start(new_state.state) if self.char_position_state.value != position_state: diff --git a/tests/components/homekit/test_type_covers.py b/tests/components/homekit/test_type_covers.py index 44c9365fc046..8f26967c160a 100644 --- a/tests/components/homekit/test_type_covers.py +++ b/tests/components/homekit/test_type_covers.py @@ -166,7 +166,7 @@ async def test_windowcovering_set_cover_position(hass, hk_driver, events): ) await hass.async_block_till_done() assert acc.char_current_position.value == 60 - assert acc.char_target_position.value == 60 + assert acc.char_target_position.value == 0 assert acc.char_position_state.value == 1 hass.states.async_set( @@ -176,7 +176,7 @@ async def test_windowcovering_set_cover_position(hass, hk_driver, events): ) await hass.async_block_till_done() assert acc.char_current_position.value == 70 - assert acc.char_target_position.value == 70 + assert acc.char_target_position.value == 0 assert acc.char_position_state.value == 1 hass.states.async_set( @@ -186,7 +186,7 @@ async def test_windowcovering_set_cover_position(hass, hk_driver, events): ) await hass.async_block_till_done() assert acc.char_current_position.value == 50 - assert acc.char_target_position.value == 50 + assert acc.char_target_position.value == 0 assert acc.char_position_state.value == 0 hass.states.async_set(