mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Add cluster attr data to ZHA device diagnostics (#70238)
* Add cluster attr data to ZHA device diagnostics * add unsupported attributes and refactor * remove await * make parseable
This commit is contained in:
parent
12c49e1c94
commit
a053a3a8a4
@ -8,6 +8,8 @@ import bellows
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
import zigpy
|
import zigpy
|
||||||
from zigpy.config import CONF_NWK_EXTENDED_PAN_ID
|
from zigpy.config import CONF_NWK_EXTENDED_PAN_ID
|
||||||
|
from zigpy.profiles import PROFILES
|
||||||
|
from zigpy.zcl import Cluster
|
||||||
import zigpy_deconz
|
import zigpy_deconz
|
||||||
import zigpy_xbee
|
import zigpy_xbee
|
||||||
import zigpy_zigate
|
import zigpy_zigate
|
||||||
@ -15,11 +17,24 @@ import zigpy_znp
|
|||||||
|
|
||||||
from homeassistant.components.diagnostics.util import async_redact_data
|
from homeassistant.components.diagnostics.util import async_redact_data
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_UNIQUE_ID
|
from homeassistant.const import CONF_ID, CONF_NAME, CONF_UNIQUE_ID
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
|
||||||
from .core.const import ATTR_IEEE, DATA_ZHA, DATA_ZHA_CONFIG, DATA_ZHA_GATEWAY
|
from .core.const import (
|
||||||
|
ATTR_ATTRIBUTE_NAME,
|
||||||
|
ATTR_DEVICE_TYPE,
|
||||||
|
ATTR_IEEE,
|
||||||
|
ATTR_IN_CLUSTERS,
|
||||||
|
ATTR_OUT_CLUSTERS,
|
||||||
|
ATTR_PROFILE_ID,
|
||||||
|
ATTR_VALUE,
|
||||||
|
CONF_ALARM_MASTER_CODE,
|
||||||
|
DATA_ZHA,
|
||||||
|
DATA_ZHA_CONFIG,
|
||||||
|
DATA_ZHA_GATEWAY,
|
||||||
|
UNKNOWN,
|
||||||
|
)
|
||||||
from .core.device import ZHADevice
|
from .core.device import ZHADevice
|
||||||
from .core.gateway import ZHAGateway
|
from .core.gateway import ZHAGateway
|
||||||
from .core.helpers import async_get_zha_device
|
from .core.helpers import async_get_zha_device
|
||||||
@ -27,11 +42,16 @@ from .core.helpers import async_get_zha_device
|
|||||||
KEYS_TO_REDACT = {
|
KEYS_TO_REDACT = {
|
||||||
ATTR_IEEE,
|
ATTR_IEEE,
|
||||||
CONF_UNIQUE_ID,
|
CONF_UNIQUE_ID,
|
||||||
|
CONF_ALARM_MASTER_CODE,
|
||||||
"network_key",
|
"network_key",
|
||||||
CONF_NWK_EXTENDED_PAN_ID,
|
CONF_NWK_EXTENDED_PAN_ID,
|
||||||
"partner_ieee",
|
"partner_ieee",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ATTRIBUTES = "attributes"
|
||||||
|
CLUSTER_DETAILS = "cluster_details"
|
||||||
|
UNSUPPORTED_ATTRIBUTES = "unsupported_attributes"
|
||||||
|
|
||||||
|
|
||||||
def shallow_asdict(obj: Any) -> dict:
|
def shallow_asdict(obj: Any) -> dict:
|
||||||
"""Return a shallow copy of a dataclass as a dict."""
|
"""Return a shallow copy of a dataclass as a dict."""
|
||||||
@ -77,4 +97,62 @@ async def async_get_device_diagnostics(
|
|||||||
) -> dict:
|
) -> dict:
|
||||||
"""Return diagnostics for a device."""
|
"""Return diagnostics for a device."""
|
||||||
zha_device: ZHADevice = async_get_zha_device(hass, device.id)
|
zha_device: ZHADevice = async_get_zha_device(hass, device.id)
|
||||||
return async_redact_data(zha_device.zha_device_info, KEYS_TO_REDACT)
|
device_info: dict[str, Any] = zha_device.zha_device_info
|
||||||
|
device_info[CLUSTER_DETAILS] = get_endpoint_cluster_attr_data(zha_device)
|
||||||
|
return async_redact_data(device_info, KEYS_TO_REDACT)
|
||||||
|
|
||||||
|
|
||||||
|
def get_endpoint_cluster_attr_data(zha_device: ZHADevice) -> dict:
|
||||||
|
"""Return endpoint cluster attribute data."""
|
||||||
|
cluster_details = {}
|
||||||
|
for ep_id, endpoint in zha_device.device.endpoints.items():
|
||||||
|
if ep_id == 0:
|
||||||
|
continue
|
||||||
|
endpoint_key = (
|
||||||
|
f"{PROFILES.get(endpoint.profile_id).DeviceType(endpoint.device_type).name}"
|
||||||
|
if PROFILES.get(endpoint.profile_id) is not None
|
||||||
|
and endpoint.device_type is not None
|
||||||
|
else UNKNOWN
|
||||||
|
)
|
||||||
|
cluster_details[ep_id] = {
|
||||||
|
ATTR_DEVICE_TYPE: {
|
||||||
|
CONF_NAME: endpoint_key,
|
||||||
|
CONF_ID: endpoint.device_type,
|
||||||
|
},
|
||||||
|
ATTR_PROFILE_ID: endpoint.profile_id,
|
||||||
|
ATTR_IN_CLUSTERS: {
|
||||||
|
f"0x{cluster_id:04x}": {
|
||||||
|
"endpoint_attribute": cluster.ep_attribute,
|
||||||
|
**get_cluster_attr_data(cluster),
|
||||||
|
}
|
||||||
|
for cluster_id, cluster in endpoint.in_clusters.items()
|
||||||
|
},
|
||||||
|
ATTR_OUT_CLUSTERS: {
|
||||||
|
f"0x{cluster_id:04x}": {
|
||||||
|
"endpoint_attribute": cluster.ep_attribute,
|
||||||
|
**get_cluster_attr_data(cluster),
|
||||||
|
}
|
||||||
|
for cluster_id, cluster in endpoint.out_clusters.items()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return cluster_details
|
||||||
|
|
||||||
|
|
||||||
|
def get_cluster_attr_data(cluster: Cluster) -> dict:
|
||||||
|
"""Return cluster attribute data."""
|
||||||
|
return {
|
||||||
|
ATTRIBUTES: {
|
||||||
|
f"0x{attr_id:04x}": {
|
||||||
|
ATTR_ATTRIBUTE_NAME: attr_def.name,
|
||||||
|
ATTR_VALUE: attr_value,
|
||||||
|
}
|
||||||
|
for attr_id, attr_def in cluster.attributes.items()
|
||||||
|
if (attr_value := cluster.get(attr_def.name)) is not None
|
||||||
|
},
|
||||||
|
UNSUPPORTED_ATTRIBUTES: {
|
||||||
|
f"0x{cluster.find_attribute(u_attr).id:04x}": {
|
||||||
|
ATTR_ATTRIBUTE_NAME: cluster.find_attribute(u_attr).name
|
||||||
|
}
|
||||||
|
for u_attr in cluster.unsupported_attributes
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user