Add support for fan groups (#57941)
* Add support for fan groups * dry * dry * fix refactor error * tweaks * wip * tweaks * tweaks * fix * fixes * coverage * tweaks
This commit is contained in:
parent
f594bc353b
commit
def7c80e71
5 changed files with 836 additions and 3 deletions
508
tests/components/group/test_fan.py
Normal file
508
tests/components/group/test_fan.py
Normal file
|
@ -0,0 +1,508 @@
|
|||
"""The tests for the group fan platform."""
|
||||
from os import path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant import config as hass_config
|
||||
from homeassistant.components.fan import (
|
||||
ATTR_DIRECTION,
|
||||
ATTR_OSCILLATING,
|
||||
ATTR_PERCENTAGE,
|
||||
ATTR_PERCENTAGE_STEP,
|
||||
DIRECTION_FORWARD,
|
||||
DIRECTION_REVERSE,
|
||||
DOMAIN,
|
||||
SERVICE_OSCILLATE,
|
||||
SERVICE_SET_DIRECTION,
|
||||
SERVICE_SET_PERCENTAGE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
SUPPORT_DIRECTION,
|
||||
SUPPORT_OSCILLATE,
|
||||
SUPPORT_SET_SPEED,
|
||||
)
|
||||
from homeassistant.components.group import SERVICE_RELOAD
|
||||
from homeassistant.components.group.fan import DEFAULT_NAME
|
||||
from homeassistant.const import (
|
||||
ATTR_ASSUMED_STATE,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
CONF_ENTITIES,
|
||||
CONF_UNIQUE_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import CoreState
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import assert_setup_component
|
||||
|
||||
FAN_GROUP = "fan.fan_group"
|
||||
|
||||
MISSING_FAN_ENTITY_ID = "fan.missing"
|
||||
LIVING_ROOM_FAN_ENTITY_ID = "fan.living_room_fan"
|
||||
PERCENTAGE_FULL_FAN_ENTITY_ID = "fan.percentage_full_fan"
|
||||
CEILING_FAN_ENTITY_ID = "fan.ceiling_fan"
|
||||
PERCENTAGE_LIMITED_FAN_ENTITY_ID = "fan.percentage_limited_fan"
|
||||
|
||||
FULL_FAN_ENTITY_IDS = [LIVING_ROOM_FAN_ENTITY_ID, PERCENTAGE_FULL_FAN_ENTITY_ID]
|
||||
LIMITED_FAN_ENTITY_IDS = [CEILING_FAN_ENTITY_ID, PERCENTAGE_LIMITED_FAN_ENTITY_ID]
|
||||
|
||||
|
||||
FULL_SUPPORT_FEATURES = SUPPORT_SET_SPEED | SUPPORT_DIRECTION | SUPPORT_OSCILLATE
|
||||
|
||||
|
||||
CONFIG_MISSING_FAN = {
|
||||
DOMAIN: [
|
||||
{"platform": "demo"},
|
||||
{
|
||||
"platform": "group",
|
||||
CONF_ENTITIES: [
|
||||
MISSING_FAN_ENTITY_ID,
|
||||
*FULL_FAN_ENTITY_IDS,
|
||||
*LIMITED_FAN_ENTITY_IDS,
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
CONFIG_FULL_SUPPORT = {
|
||||
DOMAIN: [
|
||||
{"platform": "demo"},
|
||||
{
|
||||
"platform": "group",
|
||||
CONF_ENTITIES: [*FULL_FAN_ENTITY_IDS],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
CONFIG_LIMITED_SUPPORT = {
|
||||
DOMAIN: [
|
||||
{
|
||||
"platform": "group",
|
||||
CONF_ENTITIES: [*LIMITED_FAN_ENTITY_IDS],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
CONFIG_ATTRIBUTES = {
|
||||
DOMAIN: {
|
||||
"platform": "group",
|
||||
CONF_ENTITIES: [*FULL_FAN_ENTITY_IDS, *LIMITED_FAN_ENTITY_IDS],
|
||||
CONF_UNIQUE_ID: "unique_identifier",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def setup_comp(hass, config_count):
|
||||
"""Set up group fan component."""
|
||||
config, count = config_count
|
||||
with assert_setup_component(count, DOMAIN):
|
||||
await async_setup_component(hass, DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
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(FAN_GROUP)
|
||||
# No entity has a valid state -> group state off
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == DEFAULT_NAME
|
||||
assert state.attributes[ATTR_ENTITY_ID] == [
|
||||
*FULL_FAN_ENTITY_IDS,
|
||||
*LIMITED_FAN_ENTITY_IDS,
|
||||
]
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||
|
||||
# Set all entities as on -> group state on
|
||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_ON, {})
|
||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_ON, {})
|
||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, 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
|
||||
|
||||
# Set all entities as off -> group state off
|
||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
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 first entity as on -> group state on
|
||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_ON, {})
|
||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
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_ON
|
||||
|
||||
# Set last entity as on -> group state on
|
||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, STATE_OFF, {})
|
||||
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
|
||||
hass.states.async_remove(PERCENTAGE_LIMITED_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
|
||||
entity_registry = er.async_get(hass)
|
||||
entry = entity_registry.async_get(FAN_GROUP)
|
||||
assert entry
|
||||
assert entry.unique_id == "unique_identifier"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_count", [(CONFIG_ATTRIBUTES, 1)])
|
||||
async def test_attributes(hass, setup_comp):
|
||||
"""Test handling of state attributes."""
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == DEFAULT_NAME
|
||||
assert state.attributes[ATTR_ENTITY_ID] == [
|
||||
*FULL_FAN_ENTITY_IDS,
|
||||
*LIMITED_FAN_ENTITY_IDS,
|
||||
]
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||
hass.states.async_set(CEILING_FAN_ENTITY_ID, STATE_ON, {})
|
||||
hass.states.async_set(LIVING_ROOM_FAN_ENTITY_ID, STATE_ON, {})
|
||||
hass.states.async_set(PERCENTAGE_FULL_FAN_ENTITY_ID, 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
|
||||
|
||||
# Add Entity that supports speed
|
||||
hass.states.async_set(
|
||||
CEILING_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: SUPPORT_SET_SPEED,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == SUPPORT_SET_SPEED
|
||||
assert ATTR_PERCENTAGE in state.attributes
|
||||
assert state.attributes[ATTR_PERCENTAGE] == 50
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
|
||||
# Add Entity that supports
|
||||
# ### Test assumed state ###
|
||||
# ##########################
|
||||
|
||||
# Add Entity with a different speed should set assumed state
|
||||
hass.states.async_set(
|
||||
PERCENTAGE_LIMITED_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: SUPPORT_SET_SPEED,
|
||||
ATTR_PERCENTAGE: 75,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes[ATTR_ASSUMED_STATE] is True
|
||||
assert state.attributes[ATTR_PERCENTAGE] == int((50 + 75) / 2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_count", [(CONFIG_FULL_SUPPORT, 2)])
|
||||
async def test_direction_oscillating(hass, setup_comp):
|
||||
"""Test handling of direction and oscillating attributes."""
|
||||
|
||||
hass.states.async_set(
|
||||
LIVING_ROOM_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: True,
|
||||
ATTR_DIRECTION: DIRECTION_FORWARD,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
hass.states.async_set(
|
||||
PERCENTAGE_FULL_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: True,
|
||||
ATTR_DIRECTION: DIRECTION_FORWARD,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == DEFAULT_NAME
|
||||
assert state.attributes[ATTR_ENTITY_ID] == [*FULL_FAN_ENTITY_IDS]
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == FULL_SUPPORT_FEATURES
|
||||
assert ATTR_PERCENTAGE in state.attributes
|
||||
assert state.attributes[ATTR_PERCENTAGE] == 50
|
||||
assert state.attributes[ATTR_OSCILLATING] is True
|
||||
assert state.attributes[ATTR_DIRECTION] == DIRECTION_FORWARD
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
|
||||
# Add Entity that supports
|
||||
# ### Test assumed state ###
|
||||
# ##########################
|
||||
|
||||
# Add Entity with a different direction should set assumed state
|
||||
hass.states.async_set(
|
||||
PERCENTAGE_FULL_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: True,
|
||||
ATTR_DIRECTION: DIRECTION_REVERSE,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes[ATTR_ASSUMED_STATE] is True
|
||||
assert ATTR_PERCENTAGE in state.attributes
|
||||
assert state.attributes[ATTR_PERCENTAGE] == 50
|
||||
assert state.attributes[ATTR_OSCILLATING] is True
|
||||
assert ATTR_ASSUMED_STATE in state.attributes
|
||||
|
||||
# Now that everything is the same, no longer assumed state
|
||||
|
||||
hass.states.async_set(
|
||||
LIVING_ROOM_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: True,
|
||||
ATTR_DIRECTION: DIRECTION_REVERSE,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert ATTR_PERCENTAGE in state.attributes
|
||||
assert state.attributes[ATTR_PERCENTAGE] == 50
|
||||
assert state.attributes[ATTR_OSCILLATING] is True
|
||||
assert state.attributes[ATTR_DIRECTION] == DIRECTION_REVERSE
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
|
||||
hass.states.async_set(
|
||||
LIVING_ROOM_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: False,
|
||||
ATTR_DIRECTION: DIRECTION_FORWARD,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
hass.states.async_set(
|
||||
PERCENTAGE_FULL_FAN_ENTITY_ID,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FULL_SUPPORT_FEATURES,
|
||||
ATTR_OSCILLATING: False,
|
||||
ATTR_DIRECTION: DIRECTION_FORWARD,
|
||||
ATTR_PERCENTAGE: 50,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
assert state.state == STATE_ON
|
||||
assert ATTR_PERCENTAGE in state.attributes
|
||||
assert state.attributes[ATTR_PERCENTAGE] == 50
|
||||
assert state.attributes[ATTR_OSCILLATING] is False
|
||||
assert state.attributes[ATTR_DIRECTION] == DIRECTION_FORWARD
|
||||
assert ATTR_ASSUMED_STATE not in state.attributes
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_count", [(CONFIG_MISSING_FAN, 2)])
|
||||
async def test_state_missing_entity_id(hass, setup_comp):
|
||||
"""Test we can still setup with a missing entity id."""
|
||||
state = hass.states.get(FAN_GROUP)
|
||||
await hass.async_block_till_done()
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
async def test_setup_before_started(hass):
|
||||
"""Test we can setup before starting."""
|
||||
hass.state = CoreState.stopped
|
||||
assert await async_setup_component(hass, DOMAIN, CONFIG_MISSING_FAN)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(FAN_GROUP).state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_count", [(CONFIG_MISSING_FAN, 2)])
|
||||
async def test_reload(hass, setup_comp):
|
||||
"""Test the ability to reload fans."""
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(FAN_GROUP).state == STATE_OFF
|
||||
|
||||
yaml_path = path.join(
|
||||
_get_fixtures_base_path(),
|
||||
"fixtures",
|
||||
"group/fan_configuration.yaml",
|
||||
)
|
||||
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||
await hass.services.async_call(
|
||||
"group",
|
||||
SERVICE_RELOAD,
|
||||
{},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(FAN_GROUP) is None
|
||||
assert hass.states.get("fan.upstairs_fans") is not None
|
||||
|
||||
|
||||
def _get_fixtures_base_path():
|
||||
return path.dirname(path.dirname(path.dirname(__file__)))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_count", [(CONFIG_FULL_SUPPORT, 2)])
|
||||
async def test_service_calls(hass, setup_comp):
|
||||
"""Test calling services."""
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: FAN_GROUP}, blocking=True
|
||||
)
|
||||
assert hass.states.get(LIVING_ROOM_FAN_ENTITY_ID).state == STATE_ON
|
||||
assert hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID).state == STATE_ON
|
||||
assert hass.states.get(FAN_GROUP).state == STATE_ON
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_PERCENTAGE: 66},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_PERCENTAGE] == 66
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_PERCENTAGE] == 66
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_PERCENTAGE] == 66
|
||||
assert fan_group_state.attributes[ATTR_PERCENTAGE_STEP] == 100 / 3
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: FAN_GROUP}, blocking=True
|
||||
)
|
||||
assert hass.states.get(LIVING_ROOM_FAN_ENTITY_ID).state == STATE_OFF
|
||||
assert hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID).state == STATE_OFF
|
||||
assert hass.states.get(FAN_GROUP).state == STATE_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_PERCENTAGE,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_PERCENTAGE: 100},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_PERCENTAGE] == 100
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_PERCENTAGE] == 100
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_PERCENTAGE] == 100
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_PERCENTAGE: 0},
|
||||
blocking=True,
|
||||
)
|
||||
assert hass.states.get(LIVING_ROOM_FAN_ENTITY_ID).state == STATE_OFF
|
||||
assert hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID).state == STATE_OFF
|
||||
assert hass.states.get(FAN_GROUP).state == STATE_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_OSCILLATE,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_OSCILLATING: True},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_OSCILLATING] is True
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_OSCILLATING] is True
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_OSCILLATING] is True
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_OSCILLATE,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_OSCILLATING: False},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_OSCILLATING] is False
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_OSCILLATING] is False
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_OSCILLATING] is False
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_DIRECTION,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_DIRECTION: DIRECTION_FORWARD},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_DIRECTION] == DIRECTION_FORWARD
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_DIRECTION] == DIRECTION_FORWARD
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_DIRECTION] == DIRECTION_FORWARD
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_DIRECTION,
|
||||
{ATTR_ENTITY_ID: FAN_GROUP, ATTR_DIRECTION: DIRECTION_REVERSE},
|
||||
blocking=True,
|
||||
)
|
||||
living_room_fan_state = hass.states.get(LIVING_ROOM_FAN_ENTITY_ID)
|
||||
assert living_room_fan_state.attributes[ATTR_DIRECTION] == DIRECTION_REVERSE
|
||||
percentage_full_fan_state = hass.states.get(PERCENTAGE_FULL_FAN_ENTITY_ID)
|
||||
assert percentage_full_fan_state.attributes[ATTR_DIRECTION] == DIRECTION_REVERSE
|
||||
fan_group_state = hass.states.get(FAN_GROUP)
|
||||
assert fan_group_state.attributes[ATTR_DIRECTION] == DIRECTION_REVERSE
|
Loading…
Add table
Add a link
Reference in a new issue