Clarify cover toggle logic; prevent opening when already open (#107920)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
3299bc5ddc
commit
8ba1340c2e
2 changed files with 27 additions and 3 deletions
|
@ -480,15 +480,30 @@ class CoverEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||||
def _get_toggle_function(
|
def _get_toggle_function(
|
||||||
self, fns: dict[str, Callable[_P, _R]]
|
self, fns: dict[str, Callable[_P, _R]]
|
||||||
) -> Callable[_P, _R]:
|
) -> Callable[_P, _R]:
|
||||||
|
# If we are opening or closing and we support stopping, then we should stop
|
||||||
if self.supported_features & CoverEntityFeature.STOP and (
|
if self.supported_features & CoverEntityFeature.STOP and (
|
||||||
self.is_closing or self.is_opening
|
self.is_closing or self.is_opening
|
||||||
):
|
):
|
||||||
return fns["stop"]
|
return fns["stop"]
|
||||||
if self.is_closed:
|
|
||||||
|
# If we are fully closed or in the process of closing, then we should open
|
||||||
|
if self.is_closed or self.is_closing:
|
||||||
return fns["open"]
|
return fns["open"]
|
||||||
if self._cover_is_last_toggle_direction_open:
|
|
||||||
|
# If we are fully open or in the process of opening, then we should close
|
||||||
|
if self.current_cover_position == 100 or self.is_opening:
|
||||||
return fns["close"]
|
return fns["close"]
|
||||||
return fns["open"]
|
|
||||||
|
# We are any of:
|
||||||
|
# * fully open but do not report `current_cover_position`
|
||||||
|
# * stopped partially open
|
||||||
|
# * either opening or closing, but do not report them
|
||||||
|
# If we previously reported opening/closing, we should move in the opposite direction.
|
||||||
|
# Otherwise, we must assume we are (partially) open and should always close.
|
||||||
|
# Note: _cover_is_last_toggle_direction_open will always remain True if we never report opening/closing.
|
||||||
|
return (
|
||||||
|
fns["close"] if self._cover_is_last_toggle_direction_open else fns["open"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# These can be removed if no deprecated constant are in this module anymore
|
# These can be removed if no deprecated constant are in this module anymore
|
||||||
|
|
|
@ -108,6 +108,15 @@ async def test_services(
|
||||||
await call_service(hass, SERVICE_TOGGLE, ent6)
|
await call_service(hass, SERVICE_TOGGLE, ent6)
|
||||||
assert is_opening(hass, ent6)
|
assert is_opening(hass, ent6)
|
||||||
|
|
||||||
|
# After the unusual state transition: closing -> fully open, toggle should close
|
||||||
|
set_state(ent5, STATE_OPEN)
|
||||||
|
await call_service(hass, SERVICE_TOGGLE, ent5) # Start closing
|
||||||
|
assert is_closing(hass, ent5)
|
||||||
|
set_state(ent5, STATE_OPEN) # Unusual state transition from closing -> fully open
|
||||||
|
set_cover_position(ent5, 100)
|
||||||
|
await call_service(hass, SERVICE_TOGGLE, ent5) # Should close, not open
|
||||||
|
assert is_closing(hass, ent5)
|
||||||
|
|
||||||
|
|
||||||
def call_service(hass, service, ent):
|
def call_service(hass, service, ent):
|
||||||
"""Call any service on entity."""
|
"""Call any service on entity."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue