mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Improve state of cover groups (#57313)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
7f966613bd
commit
7e34860615
@ -259,25 +259,31 @@ class CoverGroup(GroupEntity, CoverEntity):
|
|||||||
"""Update state and attributes."""
|
"""Update state and attributes."""
|
||||||
self._attr_assumed_state = False
|
self._attr_assumed_state = False
|
||||||
|
|
||||||
self._attr_is_closed = None
|
self._attr_is_closed = True
|
||||||
self._attr_is_closing = False
|
self._attr_is_closing = False
|
||||||
self._attr_is_opening = False
|
self._attr_is_opening = False
|
||||||
|
has_valid_state = False
|
||||||
for entity_id in self._entities:
|
for entity_id in self._entities:
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
if not state:
|
if not state:
|
||||||
continue
|
continue
|
||||||
if state.state == STATE_OPEN:
|
if state.state == STATE_OPEN:
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
|
has_valid_state = True
|
||||||
continue
|
continue
|
||||||
if state.state == STATE_CLOSED:
|
if state.state == STATE_CLOSED:
|
||||||
self._attr_is_closed = True
|
has_valid_state = True
|
||||||
continue
|
continue
|
||||||
if state.state == STATE_CLOSING:
|
if state.state == STATE_CLOSING:
|
||||||
self._attr_is_closing = True
|
self._attr_is_closing = True
|
||||||
|
has_valid_state = True
|
||||||
continue
|
continue
|
||||||
if state.state == STATE_OPENING:
|
if state.state == STATE_OPENING:
|
||||||
self._attr_is_opening = True
|
self._attr_is_opening = True
|
||||||
|
has_valid_state = True
|
||||||
continue
|
continue
|
||||||
|
if not has_valid_state:
|
||||||
|
self._attr_is_closed = None
|
||||||
|
|
||||||
position_covers = self._covers[KEY_POSITION]
|
position_covers = self._covers[KEY_POSITION]
|
||||||
all_position_states = [self.hass.states.get(x) for x in position_covers]
|
all_position_states = [self.hass.states.get(x) for x in position_covers]
|
||||||
|
@ -96,6 +96,106 @@ async def setup_comp(hass, config_count):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
||||||
|
async def test_state(hass, setup_comp):
|
||||||
|
"""Test handling of state."""
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
# No entity has a valid state -> group state unknown
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
assert state.attributes[ATTR_FRIENDLY_NAME] == DEFAULT_NAME
|
||||||
|
assert state.attributes[ATTR_ENTITY_ID] == [
|
||||||
|
DEMO_COVER,
|
||||||
|
DEMO_COVER_POS,
|
||||||
|
DEMO_COVER_TILT,
|
||||||
|
DEMO_TILT,
|
||||||
|
]
|
||||||
|
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
assert ATTR_CURRENT_POSITION not in state.attributes
|
||||||
|
assert ATTR_CURRENT_TILT_POSITION not in state.attributes
|
||||||
|
|
||||||
|
# Set all entities as closed -> group state closed
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_CLOSED
|
||||||
|
|
||||||
|
# Set all entities as open -> group state open
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_OPEN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPEN
|
||||||
|
|
||||||
|
# Set first entity as open -> group state open
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPEN
|
||||||
|
|
||||||
|
# Set last entity as open -> group state open
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPEN
|
||||||
|
|
||||||
|
# Set conflicting valid states -> opening state has priority
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_OPENING, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSING, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPENING
|
||||||
|
|
||||||
|
# Set all entities to unknown state -> group state unknown
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_UNKNOWN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# Set one entity to unknown state -> open state has priority
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_OPEN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPEN
|
||||||
|
|
||||||
|
# Set one entity to unknown state -> opening state has priority
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_OPENING, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPENING
|
||||||
|
|
||||||
|
# Set one entity to unknown state -> closing state has priority
|
||||||
|
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, STATE_UNKNOWN, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSING, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_CLOSING
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
||||||
async def test_attributes(hass, setup_comp):
|
async def test_attributes(hass, setup_comp):
|
||||||
"""Test handling of state attributes."""
|
"""Test handling of state attributes."""
|
||||||
@ -196,7 +296,7 @@ async def test_attributes(hass, setup_comp):
|
|||||||
# ### Test assumed state ###
|
# ### Test assumed state ###
|
||||||
# ##########################
|
# ##########################
|
||||||
|
|
||||||
# For covers
|
# For covers - assumed state set true if position differ
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
DEMO_COVER, STATE_OPEN, {ATTR_SUPPORTED_FEATURES: 4, ATTR_CURRENT_POSITION: 100}
|
DEMO_COVER, STATE_OPEN, {ATTR_SUPPORTED_FEATURES: 4, ATTR_CURRENT_POSITION: 100}
|
||||||
)
|
)
|
||||||
@ -220,7 +320,7 @@ async def test_attributes(hass, setup_comp):
|
|||||||
assert ATTR_CURRENT_POSITION not in state.attributes
|
assert ATTR_CURRENT_POSITION not in state.attributes
|
||||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 60
|
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 60
|
||||||
|
|
||||||
# For tilts
|
# For tilts - assumed state set true if tilt position differ
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
DEMO_TILT,
|
DEMO_TILT,
|
||||||
STATE_OPEN,
|
STATE_OPEN,
|
||||||
@ -252,6 +352,7 @@ async def test_attributes(hass, setup_comp):
|
|||||||
state = hass.states.get(COVER_GROUP)
|
state = hass.states.get(COVER_GROUP)
|
||||||
assert state.attributes[ATTR_ASSUMED_STATE] is True
|
assert state.attributes[ATTR_ASSUMED_STATE] is True
|
||||||
|
|
||||||
|
# Test entity registry integration
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
entry = entity_registry.async_get(COVER_GROUP)
|
entry = entity_registry.async_get(COVER_GROUP)
|
||||||
assert entry
|
assert entry
|
||||||
|
Loading…
x
Reference in New Issue
Block a user