Preserve HomeKit Accessory ID when entity unique id changes (#102123)
This commit is contained in:
parent
433c022687
commit
10fd26df4b
4 changed files with 55 additions and 12 deletions
|
@ -33,9 +33,9 @@ AID_MIN = 2
|
|||
AID_MAX = 18446744073709551615
|
||||
|
||||
|
||||
def get_system_unique_id(entity: er.RegistryEntry) -> str:
|
||||
def get_system_unique_id(entity: er.RegistryEntry, entity_unique_id: str) -> str:
|
||||
"""Determine the system wide unique_id for an entity."""
|
||||
return f"{entity.platform}.{entity.domain}.{entity.unique_id}"
|
||||
return f"{entity.platform}.{entity.domain}.{entity_unique_id}"
|
||||
|
||||
|
||||
def _generate_aids(unique_id: str | None, entity_id: str) -> Generator[int, None, None]:
|
||||
|
@ -72,31 +72,42 @@ class AccessoryAidStorage:
|
|||
self.allocated_aids: set[int] = set()
|
||||
self._entry_id = entry_id
|
||||
self.store: Store | None = None
|
||||
self._entity_registry: er.EntityRegistry | None = None
|
||||
self._entity_registry = er.async_get(hass)
|
||||
|
||||
async def async_initialize(self) -> None:
|
||||
"""Load the latest AID data."""
|
||||
self._entity_registry = er.async_get(self.hass)
|
||||
aidstore = get_aid_storage_filename_for_entry_id(self._entry_id)
|
||||
self.store = Store(self.hass, AID_MANAGER_STORAGE_VERSION, aidstore)
|
||||
|
||||
if not (raw_storage := await self.store.async_load()):
|
||||
# There is no data about aid allocations yet
|
||||
return
|
||||
|
||||
assert isinstance(raw_storage, dict)
|
||||
self.allocations = raw_storage.get(ALLOCATIONS_KEY, {})
|
||||
self.allocated_aids = set(self.allocations.values())
|
||||
|
||||
def get_or_allocate_aid_for_entity_id(self, entity_id: str) -> int:
|
||||
"""Generate a stable aid for an entity id."""
|
||||
assert self._entity_registry is not None
|
||||
if not (entity := self._entity_registry.async_get(entity_id)):
|
||||
if not (entry := self._entity_registry.async_get(entity_id)):
|
||||
return self.get_or_allocate_aid(None, entity_id)
|
||||
|
||||
sys_unique_id = get_system_unique_id(entity)
|
||||
sys_unique_id = get_system_unique_id(entry, entry.unique_id)
|
||||
self._migrate_unique_id_aid_assignment_if_needed(sys_unique_id, entry)
|
||||
return self.get_or_allocate_aid(sys_unique_id, entity_id)
|
||||
|
||||
def _migrate_unique_id_aid_assignment_if_needed(
|
||||
self, sys_unique_id: str, entry: er.RegistryEntry
|
||||
) -> None:
|
||||
"""Migrate the unique id aid assignment if its changed."""
|
||||
if sys_unique_id in self.allocations or not (
|
||||
previous_unique_id := entry.previous_unique_id
|
||||
):
|
||||
return
|
||||
old_sys_unique_id = get_system_unique_id(entry, previous_unique_id)
|
||||
if aid := self.allocations.pop(old_sys_unique_id, None):
|
||||
self.allocations[sys_unique_id] = aid
|
||||
self.async_schedule_save()
|
||||
|
||||
def get_or_allocate_aid(self, unique_id: str | None, entity_id: str) -> int:
|
||||
"""Allocate (and return) a new aid for an accessory."""
|
||||
if unique_id and unique_id in self.allocations:
|
||||
|
|
|
@ -51,7 +51,9 @@ class DeviceTriggerAccessory(HomeAccessory):
|
|||
if (entity_id_or_uuid := trigger.get("entity_id")) and (
|
||||
entry := ent_reg.async_get(entity_id_or_uuid)
|
||||
):
|
||||
unique_id += f"-entity_unique_id:{get_system_unique_id(entry)}"
|
||||
unique_id += (
|
||||
f"-entity_unique_id:{get_system_unique_id(entry, entry.unique_id)}"
|
||||
)
|
||||
entity_id = entry.entity_id
|
||||
trigger_name_parts = []
|
||||
if entity_id and (state := self.hass.states.get(entity_id)):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue