Skip to content

Commit

Permalink
Fix invalid uniqueness constraint on unique_id (#159)
Browse files Browse the repository at this point in the history
* Fix invalid uniqueness constraint on unique_id

* remove magic #
  • Loading branch information
dmulcahey authored Aug 10, 2024
1 parent 77e4094 commit 584e56b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 23 deletions.
3 changes: 2 additions & 1 deletion tests/test_alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import zigpy.zcl.foundation as zcl_f

from tests.conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE
from zha.application import Platform
from zha.application.gateway import Gateway
from zha.application.platforms.alarm_control_panel import AlarmControlPanel
from zha.application.platforms.alarm_control_panel.const import AlarmState
Expand Down Expand Up @@ -49,7 +50,7 @@ async def test_alarm_control_panel(
zha_device: Device = await device_joined(zigpy_device)
cluster: security.IasAce = zigpy_device.endpoints.get(1).ias_ace
alarm_entity: AlarmControlPanel = zha_device.platform_entities.get(
"00:0d:6f:00:0a:90:69:e7-1"
(Platform.ALARM_CONTROL_PANEL, "00:0d:6f:00:0a:90:69:e7-1")
)
assert alarm_entity is not None
assert isinstance(alarm_entity, AlarmControlPanel)
Expand Down
43 changes: 34 additions & 9 deletions tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import zigpy.zdo.types as zdo_t

from tests.conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_TYPE
from zha.application import Platform
from zha.application.const import (
CLUSTER_COMMAND_SERVER,
CLUSTER_COMMANDS_CLIENT,
Expand Down Expand Up @@ -766,27 +767,51 @@ async def test_device_properties(
assert zha_device.sw_version is None

assert len(zha_device.platform_entities) == 3
assert "00:0d:6f:00:0a:90:69:e7-3-0-lqi" in zha_device.platform_entities
assert "00:0d:6f:00:0a:90:69:e7-3-0-rssi" in zha_device.platform_entities
assert "00:0d:6f:00:0a:90:69:e7-3-6" in zha_device.platform_entities
assert (
Platform.SENSOR,
"00:0d:6f:00:0a:90:69:e7-3-0-lqi",
) in zha_device.platform_entities
assert (
Platform.SENSOR,
"00:0d:6f:00:0a:90:69:e7-3-0-rssi",
) in zha_device.platform_entities
assert (
Platform.SWITCH,
"00:0d:6f:00:0a:90:69:e7-3-6",
) in zha_device.platform_entities

assert isinstance(
zha_device.platform_entities["00:0d:6f:00:0a:90:69:e7-3-0-lqi"], LQISensor
zha_device.platform_entities[
(Platform.SENSOR, "00:0d:6f:00:0a:90:69:e7-3-0-lqi")
],
LQISensor,
)
assert isinstance(
zha_device.platform_entities["00:0d:6f:00:0a:90:69:e7-3-0-rssi"], RSSISensor
zha_device.platform_entities[
(Platform.SENSOR, "00:0d:6f:00:0a:90:69:e7-3-0-rssi")
],
RSSISensor,
)
assert isinstance(
zha_device.platform_entities["00:0d:6f:00:0a:90:69:e7-3-6"], Switch
zha_device.platform_entities[(Platform.SWITCH, "00:0d:6f:00:0a:90:69:e7-3-6")],
Switch,
)

assert zha_device.get_platform_entity("00:0d:6f:00:0a:90:69:e7-3-0-lqi") is not None
assert (
zha_device.get_platform_entity(
Platform.SENSOR, "00:0d:6f:00:0a:90:69:e7-3-0-lqi"
)
is not None
)
assert isinstance(
zha_device.get_platform_entity("00:0d:6f:00:0a:90:69:e7-3-0-lqi"), LQISensor
zha_device.get_platform_entity(
Platform.SENSOR, "00:0d:6f:00:0a:90:69:e7-3-0-lqi"
),
LQISensor,
)

with pytest.raises(KeyError, match="Entity foo not found"):
zha_device.get_platform_entity("foo")
zha_device.get_platform_entity("bar", "foo")

# test things are none when they aren't returned by Zigpy
zigpy_dev.node_desc = None
Expand Down
8 changes: 4 additions & 4 deletions zha/application/platforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,14 @@ def __init__(
self._device: Device = device
self._endpoint = endpoint
# we double create these in discovery tests because we reissue the create calls to count and prove them out
if self.unique_id not in self._device.platform_entities:
self._device.platform_entities[self.unique_id] = self
if (self.PLATFORM, self.unique_id) not in self._device.platform_entities:
self._device.platform_entities[(self.PLATFORM, self.unique_id)] = self
else:
_LOGGER.debug(
"Not registering entity %r, unique id %r already exists: %r",
self,
self.unique_id,
self._device.platform_entities[self.unique_id],
(self.PLATFORM, self.unique_id),
self._device.platform_entities[(self.PLATFORM, self.unique_id)],
)

@classmethod
Expand Down
4 changes: 2 additions & 2 deletions zha/application/platforms/sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,8 @@ def __init__(
self._device.gateway.global_updater.register_update_listener(self.update)

# we double create these in discovery tests because we reissue the create calls to count and prove them out
if self.unique_id not in self._device.platform_entities:
self._device.platform_entities[self.unique_id] = self
if (self.PLATFORM, self.unique_id) not in self._device.platform_entities:
self._device.platform_entities[(self.PLATFORM, self.unique_id)] = self

@functools.cached_property
def identifiers(self) -> DeviceCounterSensorIdentifiers:
Expand Down
14 changes: 7 additions & 7 deletions zha/zigbee/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import zigpy.zdo.types as zdo_types
from zigpy.zdo.types import RouteStatus, _NeighborEnums

from zha.application import discovery
from zha.application import Platform, discovery
from zha.application.const import (
ATTR_ARGS,
ATTR_ATTRIBUTE,
Expand Down Expand Up @@ -233,7 +233,7 @@ def __init__(
self._checkins_missed_count: int = 0
self._on_network: bool = True

self._platform_entities: dict[str, PlatformEntity] = {}
self._platform_entities: dict[tuple[Platform, str], PlatformEntity] = {}
self.semaphore: asyncio.Semaphore = asyncio.Semaphore(3)
self._zdo_handler: ZDOClusterHandler = ZDOClusterHandler(self)
self.status: DeviceStatus = DeviceStatus.CREATED
Expand Down Expand Up @@ -494,13 +494,13 @@ def sw_version(self, sw_build_id: int) -> None:
self._sw_build_id = sw_build_id

@property
def platform_entities(self) -> dict[str, PlatformEntity]:
def platform_entities(self) -> dict[tuple[Platform, str], PlatformEntity]:
"""Return the platform entities for this device."""
return self._platform_entities

def get_platform_entity(self, unique_id: str) -> PlatformEntity:
def get_platform_entity(self, platform: Platform, unique_id: str) -> PlatformEntity:
"""Get a platform entity by unique id."""
entity = self._platform_entities.get(unique_id)
entity = self._platform_entities.get((platform, unique_id))
if entity is None:
raise KeyError(f"Entity {unique_id} not found")
return entity
Expand Down Expand Up @@ -672,8 +672,8 @@ def extended_device_info(self) -> ExtendedDeviceInfo:
**self.device_info.__dict__,
active_coordinator=self.is_active_coordinator,
entities={
unique_id: platform_entity.info_object
for unique_id, platform_entity in self.platform_entities.items()
platform_entity.unique_id: platform_entity.info_object
for platform_entity in self.platform_entities.values()
},
neighbors=[
NeighborInfo(
Expand Down

0 comments on commit 584e56b

Please sign in to comment.