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:
parent
a2d2b7842d
commit
a8b68dc4f9
16 changed files with 97 additions and 24 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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": [],
|
||||
}
|
||||
|
|
|
@ -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": [],
|
||||
|
|
|
@ -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": [],
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue