Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions zha/zigbee/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,51 @@ def _discover_new_entities(self) -> None:
entity.on_add()
self._pending_entities.append(entity)

@staticmethod
def _entity_class_path(entity: BaseEntity) -> tuple[str, str]:
"""Return module and class name for an entity."""
return (entity.__class__.__module__, entity.__class__.__name__)

@staticmethod
def _entity_endpoint_id(entity: BaseEntity) -> int | None:
"""Return endpoint id if this is a platform entity."""
if not isinstance(entity, PlatformEntity):
return None
return entity.endpoint.id

@staticmethod
def _entity_cluster_handler_names(entity: BaseEntity) -> list[str]:
"""Return cluster handler names if this is a platform entity."""
if not isinstance(entity, PlatformEntity):
return []
return sorted(entity.cluster_handlers.keys())

def _log_entity_unique_id_conflict(
self,
key: tuple[Platform, str],
existing_entity: BaseEntity,
duplicate_entity: BaseEntity,
) -> None:
"""Log duplicate unique_id collisions when classes differ."""
existing_class = self._entity_class_path(existing_entity)
duplicate_class = self._entity_class_path(duplicate_entity)
if existing_class == duplicate_class:
return

_LOGGER.warning(
"Entity unique_id conflict on device %s for %s: keeping %s "
"(endpoint=%s, cluster_handlers=%s), dropping %s "
"(endpoint=%s, cluster_handlers=%s)",
self.ieee,
key,
".".join(existing_class),
self._entity_endpoint_id(existing_entity),
self._entity_cluster_handler_names(existing_entity),
".".join(duplicate_class),
self._entity_endpoint_id(duplicate_entity),
self._entity_cluster_handler_names(duplicate_entity),
)

async def async_initialize(self, from_cache: bool = False) -> None:
"""Initialize cluster handlers."""
self.debug("started initialization")
Expand Down Expand Up @@ -1012,6 +1057,7 @@ async def async_initialize(self, from_cache: bool = False) -> None:

# Ignore entities that already exist
if key in new_entities:
self._log_entity_unique_id_conflict(key, new_entities[key], entity)
await entity.on_remove()
continue

Expand Down
Loading