Improve group tests (#73630)
This commit is contained in:
parent
186141ee4d
commit
9b8c3e37bb
8 changed files with 685 additions and 235 deletions
|
@ -132,7 +132,7 @@ class BinarySensorGroup(GroupEntity, BinarySensorEntity):
|
||||||
# filtered_states are members currently in the state machine
|
# filtered_states are members currently in the state machine
|
||||||
filtered_states: list[str] = [x.state for x in all_states if x is not None]
|
filtered_states: list[str] = [x.state for x in all_states if x is not None]
|
||||||
|
|
||||||
# Set group as unavailable if all members are unavailable
|
# Set group as unavailable if all members are unavailable or missing
|
||||||
self._attr_available = any(
|
self._attr_available = any(
|
||||||
state != STATE_UNAVAILABLE for state in filtered_states
|
state != STATE_UNAVAILABLE for state in filtered_states
|
||||||
)
|
)
|
||||||
|
|
|
@ -50,7 +50,13 @@ async def test_default_state(hass):
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting_all(hass):
|
async def test_state_reporting_all(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'all' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if at least one group member is unknown or unavailable.
|
||||||
|
Otherwise, the group state is off if at least one group member is off.
|
||||||
|
Otherwise, the group state is on.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
BINARY_SENSOR_DOMAIN,
|
BINARY_SENSOR_DOMAIN,
|
||||||
|
@ -68,26 +74,12 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
assert (
|
||||||
await hass.async_block_till_done()
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
)
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_ON)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_UNAVAILABLE)
|
hass.states.async_set("binary_sensor.test1", STATE_UNAVAILABLE)
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -95,6 +87,12 @@ async def test_state_reporting_all(hass):
|
||||||
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# At least one member unknown or unavailable -> group unknown
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -105,9 +103,55 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member off -> group off
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# Otherwise -> on
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unavailable
|
||||||
|
hass.states.async_remove("binary_sensor.test1")
|
||||||
|
hass.states.async_remove("binary_sensor.test2")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert (
|
||||||
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting_any(hass):
|
async def test_state_reporting_any(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'any' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if all group members are unknown.
|
||||||
|
Otherwise, the group state is on if at least one group member is on.
|
||||||
|
Otherwise, the group state is off.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
BINARY_SENSOR_DOMAIN,
|
BINARY_SENSOR_DOMAIN,
|
||||||
|
@ -126,26 +170,17 @@ async def test_state_reporting_any(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
entity_registry = er.async_get(hass)
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
entry = entity_registry.async_get("binary_sensor.binary_sensor_group")
|
||||||
await hass.async_block_till_done()
|
assert entry
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
assert entry.unique_id == "unique_identifier"
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
assert (
|
||||||
await hass.async_block_till_done()
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
)
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_ON)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_UNAVAILABLE)
|
hass.states.async_set("binary_sensor.test1", STATE_UNAVAILABLE)
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -153,17 +188,59 @@ async def test_state_reporting_any(hass):
|
||||||
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
entity_registry = er.async_get(hass)
|
# All group members unknown -> unknown
|
||||||
entry = entity_registry.async_get("binary_sensor.binary_sensor_group")
|
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
||||||
assert entry
|
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
||||||
assert entry.unique_id == "unique_identifier"
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# Group members unknown or unavailable -> unknown
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member on -> group on
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
hass.states.async_set("binary_sensor.test1", STATE_ON)
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_ON
|
||||||
|
|
||||||
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
# Otherwise -> off
|
||||||
hass.states.async_set("binary_sensor.test2", STATE_UNKNOWN)
|
hass.states.async_set("binary_sensor.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNKNOWN
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_UNAVAILABLE)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("binary_sensor.binary_sensor_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unavailable
|
||||||
|
hass.states.async_remove("binary_sensor.test1")
|
||||||
|
hass.states.async_remove("binary_sensor.test2")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert (
|
||||||
|
hass.states.get("binary_sensor.binary_sensor_group").state == STATE_UNAVAILABLE
|
||||||
|
)
|
||||||
|
|
|
@ -33,6 +33,7 @@ from homeassistant.const import (
|
||||||
STATE_CLOSING,
|
STATE_CLOSING,
|
||||||
STATE_OPEN,
|
STATE_OPEN,
|
||||||
STATE_OPENING,
|
STATE_OPENING,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
@ -99,7 +100,14 @@ async def setup_comp(hass, config_count):
|
||||||
|
|
||||||
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
||||||
async def test_state(hass, setup_comp):
|
async def test_state(hass, setup_comp):
|
||||||
"""Test handling of state."""
|
"""Test handling of state.
|
||||||
|
|
||||||
|
The group state is unknown if all group members are unknown or unavailable.
|
||||||
|
Otherwise, the group state is opening if at least one group member is opening.
|
||||||
|
Otherwise, the group state is closing if at least one group member is closing.
|
||||||
|
Otherwise, the group state is open if at least one group member is open.
|
||||||
|
Otherwise, the group state is closed.
|
||||||
|
"""
|
||||||
state = hass.states.get(COVER_GROUP)
|
state = hass.states.get(COVER_GROUP)
|
||||||
# No entity has a valid state -> group state unknown
|
# No entity has a valid state -> group state unknown
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
@ -115,87 +123,125 @@ async def test_state(hass, setup_comp):
|
||||||
assert ATTR_CURRENT_POSITION not in state.attributes
|
assert ATTR_CURRENT_POSITION not in state.attributes
|
||||||
assert ATTR_CURRENT_TILT_POSITION not in state.attributes
|
assert ATTR_CURRENT_TILT_POSITION not in state.attributes
|
||||||
|
|
||||||
# Set all entities as closed -> group state closed
|
# The group state is unknown if all group members are unknown or unavailable.
|
||||||
hass.states.async_set(DEMO_COVER, STATE_CLOSED, {})
|
for state_1 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
for state_2 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
for state_3 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
state = hass.states.get(COVER_GROUP)
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
assert state.state == STATE_CLOSED
|
hass.states.async_set(DEMO_TILT, STATE_UNAVAILABLE, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
# Set all entities as open -> group state open
|
for state_1 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
for state_2 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_OPEN, {})
|
for state_3 in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_OPEN, {})
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
hass.states.async_set(DEMO_TILT, STATE_OPEN, {})
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
state = hass.states.get(COVER_GROUP)
|
hass.states.async_set(DEMO_TILT, STATE_UNKNOWN, {})
|
||||||
assert state.state == STATE_OPEN
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
# Set first entity as open -> group state open
|
# At least one member opening -> group opening
|
||||||
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
for state_1 in (
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
STATE_CLOSED,
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
STATE_CLOSING,
|
||||||
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
STATE_OPEN,
|
||||||
await hass.async_block_till_done()
|
STATE_OPENING,
|
||||||
state = hass.states.get(COVER_GROUP)
|
STATE_UNAVAILABLE,
|
||||||
assert state.state == STATE_OPEN
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
for state_2 in (
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_OPENING,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
for state_3 in (
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_OPENING,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_OPENING, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_OPENING
|
||||||
|
|
||||||
# Set last entity as open -> group state open
|
# At least one member closing -> group closing
|
||||||
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
for state_1 in (
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_CLOSED, {})
|
STATE_CLOSED,
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSED, {})
|
STATE_CLOSING,
|
||||||
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
STATE_OPEN,
|
||||||
await hass.async_block_till_done()
|
STATE_UNAVAILABLE,
|
||||||
state = hass.states.get(COVER_GROUP)
|
STATE_UNKNOWN,
|
||||||
assert state.state == STATE_OPEN
|
):
|
||||||
|
for state_2 in (
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
for state_3 in (
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
|
hass.states.async_set(DEMO_TILT, STATE_CLOSING, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(COVER_GROUP)
|
||||||
|
assert state.state == STATE_CLOSING
|
||||||
|
|
||||||
# Set conflicting valid states -> opening state has priority
|
# At least one member open -> group open
|
||||||
hass.states.async_set(DEMO_COVER, STATE_OPEN, {})
|
for state_1 in (STATE_CLOSED, STATE_OPEN, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_OPENING, {})
|
for state_2 in (STATE_CLOSED, STATE_OPEN, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_CLOSING, {})
|
for state_3 in (STATE_CLOSED, STATE_OPEN, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_TILT, STATE_CLOSED, {})
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
state = hass.states.get(COVER_GROUP)
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
assert state.state == STATE_OPENING
|
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 all entities to unknown state -> group state unknown
|
# At least one member closed -> group closed
|
||||||
hass.states.async_set(DEMO_COVER, STATE_UNKNOWN, {})
|
for state_1 in (STATE_CLOSED, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_POS, STATE_UNKNOWN, {})
|
for state_2 in (STATE_CLOSED, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_COVER_TILT, STATE_UNKNOWN, {})
|
for state_3 in (STATE_CLOSED, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(DEMO_TILT, STATE_UNKNOWN, {})
|
hass.states.async_set(DEMO_COVER, state_1, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_POS, state_2, {})
|
||||||
|
hass.states.async_set(DEMO_COVER_TILT, state_3, {})
|
||||||
|
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
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unknown
|
||||||
|
hass.states.async_remove(DEMO_COVER)
|
||||||
|
hass.states.async_remove(DEMO_COVER_POS)
|
||||||
|
hass.states.async_remove(DEMO_COVER_TILT)
|
||||||
|
hass.states.async_remove(DEMO_TILT)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(COVER_GROUP)
|
state = hass.states.get(COVER_GROUP)
|
||||||
assert state.state == STATE_UNKNOWN
|
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):
|
||||||
|
|
|
@ -33,6 +33,8 @@ from homeassistant.const import (
|
||||||
CONF_UNIQUE_ID,
|
CONF_UNIQUE_ID,
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
)
|
)
|
||||||
from homeassistant.core import CoreState
|
from homeassistant.core import CoreState
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
@ -111,7 +113,11 @@ async def setup_comp(hass, config_count):
|
||||||
|
|
||||||
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
||||||
async def test_state(hass, setup_comp):
|
async def test_state(hass, setup_comp):
|
||||||
"""Test handling of state."""
|
"""Test handling of state.
|
||||||
|
|
||||||
|
The group state is on if at least one group member is on.
|
||||||
|
Otherwise, the group state is off.
|
||||||
|
"""
|
||||||
state = hass.states.get(FAN_GROUP)
|
state = hass.states.get(FAN_GROUP)
|
||||||
# No entity has a valid state -> group state off
|
# No entity has a valid state -> group state off
|
||||||
assert state.state == STATE_OFF
|
assert state.state == STATE_OFF
|
||||||
|
@ -123,41 +129,55 @@ async def test_state(hass, setup_comp):
|
||||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
# Set all entities as on -> group state on
|
# The group state is off if all group members are off, unknown or unavailable.
|
||||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_ON, {})
|
for state_1 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_ON, {})
|
for state_2 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_ON, {})
|
for state_3 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_ON, {})
|
hass.states.async_set(CEILING_FAN_ENTITY_ID, state_1, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, state_2, {})
|
||||||
state = hass.states.get(FAN_GROUP)
|
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, state_3, {})
|
||||||
assert state.state == STATE_ON
|
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_OFF, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(FAN_GROUP)
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
# Set all entities as off -> group state off
|
for state_1 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_2 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_3 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
hass.states.async_set(CEILING_FAN_ENTITY_ID, state_1, {})
|
||||||
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_OFF, {})
|
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, state_2, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, state_3, {})
|
||||||
state = hass.states.get(FAN_GROUP)
|
hass.states.async_set(
|
||||||
assert state.state == STATE_OFF
|
PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_UNAVAILABLE, {}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(FAN_GROUP)
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
# Set first entity as on -> group state on
|
for state_1 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_ON, {})
|
for state_2 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_3 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
hass.states.async_set(CEILING_FAN_ENTITY_ID, state_1, {})
|
||||||
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_OFF, {})
|
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, state_2, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, state_3, {})
|
||||||
state = hass.states.get(FAN_GROUP)
|
hass.states.async_set(
|
||||||
assert state.state == STATE_ON
|
PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_UNKNOWN, {}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(FAN_GROUP)
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
# Set last entity as on -> group state on
|
# At least one member on -> group on
|
||||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_1 in (STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_2 in (STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
for state_3 in (STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_ON, {})
|
hass.states.async_set(CEILING_FAN_ENTITY_ID, state_1, {})
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, state_2, {})
|
||||||
state = hass.states.get(FAN_GROUP)
|
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, state_3, {})
|
||||||
assert state.state == STATE_ON
|
hass.states.async_set(PERCENTAGE_LIMITED_FAN_ENTITY_ID, STATE_ON, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(FAN_GROUP)
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
# now remove an entity
|
# now remove an entity
|
||||||
hass.states.async_remove(PERCENTAGE_LIMITED_FAN_ENTITY_ID)
|
hass.states.async_remove(PERCENTAGE_LIMITED_FAN_ENTITY_ID)
|
||||||
|
@ -167,6 +187,16 @@ async def test_state(hass, setup_comp):
|
||||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
|
# now remove all entities
|
||||||
|
hass.states.async_remove(CEILING_FAN_ENTITY_ID)
|
||||||
|
hass.states.async_remove(LIVING_ROOM_FAN_ENTITY_ID)
|
||||||
|
hass.states.async_remove(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(FAN_GROUP)
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
# Test entity registry integration
|
# Test entity registry integration
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
entry = entity_registry.async_get(FAN_GROUP)
|
entry = entity_registry.async_get(FAN_GROUP)
|
||||||
|
|
|
@ -88,8 +88,14 @@ async def test_default_state(hass):
|
||||||
assert entry.unique_id == "unique_identifier"
|
assert entry.unique_id == "unique_identifier"
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting(hass):
|
async def test_state_reporting_any(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'any' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if all group members are unknown.
|
||||||
|
Otherwise, the group state is on if at least one group member is on.
|
||||||
|
Otherwise, the group state is off.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
|
@ -105,29 +111,79 @@ async def test_state_reporting(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.async_set("light.test1", STATE_ON)
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("light.light_group").state == STATE_ON
|
|
||||||
|
|
||||||
hass.states.async_set("light.test1", STATE_ON)
|
|
||||||
hass.states.async_set("light.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("light.light_group").state == STATE_ON
|
|
||||||
|
|
||||||
hass.states.async_set("light.test1", STATE_OFF)
|
|
||||||
hass.states.async_set("light.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("light.light_group").state == STATE_OFF
|
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
hass.states.async_set("light.test1", STATE_UNAVAILABLE)
|
hass.states.async_set("light.test1", STATE_UNAVAILABLE)
|
||||||
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# All group members unknown -> unknown
|
||||||
|
hass.states.async_set("light.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# Group members unknown or unavailable -> unknown
|
||||||
|
hass.states.async_set("light.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member on -> group on
|
||||||
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
|
hass.states.async_set("light.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
|
hass.states.async_set("light.test2", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_ON
|
||||||
|
|
||||||
|
# Otherwise -> off
|
||||||
|
hass.states.async_set("light.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("light.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("light.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_UNAVAILABLE)
|
||||||
|
hass.states.async_set("light.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unavailable
|
||||||
|
hass.states.async_remove("light.test1")
|
||||||
|
hass.states.async_remove("light.test2")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting_all(hass):
|
async def test_state_reporting_all(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'all' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if at least one group member is unknown or unavailable.
|
||||||
|
Otherwise, the group state is off if at least one group member is off.
|
||||||
|
Otherwise, the group state is on.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
|
@ -143,11 +199,47 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
|
hass.states.async_set("light.test1", STATE_UNAVAILABLE)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# At least one member unknown or unavailable -> group unknown
|
||||||
hass.states.async_set("light.test1", STATE_ON)
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("light.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("light.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("binary_sensor.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("light.light_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member off -> group off
|
||||||
hass.states.async_set("light.test1", STATE_ON)
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
hass.states.async_set("light.test2", STATE_OFF)
|
hass.states.async_set("light.test2", STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -158,13 +250,15 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.light_group").state == STATE_OFF
|
assert hass.states.get("light.light_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# Otherwise -> on
|
||||||
hass.states.async_set("light.test1", STATE_ON)
|
hass.states.async_set("light.test1", STATE_ON)
|
||||||
hass.states.async_set("light.test2", STATE_ON)
|
hass.states.async_set("light.test2", STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.light_group").state == STATE_ON
|
assert hass.states.get("light.light_group").state == STATE_ON
|
||||||
|
|
||||||
hass.states.async_set("light.test1", STATE_UNAVAILABLE)
|
# All group members removed from the state machine -> unavailable
|
||||||
hass.states.async_set("light.test2", STATE_UNAVAILABLE)
|
hass.states.async_remove("light.test1")
|
||||||
|
hass.states.async_remove("light.test2")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("light.light_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,16 @@ async def test_default_state(hass):
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting(hass):
|
async def test_state_reporting(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if at least one group member is unknown or unavailable.
|
||||||
|
Otherwise, the group state is jammed if at least one group member is jammed.
|
||||||
|
Otherwise, the group state is locking if at least one group member is locking.
|
||||||
|
Otherwise, the group state is unlocking if at least one group member is unlocking.
|
||||||
|
Otherwise, the group state is unlocked if at least one group member is unlocked.
|
||||||
|
Otherwise, the group state is locked.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
LOCK_DOMAIN,
|
LOCK_DOMAIN,
|
||||||
|
@ -72,43 +81,98 @@ async def test_state_reporting(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_LOCKED)
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
|
hass.states.async_set("lock.test1", STATE_UNAVAILABLE)
|
||||||
hass.states.async_set("lock.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("lock.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_UNKNOWN
|
assert hass.states.get("lock.lock_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_LOCKED)
|
# At least one member unknown or unavailable -> group unknown
|
||||||
hass.states.async_set("lock.test2", STATE_UNLOCKED)
|
for state_1 in (
|
||||||
await hass.async_block_till_done()
|
STATE_JAMMED,
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED
|
STATE_LOCKED,
|
||||||
|
STATE_LOCKING,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
STATE_UNLOCKING,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
for state_1 in (
|
||||||
|
STATE_JAMMED,
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_LOCKING,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
STATE_UNLOCKING,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member jammed -> group jammed
|
||||||
|
for state_1 in (
|
||||||
|
STATE_JAMMED,
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_LOCKING,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
STATE_UNLOCKING,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_JAMMED)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_JAMMED
|
||||||
|
|
||||||
|
# At least one member locking -> group unlocking
|
||||||
|
for state_1 in (
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_LOCKING,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
STATE_UNLOCKING,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_LOCKING)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_LOCKING
|
||||||
|
|
||||||
|
# At least one member unlocking -> group unlocking
|
||||||
|
for state_1 in (
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
STATE_UNLOCKING,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_UNLOCKING)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_UNLOCKING
|
||||||
|
|
||||||
|
# At least one member unlocked -> group unlocked
|
||||||
|
for state_1 in (
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
):
|
||||||
|
hass.states.async_set("lock.test1", state_1)
|
||||||
|
hass.states.async_set("lock.test2", STATE_UNLOCKED)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED
|
||||||
|
|
||||||
|
# Otherwise -> locked
|
||||||
hass.states.async_set("lock.test1", STATE_LOCKED)
|
hass.states.async_set("lock.test1", STATE_LOCKED)
|
||||||
hass.states.async_set("lock.test2", STATE_LOCKED)
|
hass.states.async_set("lock.test2", STATE_LOCKED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_LOCKED
|
assert hass.states.get("lock.lock_group").state == STATE_LOCKED
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_UNLOCKED)
|
# All group members removed from the state machine -> unavailable
|
||||||
hass.states.async_set("lock.test2", STATE_UNLOCKED)
|
hass.states.async_remove("lock.test1")
|
||||||
await hass.async_block_till_done()
|
hass.states.async_remove("lock.test2")
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED
|
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_UNLOCKED)
|
|
||||||
hass.states.async_set("lock.test2", STATE_JAMMED)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_JAMMED
|
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_LOCKED)
|
|
||||||
hass.states.async_set("lock.test2", STATE_UNLOCKING)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_UNLOCKING
|
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_UNLOCKED)
|
|
||||||
hass.states.async_set("lock.test2", STATE_LOCKING)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_LOCKING
|
|
||||||
|
|
||||||
hass.states.async_set("lock.test1", STATE_UNAVAILABLE)
|
|
||||||
hass.states.async_set("lock.test2", STATE_UNAVAILABLE)
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("lock.lock_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("lock.lock_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ from homeassistant.const import (
|
||||||
SERVICE_VOLUME_DOWN,
|
SERVICE_VOLUME_DOWN,
|
||||||
SERVICE_VOLUME_MUTE,
|
SERVICE_VOLUME_MUTE,
|
||||||
SERVICE_VOLUME_UP,
|
SERVICE_VOLUME_UP,
|
||||||
|
STATE_BUFFERING,
|
||||||
|
STATE_IDLE,
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
STATE_PAUSED,
|
STATE_PAUSED,
|
||||||
|
@ -99,7 +101,17 @@ async def test_default_state(hass):
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting(hass):
|
async def test_state_reporting(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if all group members are unknown.
|
||||||
|
Otherwise, the group state is buffering if all group members are buffering.
|
||||||
|
Otherwise, the group state is idle if all group members are idle.
|
||||||
|
Otherwise, the group state is paused if all group members are paused.
|
||||||
|
Otherwise, the group state is playing if all group members are playing.
|
||||||
|
Otherwise, the group state is on if at least one group member is not off, unavailable or unknown.
|
||||||
|
Otherwise, the group state is off.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
MEDIA_DOMAIN,
|
MEDIA_DOMAIN,
|
||||||
|
@ -114,27 +126,60 @@ async def test_state_reporting(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Initial state with no group member in the state machine -> unknown
|
||||||
assert hass.states.get("media_player.media_group").state == STATE_UNKNOWN
|
assert hass.states.get("media_player.media_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
hass.states.async_set("media_player.player_1", STATE_ON)
|
# All group members buffering -> buffering
|
||||||
hass.states.async_set("media_player.player_2", STATE_UNAVAILABLE)
|
# All group members idle -> idle
|
||||||
await hass.async_block_till_done()
|
# All group members paused -> paused
|
||||||
assert hass.states.get("media_player.media_group").state == STATE_ON
|
# All group members playing -> playing
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
|
# All group members unknown -> unknown
|
||||||
|
for state in (
|
||||||
|
STATE_BUFFERING,
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_PAUSED,
|
||||||
|
STATE_PLAYING,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
):
|
||||||
|
hass.states.async_set("media_player.player_1", state)
|
||||||
|
hass.states.async_set("media_player.player_2", state)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("media_player.media_group").state == state
|
||||||
|
|
||||||
hass.states.async_set("media_player.player_1", STATE_ON)
|
# At least one member not off, unavailable or unknown -> on
|
||||||
hass.states.async_set("media_player.player_2", STATE_OFF)
|
for state_1 in (STATE_BUFFERING, STATE_IDLE, STATE_ON, STATE_PAUSED, STATE_PLAYING):
|
||||||
await hass.async_block_till_done()
|
for state_2 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
assert hass.states.get("media_player.media_group").state == STATE_ON
|
hass.states.async_set("media_player.player_1", state_1)
|
||||||
|
hass.states.async_set("media_player.player_2", state_2)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("media_player.media_group").state == STATE_ON
|
||||||
|
|
||||||
hass.states.async_set("media_player.player_1", STATE_OFF)
|
for state_1 in (STATE_OFF, STATE_UNAVAILABLE, STATE_UNKNOWN):
|
||||||
hass.states.async_set("media_player.player_2", STATE_UNAVAILABLE)
|
hass.states.async_set("media_player.player_1", state_1)
|
||||||
await hass.async_block_till_done()
|
hass.states.async_set("media_player.player_2", STATE_OFF)
|
||||||
assert hass.states.get("media_player.media_group").state == STATE_OFF
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("media_player.media_group").state == STATE_OFF
|
||||||
|
|
||||||
hass.states.async_set("media_player.player_1", STATE_UNAVAILABLE)
|
# Otherwise off
|
||||||
hass.states.async_set("media_player.player_2", STATE_UNAVAILABLE)
|
for state_1 in (STATE_OFF, STATE_UNKNOWN):
|
||||||
|
hass.states.async_set("media_player.player_1", state_1)
|
||||||
|
hass.states.async_set("media_player.player_2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("media_player.media_group").state == STATE_OFF
|
||||||
|
|
||||||
|
for state_1 in (STATE_OFF, STATE_UNAVAILABLE):
|
||||||
|
hass.states.async_set("media_player.player_1", state_1)
|
||||||
|
hass.states.async_set("media_player.player_2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("media_player.media_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unknown
|
||||||
|
hass.states.async_remove("media_player.player_1")
|
||||||
|
hass.states.async_remove("media_player.player_2")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("media_player.media_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("media_player.media_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
async def test_supported_features(hass):
|
async def test_supported_features(hass):
|
||||||
|
|
|
@ -56,7 +56,13 @@ async def test_default_state(hass):
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting(hass):
|
async def test_state_reporting(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'any' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if all group members are unknown.
|
||||||
|
Otherwise, the group state is on if at least one group member is on.
|
||||||
|
Otherwise, the group state is off.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
SWITCH_DOMAIN,
|
SWITCH_DOMAIN,
|
||||||
|
@ -72,29 +78,79 @@ async def test_state_reporting(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.async_set("switch.test1", STATE_ON)
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_ON
|
|
||||||
|
|
||||||
hass.states.async_set("switch.test1", STATE_ON)
|
|
||||||
hass.states.async_set("switch.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_ON
|
|
||||||
|
|
||||||
hass.states.async_set("switch.test1", STATE_OFF)
|
|
||||||
hass.states.async_set("switch.test2", STATE_OFF)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
hass.states.async_set("switch.test1", STATE_UNAVAILABLE)
|
hass.states.async_set("switch.test1", STATE_UNAVAILABLE)
|
||||||
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# All group members unknown -> unknown
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# Group members unknown or unavailable -> unknown
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member on -> group on
|
||||||
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
|
hass.states.async_set("switch.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
|
hass.states.async_set("switch.test2", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_ON
|
||||||
|
|
||||||
|
# Otherwise -> off
|
||||||
|
hass.states.async_set("switch.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("switch.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("switch.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNAVAILABLE)
|
||||||
|
hass.states.async_set("switch.test2", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# All group members removed from the state machine -> unavailable
|
||||||
|
hass.states.async_remove("switch.test1")
|
||||||
|
hass.states.async_remove("switch.test2")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
async def test_state_reporting_all(hass):
|
async def test_state_reporting_all(hass):
|
||||||
"""Test the state reporting."""
|
"""Test the state reporting in 'all' mode.
|
||||||
|
|
||||||
|
The group state is unavailable if all group members are unavailable.
|
||||||
|
Otherwise, the group state is unknown if at least one group member is unknown or unavailable.
|
||||||
|
Otherwise, the group state is off if at least one group member is off.
|
||||||
|
Otherwise, the group state is on.
|
||||||
|
"""
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
SWITCH_DOMAIN,
|
SWITCH_DOMAIN,
|
||||||
|
@ -110,11 +166,47 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Initial state with no group member in the state machine -> unavailable
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# All group members unavailable -> unavailable
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNAVAILABLE)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# At least one member unknown or unavailable -> group unknown
|
||||||
hass.states.async_set("switch.test1", STATE_ON)
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_OFF)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNKNOWN)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
hass.states.async_set("switch.test1", STATE_UNKNOWN)
|
||||||
|
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("switch.switch_group").state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
# At least one member off -> group off
|
||||||
hass.states.async_set("switch.test1", STATE_ON)
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
hass.states.async_set("switch.test2", STATE_OFF)
|
hass.states.async_set("switch.test2", STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -125,13 +217,15 @@ async def test_state_reporting_all(hass):
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
assert hass.states.get("switch.switch_group").state == STATE_OFF
|
||||||
|
|
||||||
|
# Otherwise -> on
|
||||||
hass.states.async_set("switch.test1", STATE_ON)
|
hass.states.async_set("switch.test1", STATE_ON)
|
||||||
hass.states.async_set("switch.test2", STATE_ON)
|
hass.states.async_set("switch.test2", STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_ON
|
assert hass.states.get("switch.switch_group").state == STATE_ON
|
||||||
|
|
||||||
hass.states.async_set("switch.test1", STATE_UNAVAILABLE)
|
# All group members removed from the state machine -> unavailable
|
||||||
hass.states.async_set("switch.test2", STATE_UNAVAILABLE)
|
hass.states.async_remove("switch.test1")
|
||||||
|
hass.states.async_remove("switch.test2")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
assert hass.states.get("switch.switch_group").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue