Update ZHA to support zigpy 0.34.0 device initialization (#52610)

* Handle `None` node descriptors

* Skip loading uninitialized devices

* Fix unit test incorrectly handling unset cluster `ep_attribute`

* Revert filtering devices by status during startup
This commit is contained in:
puddly 2021-07-13 13:31:17 -04:00 committed by GitHub
parent 7aaa08f153
commit 987c7a289a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 22 deletions

View file

@ -183,11 +183,12 @@ class ZHADevice(LogMixin):
return self._zigpy_device.model return self._zigpy_device.model
@property @property
def manufacturer_code(self): def manufacturer_code(self) -> int | None:
"""Return the manufacturer code for the device.""" """Return the manufacturer code for the device."""
if self._zigpy_device.node_desc.is_valid: if self._zigpy_device.node_desc is None:
return self._zigpy_device.node_desc.manufacturer_code return None
return None
return self._zigpy_device.node_desc.manufacturer_code
@property @property
def nwk(self): def nwk(self):
@ -210,17 +211,20 @@ class ZHADevice(LogMixin):
return self._zigpy_device.last_seen return self._zigpy_device.last_seen
@property @property
def is_mains_powered(self): def is_mains_powered(self) -> bool | None:
"""Return true if device is mains powered.""" """Return true if device is mains powered."""
if self._zigpy_device.node_desc is None:
return None
return self._zigpy_device.node_desc.is_mains_powered return self._zigpy_device.node_desc.is_mains_powered
@property @property
def device_type(self): def device_type(self) -> str:
"""Return the logical device type for the device.""" """Return the logical device type for the device."""
node_descriptor = self._zigpy_device.node_desc if self._zigpy_device.node_desc is None:
return ( return UNKNOWN
node_descriptor.logical_type.name if node_descriptor.is_valid else UNKNOWN
) return self._zigpy_device.node_desc.logical_type.name
@property @property
def power_source(self): def power_source(self):
@ -230,18 +234,27 @@ class ZHADevice(LogMixin):
) )
@property @property
def is_router(self): def is_router(self) -> bool | None:
"""Return true if this is a routing capable device.""" """Return true if this is a routing capable device."""
if self._zigpy_device.node_desc is None:
return None
return self._zigpy_device.node_desc.is_router return self._zigpy_device.node_desc.is_router
@property @property
def is_coordinator(self): def is_coordinator(self) -> bool | None:
"""Return true if this device represents the coordinator.""" """Return true if this device represents the coordinator."""
if self._zigpy_device.node_desc is None:
return None
return self._zigpy_device.node_desc.is_coordinator return self._zigpy_device.node_desc.is_coordinator
@property @property
def is_end_device(self): def is_end_device(self) -> bool | None:
"""Return true if this device is an end device.""" """Return true if this device is an end device."""
if self._zigpy_device.node_desc is None:
return None
return self._zigpy_device.node_desc.is_end_device return self._zigpy_device.node_desc.is_end_device
@property @property

View file

@ -3,8 +3,8 @@ import asyncio
import time import time
from unittest.mock import AsyncMock, Mock from unittest.mock import AsyncMock, Mock
from zigpy.device import Device as zigpy_dev import zigpy.device as zigpy_dev
from zigpy.endpoint import Endpoint as zigpy_ep import zigpy.endpoint as zigpy_ep
import zigpy.profiles.zha import zigpy.profiles.zha
import zigpy.types import zigpy.types
import zigpy.zcl import zigpy.zcl
@ -27,7 +27,7 @@ class FakeEndpoint:
self.out_clusters = {} self.out_clusters = {}
self._cluster_attr = {} self._cluster_attr = {}
self.member_of = {} self.member_of = {}
self.status = 1 self.status = zigpy_ep.Status.ZDO_INIT
self.manufacturer = manufacturer self.manufacturer = manufacturer
self.model = model self.model = model
self.profile_id = zigpy.profiles.zha.PROFILE_ID self.profile_id = zigpy.profiles.zha.PROFILE_ID
@ -57,7 +57,7 @@ class FakeEndpoint:
@property @property
def __class__(self): def __class__(self):
"""Fake being Zigpy endpoint.""" """Fake being Zigpy endpoint."""
return zigpy_ep return zigpy_ep.Endpoint
@property @property
def unique_id(self): def unique_id(self):
@ -65,8 +65,8 @@ class FakeEndpoint:
return self.device.ieee, self.endpoint_id return self.device.ieee, self.endpoint_id
FakeEndpoint.add_to_group = zigpy_ep.add_to_group FakeEndpoint.add_to_group = zigpy_ep.Endpoint.add_to_group
FakeEndpoint.remove_from_group = zigpy_ep.remove_from_group FakeEndpoint.remove_from_group = zigpy_ep.Endpoint.remove_from_group
def patch_cluster(cluster): def patch_cluster(cluster):
@ -125,12 +125,11 @@ class FakeDevice:
self.lqi = 255 self.lqi = 255
self.rssi = 8 self.rssi = 8
self.last_seen = time.time() self.last_seen = time.time()
self.status = 2 self.status = zigpy_dev.Status.ENDPOINTS_INIT
self.initializing = False self.initializing = False
self.skip_configuration = False self.skip_configuration = False
self.manufacturer = manufacturer self.manufacturer = manufacturer
self.model = model self.model = model
self.node_desc = zigpy.zdo.types.NodeDescriptor()
self.remove_from_group = AsyncMock() self.remove_from_group = AsyncMock()
if node_desc is None: if node_desc is None:
node_desc = b"\x02@\x807\x10\x7fd\x00\x00*d\x00\x00" node_desc = b"\x02@\x807\x10\x7fd\x00\x00*d\x00\x00"
@ -138,7 +137,7 @@ class FakeDevice:
self.neighbors = [] self.neighbors = []
FakeDevice.add_to_group = zigpy_dev.add_to_group FakeDevice.add_to_group = zigpy_dev.Device.add_to_group
def get_zha_gateway(hass): def get_zha_gateway(hass):