Esempio n. 1
0
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]
    members = [
        GroupMember(device_light_1.ieee, 1),
        GroupMember(device_light_2.ieee, 1)
    ]

    # test creating a group with 2 members
    zha_group = await zha_gateway.async_create_zigpy_group(
        "Test Group", members)
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 2
    for member in zha_group.members:
        assert member.device.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", [GroupMember(device_light_1.ieee, 1)])
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 1
    for member in zha_group.members:
        assert member.device.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)

    with patch("zigpy.zcl.Cluster.request", side_effect=asyncio.TimeoutError):
        await zha_group.members[0].async_remove_from_group()
        assert len(zha_group.members) == 1
        for member in zha_group.members:
            assert member.device.ieee in [device_light_1.ieee]
Esempio n. 2
0
async def test_zha_group_fan_entity_failure_state(
    hass, device_fan_1, device_fan_2, coordinator, caplog
):
    """Test the fan entity for a ZHA group when writing attributes generates an exception."""
    zha_gateway = get_zha_gateway(hass)
    assert zha_gateway is not None
    zha_gateway.coordinator_zha_device = coordinator
    coordinator._zha_gateway = zha_gateway
    device_fan_1._zha_gateway = zha_gateway
    device_fan_2._zha_gateway = zha_gateway
    member_ieee_addresses = [device_fan_1.ieee, device_fan_2.ieee]
    members = [GroupMember(device_fan_1.ieee, 1), GroupMember(device_fan_2.ieee, 1)]

    # test creating a group with 2 members
    zha_group = await zha_gateway.async_create_zigpy_group("Test Group", members)
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 2
    for member in zha_group.members:
        assert member.device.ieee in member_ieee_addresses
        assert member.group == zha_group
        assert member.endpoint is not None

    entity_domains = GROUP_PROBE.determine_entity_domains(hass, zha_group)
    assert len(entity_domains) == 2

    assert LIGHT_DOMAIN in entity_domains
    assert DOMAIN in entity_domains

    entity_id = async_find_group_entity_id(hass, DOMAIN, zha_group)
    assert hass.states.get(entity_id) is not None

    group_fan_cluster = zha_group.endpoint[hvac.Fan.cluster_id]

    await async_enable_traffic(hass, [device_fan_1, device_fan_2], enabled=False)
    await async_wait_for_updates(hass)
    # test that the fans were created and that they are unavailable
    assert hass.states.get(entity_id).state == STATE_UNAVAILABLE

    # allow traffic to flow through the gateway and device
    await async_enable_traffic(hass, [device_fan_1, device_fan_2])
    await async_wait_for_updates(hass)
    # test that the fan group entity was created and is off
    assert hass.states.get(entity_id).state == STATE_OFF

    # turn on from HA
    group_fan_cluster.write_attributes.reset_mock()
    await async_turn_on(hass, entity_id)
    await hass.async_block_till_done()
    assert len(group_fan_cluster.write_attributes.mock_calls) == 1
    assert group_fan_cluster.write_attributes.call_args[0][0] == {"fan_mode": 2}

    assert "Could not set fan mode" in caplog.text
Esempio n. 3
0
async def test_gateway_create_group_with_id(hass, device_light_1, coordinator):
    """Test creating a group with a specific ID."""
    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

    zha_group = await zha_gateway.async_create_zigpy_group(
        "Test Group", [GroupMember(device_light_1.ieee, 1)], group_id=0x1234)
    await hass.async_block_till_done()

    assert len(zha_group.members) == 1
    assert zha_group.members[0].device is device_light_1
    assert zha_group.group_id == 0x1234
Esempio n. 4
0
async def test_zha_group_light_entity(
    hass, device_light_1, device_light_2, device_light_3, coordinator
):
    """Test the light entity for a ZHA group."""
    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]
    members = [GroupMember(device_light_1.ieee, 1), GroupMember(device_light_2.ieee, 1)]

    assert coordinator.is_coordinator

    # test creating a group with 2 members
    zha_group = await zha_gateway.async_create_zigpy_group("Test Group", members)
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 2
    for member in zha_group.members:
        assert member.device.ieee in member_ieee_addresses
        assert member.group == zha_group
        assert member.endpoint is not None

    device_1_entity_id = await find_entity_id(DOMAIN, device_light_1, hass)
    device_2_entity_id = await find_entity_id(DOMAIN, device_light_2, hass)
    device_3_entity_id = await find_entity_id(DOMAIN, device_light_3, hass)

    assert (
        device_1_entity_id != device_2_entity_id
        and device_1_entity_id != device_3_entity_id
    )
    assert device_2_entity_id != device_3_entity_id

    group_entity_id = async_find_group_entity_id(hass, DOMAIN, zha_group)
    assert hass.states.get(group_entity_id) is not None

    assert device_1_entity_id in zha_group.member_entity_ids
    assert device_2_entity_id in zha_group.member_entity_ids
    assert device_3_entity_id not in zha_group.member_entity_ids

    group_cluster_on_off = zha_group.endpoint[general.OnOff.cluster_id]
    group_cluster_level = zha_group.endpoint[general.LevelControl.cluster_id]
    group_cluster_identify = zha_group.endpoint[general.Identify.cluster_id]

    dev1_cluster_on_off = device_light_1.device.endpoints[1].on_off
    dev2_cluster_on_off = device_light_2.device.endpoints[1].on_off
    dev3_cluster_on_off = device_light_3.device.endpoints[1].on_off

    dev1_cluster_level = device_light_1.device.endpoints[1].level

    await async_enable_traffic(
        hass, [device_light_1, device_light_2, device_light_3], enabled=False
    )
    await hass.async_block_till_done()
    # test that the lights were created and that they are unavailable
    assert hass.states.get(group_entity_id).state == STATE_UNAVAILABLE

    # allow traffic to flow through the gateway and device
    await async_enable_traffic(hass, [device_light_1, device_light_2, device_light_3])
    await hass.async_block_till_done()

    # test that the lights were created and are off
    assert hass.states.get(group_entity_id).state == STATE_OFF

    # test turning the lights on and off from the HA
    await async_test_on_off_from_hass(hass, group_cluster_on_off, group_entity_id)

    # test short flashing the lights from the HA
    await async_test_flash_from_hass(
        hass, group_cluster_identify, group_entity_id, FLASH_SHORT
    )

    # test turning the lights on and off from the light
    await async_test_on_off_from_light(hass, dev1_cluster_on_off, group_entity_id)

    # test turning the lights on and off from the HA
    await async_test_level_on_off_from_hass(
        hass, group_cluster_on_off, group_cluster_level, group_entity_id
    )

    # test getting a brightness change from the network
    await async_test_on_from_light(hass, dev1_cluster_on_off, group_entity_id)
    await async_test_dimmer_from_light(
        hass, dev1_cluster_level, group_entity_id, 150, STATE_ON
    )

    # test long flashing the lights from the HA
    await async_test_flash_from_hass(
        hass, group_cluster_identify, group_entity_id, FLASH_LONG
    )

    assert len(zha_group.members) == 2
    # test some of the group logic to make sure we key off states correctly
    await send_attributes_report(hass, dev1_cluster_on_off, {0: 1})
    await send_attributes_report(hass, dev2_cluster_on_off, {0: 1})
    await hass.async_block_till_done()

    # test that group light is on
    assert hass.states.get(device_1_entity_id).state == STATE_ON
    assert hass.states.get(device_2_entity_id).state == STATE_ON
    assert hass.states.get(group_entity_id).state == STATE_ON

    await send_attributes_report(hass, dev1_cluster_on_off, {0: 0})
    await hass.async_block_till_done()

    # test that group light is still on
    assert hass.states.get(device_1_entity_id).state == STATE_OFF
    assert hass.states.get(device_2_entity_id).state == STATE_ON
    assert hass.states.get(group_entity_id).state == STATE_ON

    await send_attributes_report(hass, dev2_cluster_on_off, {0: 0})
    await hass.async_block_till_done()

    # test that group light is now off
    assert hass.states.get(device_1_entity_id).state == STATE_OFF
    assert hass.states.get(device_2_entity_id).state == STATE_OFF
    assert hass.states.get(group_entity_id).state == STATE_OFF

    await send_attributes_report(hass, dev1_cluster_on_off, {0: 1})
    await hass.async_block_till_done()

    # test that group light is now back on
    assert hass.states.get(device_1_entity_id).state == STATE_ON
    assert hass.states.get(device_2_entity_id).state == STATE_OFF
    assert hass.states.get(group_entity_id).state == STATE_ON

    # turn it off to test a new member add being tracked
    await send_attributes_report(hass, dev1_cluster_on_off, {0: 0})
    await hass.async_block_till_done()
    assert hass.states.get(device_1_entity_id).state == STATE_OFF
    assert hass.states.get(device_2_entity_id).state == STATE_OFF
    assert hass.states.get(group_entity_id).state == STATE_OFF

    # add a new member and test that his state is also tracked
    await zha_group.async_add_members([GroupMember(device_light_3.ieee, 1)])
    await send_attributes_report(hass, dev3_cluster_on_off, {0: 1})
    await hass.async_block_till_done()
    assert device_3_entity_id in zha_group.member_entity_ids
    assert len(zha_group.members) == 3

    assert hass.states.get(device_1_entity_id).state == STATE_OFF
    assert hass.states.get(device_2_entity_id).state == STATE_OFF
    assert hass.states.get(device_3_entity_id).state == STATE_ON
    assert hass.states.get(group_entity_id).state == STATE_ON

    # make the group have only 1 member and now there should be no entity
    await zha_group.async_remove_members(
        [GroupMember(device_light_2.ieee, 1), GroupMember(device_light_3.ieee, 1)]
    )
    assert len(zha_group.members) == 1
    assert hass.states.get(group_entity_id) is None
    assert device_2_entity_id not in zha_group.member_entity_ids
    assert device_3_entity_id not in zha_group.member_entity_ids

    # make sure the entity registry entry is still there
    assert zha_gateway.ha_entity_registry.async_get(group_entity_id) is not None

    # add a member back and ensure that the group entity was created again
    await zha_group.async_add_members([GroupMember(device_light_3.ieee, 1)])
    await send_attributes_report(hass, dev3_cluster_on_off, {0: 1})
    await hass.async_block_till_done()
    assert len(zha_group.members) == 2
    assert hass.states.get(group_entity_id).state == STATE_ON

    # add a 3rd member and ensure we still have an entity and we track the new one
    await send_attributes_report(hass, dev1_cluster_on_off, {0: 0})
    await send_attributes_report(hass, dev3_cluster_on_off, {0: 0})
    await hass.async_block_till_done()
    assert hass.states.get(group_entity_id).state == STATE_OFF

    # this will test that _reprobe_group is used correctly
    await zha_group.async_add_members(
        [GroupMember(device_light_2.ieee, 1), GroupMember(coordinator.ieee, 1)]
    )
    await send_attributes_report(hass, dev2_cluster_on_off, {0: 1})
    await hass.async_block_till_done()
    assert len(zha_group.members) == 4
    assert hass.states.get(group_entity_id).state == STATE_ON

    await zha_group.async_remove_members([GroupMember(coordinator.ieee, 1)])
    await hass.async_block_till_done()
    assert hass.states.get(group_entity_id).state == STATE_ON
    assert len(zha_group.members) == 3

    # remove the group and ensure that there is no entity and that the entity registry is cleaned up
    assert zha_gateway.ha_entity_registry.async_get(group_entity_id) is not None
    await zha_gateway.async_remove_zigpy_group(zha_group.group_id)
    assert hass.states.get(group_entity_id) is None
    assert zha_gateway.ha_entity_registry.async_get(group_entity_id) is None
Esempio n. 5
0
async def test_zha_group_switch_entity(hass, device_switch_1, device_switch_2,
                                       coordinator):
    """Test the switch entity for a ZHA group."""
    zha_gateway = get_zha_gateway(hass)
    assert zha_gateway is not None
    zha_gateway.coordinator_zha_device = coordinator
    coordinator._zha_gateway = zha_gateway
    device_switch_1._zha_gateway = zha_gateway
    device_switch_2._zha_gateway = zha_gateway
    member_ieee_addresses = [device_switch_1.ieee, device_switch_2.ieee]
    members = [
        GroupMember(device_switch_1.ieee, 1),
        GroupMember(device_switch_2.ieee, 1),
    ]

    # test creating a group with 2 members
    zha_group = await zha_gateway.async_create_zigpy_group(
        "Test Group", members)
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 2
    for member in zha_group.members:
        assert member.device.ieee in member_ieee_addresses
        assert member.group == zha_group
        assert member.endpoint is not None

    entity_id = async_find_group_entity_id(hass, Platform.SWITCH, zha_group)
    assert hass.states.get(entity_id) is not None

    group_cluster_on_off = zha_group.endpoint[general.OnOff.cluster_id]
    dev1_cluster_on_off = device_switch_1.device.endpoints[1].on_off
    dev2_cluster_on_off = device_switch_2.device.endpoints[1].on_off

    await async_enable_traffic(hass, [device_switch_1, device_switch_2],
                               enabled=False)
    await async_wait_for_updates(hass)

    # test that the lights were created and that they are off
    assert hass.states.get(entity_id).state == STATE_UNAVAILABLE

    # allow traffic to flow through the gateway and device
    await async_enable_traffic(hass, [device_switch_1, device_switch_2])
    await async_wait_for_updates(hass)

    # test that the lights were created and are off
    assert hass.states.get(entity_id).state == STATE_OFF

    # turn on from HA
    with patch(
            "zigpy.zcl.Cluster.request",
            return_value=mock_coro([0x00, zcl_f.Status.SUCCESS]),
    ):
        # turn on via UI
        await hass.services.async_call(SWITCH_DOMAIN,
                                       "turn_on", {"entity_id": entity_id},
                                       blocking=True)
        assert len(group_cluster_on_off.request.mock_calls) == 1
        assert group_cluster_on_off.request.call_args == call(
            False,
            ON,
            group_cluster_on_off.commands_by_name["on"].schema,
            expect_reply=True,
            manufacturer=None,
            tries=1,
            tsn=None,
        )
    assert hass.states.get(entity_id).state == STATE_ON

    # turn off from HA
    with patch(
            "zigpy.zcl.Cluster.request",
            return_value=mock_coro([0x01, zcl_f.Status.SUCCESS]),
    ):
        # turn off via UI
        await hass.services.async_call(SWITCH_DOMAIN,
                                       "turn_off", {"entity_id": entity_id},
                                       blocking=True)
        assert len(group_cluster_on_off.request.mock_calls) == 1
        assert group_cluster_on_off.request.call_args == call(
            False,
            OFF,
            group_cluster_on_off.commands_by_name["off"].schema,
            expect_reply=True,
            manufacturer=None,
            tries=1,
            tsn=None,
        )
    assert hass.states.get(entity_id).state == STATE_OFF

    # test some of the group logic to make sure we key off states correctly
    await send_attributes_report(hass, dev1_cluster_on_off, {0: 1})
    await send_attributes_report(hass, dev2_cluster_on_off, {0: 1})
    await async_wait_for_updates(hass)

    # test that group light is on
    assert hass.states.get(entity_id).state == STATE_ON

    await send_attributes_report(hass, dev1_cluster_on_off, {0: 0})
    await async_wait_for_updates(hass)

    # test that group light is still on
    assert hass.states.get(entity_id).state == STATE_ON

    await send_attributes_report(hass, dev2_cluster_on_off, {0: 0})
    await async_wait_for_updates(hass)

    # test that group light is now off
    assert hass.states.get(entity_id).state == STATE_OFF

    await send_attributes_report(hass, dev1_cluster_on_off, {0: 1})
    await async_wait_for_updates(hass)

    # test that group light is now back on
    assert hass.states.get(entity_id).state == STATE_ON
Esempio n. 6
0
async def test_zha_group_fan_entity(hass, device_fan_1, device_fan_2,
                                    coordinator):
    """Test the fan entity for a ZHA group."""
    zha_gateway = get_zha_gateway(hass)
    assert zha_gateway is not None
    zha_gateway.coordinator_zha_device = coordinator
    coordinator._zha_gateway = zha_gateway
    device_fan_1._zha_gateway = zha_gateway
    device_fan_2._zha_gateway = zha_gateway
    member_ieee_addresses = [device_fan_1.ieee, device_fan_2.ieee]
    members = [
        GroupMember(device_fan_1.ieee, 1),
        GroupMember(device_fan_2.ieee, 1)
    ]

    # test creating a group with 2 members
    zha_group = await zha_gateway.async_create_zigpy_group(
        "Test Group", members)
    await hass.async_block_till_done()

    assert zha_group is not None
    assert len(zha_group.members) == 2
    for member in zha_group.members:
        assert member.device.ieee in member_ieee_addresses
        assert member.group == zha_group
        assert member.endpoint is not None

    entity_domains = GROUP_PROBE.determine_entity_domains(hass, zha_group)
    assert len(entity_domains) == 2

    assert LIGHT_DOMAIN in entity_domains
    assert DOMAIN in entity_domains

    entity_id = async_find_group_entity_id(hass, DOMAIN, zha_group)
    assert hass.states.get(entity_id) is not None

    group_fan_cluster = zha_group.endpoint[hvac.Fan.cluster_id]

    dev1_fan_cluster = device_fan_1.device.endpoints[1].fan
    dev2_fan_cluster = device_fan_2.device.endpoints[1].fan

    await async_enable_traffic(hass, [device_fan_1, device_fan_2],
                               enabled=False)
    await hass.async_block_till_done()
    # test that the fans were created and that they are unavailable
    assert hass.states.get(entity_id).state == STATE_UNAVAILABLE

    # allow traffic to flow through the gateway and device
    await async_enable_traffic(hass, [device_fan_1, device_fan_2])

    # test that the fan group entity was created and is off
    assert hass.states.get(entity_id).state == STATE_OFF

    # turn on from HA
    group_fan_cluster.write_attributes.reset_mock()
    await async_turn_on(hass, entity_id)
    await hass.async_block_till_done()
    assert len(group_fan_cluster.write_attributes.mock_calls) == 1
    assert group_fan_cluster.write_attributes.call_args[0][0] == {
        "fan_mode": 2
    }

    # turn off from HA
    group_fan_cluster.write_attributes.reset_mock()
    await async_turn_off(hass, entity_id)
    assert len(group_fan_cluster.write_attributes.mock_calls) == 1
    assert group_fan_cluster.write_attributes.call_args[0][0] == {
        "fan_mode": 0
    }

    # change speed from HA
    group_fan_cluster.write_attributes.reset_mock()
    await async_set_speed(hass, entity_id, speed=fan.SPEED_HIGH)
    assert len(group_fan_cluster.write_attributes.mock_calls) == 1
    assert group_fan_cluster.write_attributes.call_args[0][0] == {
        "fan_mode": 3
    }

    # test some of the group logic to make sure we key off states correctly
    await send_attributes_report(hass, dev1_fan_cluster, {0: 0})
    await send_attributes_report(hass, dev2_fan_cluster, {0: 0})

    # test that group fan is off
    assert hass.states.get(entity_id).state == STATE_OFF

    await send_attributes_report(hass, dev2_fan_cluster, {0: 2})
    await hass.async_block_till_done()

    # test that group fan is speed medium
    assert hass.states.get(entity_id).state == STATE_ON

    await send_attributes_report(hass, dev2_fan_cluster, {0: 0})
    await hass.async_block_till_done()

    # test that group fan is now off
    assert hass.states.get(entity_id).state == STATE_OFF