Add Neighbors & Endpoint Names to zha/devices reply (#40748)

* Add Neighbors & Endpoint Names to zha/devices reply.

* Remove unused const

* Add tests & correct const name.

* Change tests to use corresponding enum device_type
This commit is contained in:
Samantha 2020-09-29 20:25:05 +01:00 committed by GitHub
parent a2d2b7842d
commit a8b68dc4f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 97 additions and 24 deletions

View file

@ -35,6 +35,7 @@ ATTR_COMMAND_TYPE = "command_type"
ATTR_DEVICE_IEEE = "device_ieee"
ATTR_DEVICE_TYPE = "device_type"
ATTR_ENDPOINTS = "endpoints"
ATTR_ENDPOINT_NAMES = "endpoint_names"
ATTR_ENDPOINT_ID = "endpoint_id"
ATTR_IEEE = "ieee"
ATTR_IN_CLUSTERS = "in_clusters"
@ -46,6 +47,7 @@ ATTR_MANUFACTURER_CODE = "manufacturer_code"
ATTR_MEMBERS = "members"
ATTR_MODEL = "model"
ATTR_NAME = "name"
ATTR_NEIGHBORS = "neighbors"
ATTR_NODE_DESCRIPTOR = "node_descriptor"
ATTR_NWK = "nwk"
ATTR_OUT_CLUSTERS = "out_clusters"

View file

@ -33,6 +33,7 @@ from .const import (
ATTR_DEVICE_IEEE,
ATTR_DEVICE_TYPE,
ATTR_ENDPOINT_ID,
ATTR_ENDPOINT_NAMES,
ATTR_ENDPOINTS,
ATTR_IEEE,
ATTR_LAST_SEEN,
@ -41,6 +42,7 @@ from .const import (
ATTR_MANUFACTURER_CODE,
ATTR_MODEL,
ATTR_NAME,
ATTR_NEIGHBORS,
ATTR_NODE_DESCRIPTOR,
ATTR_NWK,
ATTR_POWER_SOURCE,
@ -436,6 +438,46 @@ class ZHADevice(LogMixin):
}
for entity_ref in self.gateway.device_registry[self.ieee]
]
# Return the neighbor information
device_info[ATTR_NEIGHBORS] = [
{
"device_type": neighbor.neighbor.device_type.name,
"rx_on_when_idle": neighbor.neighbor.rx_on_when_idle.name,
"relationship": neighbor.neighbor.relationship.name,
"extended_pan_id": str(neighbor.neighbor.extended_pan_id),
"ieee": str(neighbor.neighbor.ieee),
"nwk": str(neighbor.neighbor.nwk),
"permit_joining": neighbor.neighbor.permit_joining.name,
"depth": str(neighbor.neighbor.depth),
"lqi": str(neighbor.neighbor.lqi),
}
for neighbor in self._zigpy_device.neighbors
]
# Return endpoint device type Names
try:
device_info[ATTR_ENDPOINT_NAMES] = [
{
"name": endpoint.device_type.name,
}
for (ep_id, endpoint) in self._zigpy_device.endpoints.items()
if ep_id != 0
and endpoint.profile_id in (zha.PROFILE_ID, zll.PROFILE_ID)
]
except AttributeError as ex:
# Some device types are not using an enumeration
self.warning(
"Failed to identify endpoint name in '%s' with exception '%s'",
self._zigpy_device.endpoints.items(),
ex,
)
device_info[ATTR_ENDPOINT_NAMES] = [
{
"name": "unknown",
}
]
reg_device = self.gateway.ha_device_registry.async_get(self.device_id)
if reg_device is not None:
device_info["user_given_name"] = reg_device.name_by_user

View file

@ -108,6 +108,7 @@ class FakeDevice:
if node_desc is None:
node_desc = b"\x02@\x807\x10\x7fd\x00\x00*d\x00\x00"
self.node_desc = zigpy.zdo.types.NodeDescriptor.deserialize(node_desc)[0]
self.neighbors = []
FakeDevice.add_to_group = zigpy_dev.add_to_group

View file

@ -23,10 +23,12 @@ from homeassistant.components.zha.core.const import (
ATTR_CLUSTER_ID,
ATTR_CLUSTER_TYPE,
ATTR_ENDPOINT_ID,
ATTR_ENDPOINT_NAMES,
ATTR_IEEE,
ATTR_MANUFACTURER,
ATTR_MODEL,
ATTR_NAME,
ATTR_NEIGHBORS,
ATTR_QUIRK_APPLIED,
CLUSTER_TYPE_IN,
DATA_ZHA,
@ -184,6 +186,8 @@ async def test_list_devices(zha_client):
assert device[ATTR_NAME] is not None
assert device[ATTR_QUIRK_APPLIED] is not None
assert device["entities"] is not None
assert device[ATTR_NEIGHBORS] is not None
assert device[ATTR_ENDPOINT_NAMES] is not None
for entity_reference in device["entities"]:
assert entity_reference[ATTR_NAME] is not None

View file

@ -1,5 +1,6 @@
"""Test zha binary sensor."""
import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.measurement as measurement
import zigpy.zcl.clusters.security as security
@ -15,7 +16,7 @@ from .common import (
DEVICE_IAS = {
1: {
"device_type": 1026,
"device_type": zigpy.profiles.zha.DeviceType.IAS_ZONE,
"in_clusters": [security.IasZone.cluster_id],
"out_clusters": [],
}
@ -24,7 +25,7 @@ DEVICE_IAS = {
DEVICE_OCCUPANCY = {
1: {
"device_type": 263,
"device_type": zigpy.profiles.zha.DeviceType.OCCUPANCY_SENSOR,
"in_clusters": [measurement.OccupancySensing.cluster_id],
"out_clusters": [],
}

View file

@ -3,6 +3,7 @@ import asyncio
from unittest import mock
import pytest
import zigpy.profiles.zha
import zigpy.types as t
import zigpy.zcl.clusters
@ -286,7 +287,11 @@ def test_ep_channels_all_channels(m1, zha_device_mock):
"""Test EndpointChannels adding all channels."""
zha_device = zha_device_mock(
{
1: {"in_clusters": [0, 1, 6, 8], "out_clusters": [], "device_type": 0x0000},
1: {
"in_clusters": [0, 1, 6, 8],
"out_clusters": [],
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
},
2: {
"in_clusters": [0, 1, 6, 8, 768],
"out_clusters": [],

View file

@ -2,6 +2,7 @@
import asyncio
import pytest
import zigpy.profiles.zha
import zigpy.types
import zigpy.zcl.clusters.closures as closures
import zigpy.zcl.clusters.general as general
@ -41,7 +42,7 @@ def zigpy_cover_device(zigpy_device_mock):
endpoints = {
1: {
"device_type": 1026,
"device_type": zigpy.profiles.zha.DeviceType.IAS_ZONE,
"in_clusters": [closures.WindowCovering.cluster_id],
"out_clusters": [],
}
@ -55,7 +56,7 @@ def zigpy_cover_remote(zigpy_device_mock):
endpoints = {
1: {
"device_type": 0x0203,
"device_type": zigpy.profiles.zha.DeviceType.WINDOW_COVERING_CONTROLLER,
"in_clusters": [],
"out_clusters": [closures.WindowCovering.cluster_id],
}
@ -69,7 +70,7 @@ def zigpy_shade_device(zigpy_device_mock):
endpoints = {
1: {
"device_type": 512,
"device_type": zigpy.profiles.zha.DeviceType.SHADE,
"in_clusters": [
closures.Shade.cluster_id,
general.LevelControl.cluster_id,
@ -87,7 +88,7 @@ def zigpy_keen_vent(zigpy_device_mock):
endpoints = {
1: {
"device_type": 3,
"device_type": zigpy.profiles.zha.DeviceType.LEVEL_CONTROLLABLE_OUTPUT,
"in_clusters": [general.LevelControl.cluster_id, general.OnOff.cluster_id],
"out_clusters": [],
}

View file

@ -4,6 +4,7 @@ import time
from unittest import mock
import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.general as general
import homeassistant.components.zha.core.device as zha_core_device
@ -27,7 +28,11 @@ def zigpy_device(zigpy_device_mock):
in_clusters.append(general.Basic.cluster_id)
endpoints = {
3: {"in_clusters": in_clusters, "out_clusters": [], "device_type": 0}
3: {
"in_clusters": in_clusters,
"out_clusters": [],
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
return zigpy_device_mock(endpoints)
@ -44,7 +49,11 @@ def zigpy_device_mains(zigpy_device_mock):
in_clusters.append(general.Basic.cluster_id)
endpoints = {
3: {"in_clusters": in_clusters, "out_clusters": [], "device_type": 0}
3: {
"in_clusters": in_clusters,
"out_clusters": [],
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
return zigpy_device_mock(
endpoints, node_descriptor=b"\x02@\x84_\x11\x7fd\x00\x00,d\x00\x00"

View file

@ -2,6 +2,7 @@
from unittest.mock import patch
import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.general as general
import zigpy.zcl.clusters.security as security
import zigpy.zcl.foundation as zcl_f
@ -31,7 +32,7 @@ async def device_ias(hass, zigpy_device_mock, zha_device_joined_restored):
1: {
"in_clusters": [c.cluster_id for c in clusters],
"out_clusters": [general.OnOff.cluster_id],
"device_type": 0,
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
},
)

View file

@ -3,6 +3,7 @@ from datetime import timedelta
import time
import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.general as general
import homeassistant.components.automation as automation
@ -58,7 +59,7 @@ async def mock_devices(hass, zigpy_device_mock, zha_device_joined_restored):
1: {
"in_clusters": [general.Basic.cluster_id],
"out_clusters": [general.OnOff.cluster_id],
"device_type": 0,
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
)

View file

@ -4,6 +4,7 @@ import re
from unittest import mock
import pytest
import zigpy.profiles.zha
import zigpy.quirks
import zigpy.types
import zigpy.zcl.clusters.closures
@ -163,9 +164,9 @@ def test_discover_entities(m1, m2):
@pytest.mark.parametrize(
"device_type, component, hit",
[
(0x0100, zha_const.LIGHT, True),
(0x0108, zha_const.SWITCH, True),
(0x0051, zha_const.SWITCH, True),
(zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT, zha_const.LIGHT, True),
(zigpy.profiles.zha.DeviceType.ON_OFF_BALLAST, zha_const.SWITCH, True),
(zigpy.profiles.zha.DeviceType.SMART_PLUG, zha_const.SWITCH, True),
(0xFFFF, None, False),
],
)
@ -379,7 +380,7 @@ async def test_device_override(
zigpy_device = zigpy_device_mock(
{
1: {
"device_type": 258,
"device_type": zigpy.profiles.zha.DeviceType.COLOR_DIMMABLE_LIGHT,
"endpoint_id": 1,
"in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 64513],
"out_clusters": [25],

View file

@ -43,7 +43,11 @@ IEEE_GROUPABLE_DEVICE2 = "02:2d:6f:00:0a:90:69:e8"
def zigpy_device(zigpy_device_mock):
"""Device tracker zigpy device."""
endpoints = {
1: {"in_clusters": [hvac.Fan.cluster_id], "out_clusters": [], "device_type": 0}
1: {
"in_clusters": [hvac.Fan.cluster_id],
"out_clusters": [],
"device_type": zha.DeviceType.ON_OFF_SWITCH,
}
}
return zigpy_device_mock(endpoints)

View file

@ -28,7 +28,7 @@ def zigpy_dev_basic(zigpy_device_mock):
1: {
"in_clusters": [general.Basic.cluster_id],
"out_clusters": [],
"device_type": 0,
"device_type": zha.DeviceType.ON_OFF_SWITCH,
}
}
)

View file

@ -34,7 +34,7 @@ IEEE_GROUPABLE_DEVICE3 = "03:2d:6f:00:0a:90:69:e7"
LIGHT_ON_OFF = {
1: {
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT,
"device_type": zha.DeviceType.ON_OFF_LIGHT,
"in_clusters": [
general.Basic.cluster_id,
general.Identify.cluster_id,
@ -46,7 +46,7 @@ LIGHT_ON_OFF = {
LIGHT_LEVEL = {
1: {
"device_type": zigpy.profiles.zha.DeviceType.DIMMABLE_LIGHT,
"device_type": zha.DeviceType.DIMMABLE_LIGHT,
"in_clusters": [
general.Basic.cluster_id,
general.LevelControl.cluster_id,
@ -58,7 +58,7 @@ LIGHT_LEVEL = {
LIGHT_COLOR = {
1: {
"device_type": zigpy.profiles.zha.DeviceType.COLOR_DIMMABLE_LIGHT,
"device_type": zha.DeviceType.COLOR_DIMMABLE_LIGHT,
"in_clusters": [
general.Basic.cluster_id,
general.Identify.cluster_id,

View file

@ -2,6 +2,7 @@
from unittest import mock
import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.general as general
import zigpy.zcl.clusters.homeautomation as homeautomation
import zigpy.zcl.clusters.measurement as measurement
@ -122,7 +123,7 @@ async def test_sensor(
1: {
"in_clusters": [cluster_id, general.Basic.cluster_id],
"out_cluster": [],
"device_type": 0x0000,
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
)
@ -242,7 +243,7 @@ async def test_temp_uom(
general.Basic.cluster_id,
],
"out_cluster": [],
"device_type": 0x0000,
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
)
@ -282,7 +283,7 @@ async def test_electrical_measurement_init(
1: {
"in_clusters": [cluster_id, general.Basic.cluster_id],
"out_cluster": [],
"device_type": 0x0000,
"device_type": zigpy.profiles.zha.DeviceType.ON_OFF_SWITCH,
}
}
)

View file

@ -33,7 +33,7 @@ def zigpy_device(zigpy_device_mock):
1: {
"in_clusters": [general.Basic.cluster_id, general.OnOff.cluster_id],
"out_clusters": [],
"device_type": 0,
"device_type": zha.DeviceType.ON_OFF_SWITCH,
}
}
return zigpy_device_mock(endpoints)