Add group entity support to ZHA (#33196)
* split entity into base and entity * add initial light group support * add dispatching of groups to light * added zha group object * add group event listener * add and remove group members * get group by name * fix rebase * fix rebase * use group_id for unique_id * get entities from registry * use group name * update entity domain * update zha storage to handle groups * dispatch group entities * update light group * fix group remove and dispatch light group entities * allow picking the domain for group entities * beginning - auto determine entity domain * move methods to helpers so they can be shared * fix rebase * remove double init groups... again * cleanup startup * use asyncio create task * group entity discovery * add logging and fix group name * add logging and update group after probe if needed * test add group via gateway * add method to get group entity ids * update storage * test get group by name * update storage on remove * test group with single member * add light group tests * test some light group logic * type hints * fix tests and cleanup * revert init changes except for create task * remove group entity domain changing for now * add missing import * tricky code saving * review comments * clean up class defs * cleanup * fix rebase because I cant read * make pylint happy
This commit is contained in:
parent
3ee05ad4bb
commit
2a3c94bad0
16 changed files with 1084 additions and 257 deletions
|
@ -1,8 +1,18 @@
|
|||
"""Test ZHA Gateway."""
|
||||
import pytest
|
||||
import zigpy.zcl.clusters.general as general
|
||||
import logging
|
||||
|
||||
from .common import async_enable_traffic, get_zha_gateway
|
||||
import pytest
|
||||
import zigpy.profiles.zha as zha
|
||||
import zigpy.zcl.clusters.general as general
|
||||
import zigpy.zcl.clusters.lighting as lighting
|
||||
|
||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||
|
||||
from .common import async_enable_traffic, async_find_group_entity_id, get_zha_gateway
|
||||
|
||||
IEEE_GROUPABLE_DEVICE = "01:2d:6f:00:0a:90:69:e8"
|
||||
IEEE_GROUPABLE_DEVICE2 = "02:2d:6f:00:0a:90:69:e8"
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -15,7 +25,7 @@ def zigpy_dev_basic(zigpy_device_mock):
|
|||
"out_clusters": [],
|
||||
"device_type": 0,
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
@ -27,6 +37,74 @@ async def zha_dev_basic(hass, zha_device_restored, zigpy_dev_basic):
|
|||
return zha_device
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def coordinator(hass, zigpy_device_mock, zha_device_joined):
|
||||
"""Test zha light platform."""
|
||||
|
||||
zigpy_device = zigpy_device_mock(
|
||||
{
|
||||
1: {
|
||||
"in_clusters": [],
|
||||
"out_clusters": [],
|
||||
"device_type": zha.DeviceType.COLOR_DIMMABLE_LIGHT,
|
||||
}
|
||||
},
|
||||
ieee="00:15:8d:00:02:32:4f:32",
|
||||
nwk=0x0000,
|
||||
)
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.set_available(True)
|
||||
return zha_device
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def device_light_1(hass, zigpy_device_mock, zha_device_joined):
|
||||
"""Test zha light platform."""
|
||||
|
||||
zigpy_device = zigpy_device_mock(
|
||||
{
|
||||
1: {
|
||||
"in_clusters": [
|
||||
general.OnOff.cluster_id,
|
||||
general.LevelControl.cluster_id,
|
||||
lighting.Color.cluster_id,
|
||||
general.Groups.cluster_id,
|
||||
],
|
||||
"out_clusters": [],
|
||||
"device_type": zha.DeviceType.COLOR_DIMMABLE_LIGHT,
|
||||
}
|
||||
},
|
||||
ieee=IEEE_GROUPABLE_DEVICE,
|
||||
)
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.set_available(True)
|
||||
return zha_device
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def device_light_2(hass, zigpy_device_mock, zha_device_joined):
|
||||
"""Test zha light platform."""
|
||||
|
||||
zigpy_device = zigpy_device_mock(
|
||||
{
|
||||
1: {
|
||||
"in_clusters": [
|
||||
general.OnOff.cluster_id,
|
||||
general.LevelControl.cluster_id,
|
||||
lighting.Color.cluster_id,
|
||||
general.Groups.cluster_id,
|
||||
],
|
||||
"out_clusters": [],
|
||||
"device_type": zha.DeviceType.COLOR_DIMMABLE_LIGHT,
|
||||
}
|
||||
},
|
||||
ieee=IEEE_GROUPABLE_DEVICE2,
|
||||
)
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.set_available(True)
|
||||
return zha_device
|
||||
|
||||
|
||||
async def test_device_left(hass, zigpy_dev_basic, zha_dev_basic):
|
||||
"""Device leaving the network should become unavailable."""
|
||||
|
||||
|
@ -37,3 +115,57 @@ async def test_device_left(hass, zigpy_dev_basic, zha_dev_basic):
|
|||
|
||||
get_zha_gateway(hass).device_left(zigpy_dev_basic)
|
||||
assert zha_dev_basic.available is False
|
||||
|
||||
|
||||
async def test_gateway_group_methods(hass, device_light_1, device_light_2, coordinator):
|
||||
"""Test creating a group with 2 members."""
|
||||
zha_gateway = get_zha_gateway(hass)
|
||||
assert zha_gateway is not None
|
||||
zha_gateway.coordinator_zha_device = coordinator
|
||||
coordinator._zha_gateway = zha_gateway
|
||||
device_light_1._zha_gateway = zha_gateway
|
||||
device_light_2._zha_gateway = zha_gateway
|
||||
member_ieee_addresses = [device_light_1.ieee, device_light_2.ieee]
|
||||
|
||||
# test creating a group with 2 members
|
||||
zha_group = await zha_gateway.async_create_zigpy_group(
|
||||
"Test Group", member_ieee_addresses
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert zha_group is not None
|
||||
assert zha_group.entity_domain == LIGHT_DOMAIN
|
||||
assert len(zha_group.members) == 2
|
||||
for member in zha_group.members:
|
||||
assert member.ieee in member_ieee_addresses
|
||||
|
||||
entity_id = async_find_group_entity_id(hass, LIGHT_DOMAIN, zha_group)
|
||||
assert hass.states.get(entity_id) is not None
|
||||
|
||||
# test get group by name
|
||||
assert zha_group == zha_gateway.async_get_group_by_name(zha_group.name)
|
||||
|
||||
# test removing a group
|
||||
await zha_gateway.async_remove_zigpy_group(zha_group.group_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# we shouldn't have the group anymore
|
||||
assert zha_gateway.async_get_group_by_name(zha_group.name) is None
|
||||
|
||||
# the group entity should be cleaned up
|
||||
assert entity_id not in hass.states.async_entity_ids(LIGHT_DOMAIN)
|
||||
|
||||
# test creating a group with 1 member
|
||||
zha_group = await zha_gateway.async_create_zigpy_group(
|
||||
"Test Group", [device_light_1.ieee]
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert zha_group is not None
|
||||
assert zha_group.entity_domain is None
|
||||
assert len(zha_group.members) == 1
|
||||
for member in zha_group.members:
|
||||
assert member.ieee in [device_light_1.ieee]
|
||||
|
||||
# the group entity should not have been cleaned up
|
||||
assert entity_id not in hass.states.async_entity_ids(LIGHT_DOMAIN)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue