parent
b9757235a7
commit
ac15f2cf9d
|
@ -76,13 +76,7 @@ from . import ( # noqa: F401
|
|||
type_switches,
|
||||
type_thermostats,
|
||||
)
|
||||
from .accessories import (
|
||||
HomeAccessory,
|
||||
HomeBridge,
|
||||
HomeDriver,
|
||||
HomeIIDManager,
|
||||
get_accessory,
|
||||
)
|
||||
from .accessories import HomeAccessory, HomeBridge, HomeDriver, get_accessory
|
||||
from .aidmanager import AccessoryAidStorage
|
||||
from .const import (
|
||||
ATTR_INTEGRATION,
|
||||
|
@ -551,7 +545,7 @@ class HomeKit:
|
|||
async_zeroconf_instance=async_zeroconf_instance,
|
||||
zeroconf_server=f"{uuid}-hap.local.",
|
||||
loader=get_loader(),
|
||||
iid_manager=HomeIIDManager(self.iid_storage),
|
||||
iid_storage=self.iid_storage,
|
||||
)
|
||||
|
||||
# If we do not load the mac address will be wrong
|
||||
|
|
|
@ -270,7 +270,7 @@ class HomeAccessory(Accessory): # type: ignore[misc]
|
|||
driver=driver,
|
||||
display_name=cleanup_name_for_homekit(name),
|
||||
aid=aid,
|
||||
iid_manager=driver.iid_manager,
|
||||
iid_manager=HomeIIDManager(driver.iid_storage),
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
|
@ -570,7 +570,7 @@ class HomeBridge(Bridge): # type: ignore[misc]
|
|||
|
||||
def __init__(self, hass: HomeAssistant, driver: HomeDriver, name: str) -> None:
|
||||
"""Initialize a Bridge object."""
|
||||
super().__init__(driver, name, iid_manager=driver.iid_manager)
|
||||
super().__init__(driver, name, iid_manager=HomeIIDManager(driver.iid_storage))
|
||||
self.set_info_service(
|
||||
firmware_revision=format_version(__version__),
|
||||
manufacturer=MANUFACTURER,
|
||||
|
@ -603,7 +603,7 @@ class HomeDriver(AccessoryDriver): # type: ignore[misc]
|
|||
entry_id: str,
|
||||
bridge_name: str,
|
||||
entry_title: str,
|
||||
iid_manager: HomeIIDManager,
|
||||
iid_storage: AccessoryIIDStorage,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
"""Initialize a AccessoryDriver object."""
|
||||
|
@ -612,7 +612,7 @@ class HomeDriver(AccessoryDriver): # type: ignore[misc]
|
|||
self._entry_id = entry_id
|
||||
self._bridge_name = bridge_name
|
||||
self._entry_title = entry_title
|
||||
self.iid_manager = iid_manager
|
||||
self.iid_storage = iid_storage
|
||||
|
||||
@pyhap_callback # type: ignore[misc]
|
||||
def pair(
|
||||
|
|
|
@ -31,6 +31,8 @@ async def async_get_config_entry_diagnostics(
|
|||
"options": dict(entry.options),
|
||||
},
|
||||
}
|
||||
if homekit.iid_storage:
|
||||
data["iid_storage"] = homekit.iid_storage.allocations
|
||||
if not homekit.driver: # not started yet or startup failed
|
||||
return data
|
||||
driver: AccessoryDriver = homekit.driver
|
||||
|
|
|
@ -17,7 +17,7 @@ from homeassistant.helpers.storage import Store
|
|||
|
||||
from .util import get_iid_storage_filename_for_entry_id
|
||||
|
||||
IID_MANAGER_STORAGE_VERSION = 1
|
||||
IID_MANAGER_STORAGE_VERSION = 2
|
||||
IID_MANAGER_SAVE_DELAY = 2
|
||||
|
||||
ALLOCATIONS_KEY = "allocations"
|
||||
|
@ -26,6 +26,40 @@ IID_MIN = 1
|
|||
IID_MAX = 18446744073709551615
|
||||
|
||||
|
||||
ACCESSORY_INFORMATION_SERVICE = "3E"
|
||||
|
||||
|
||||
class IIDStorage(Store):
|
||||
"""Storage class for IIDManager."""
|
||||
|
||||
async def _async_migrate_func(
|
||||
self,
|
||||
old_major_version: int,
|
||||
old_minor_version: int,
|
||||
old_data: dict,
|
||||
):
|
||||
"""Migrate to the new version."""
|
||||
if old_major_version == 1:
|
||||
# Convert v1 to v2 format which uses a unique iid set per accessory
|
||||
# instead of per pairing since we need the ACCESSORY_INFORMATION_SERVICE
|
||||
# to always have iid 1 for each bridged accessory as well as the bridge
|
||||
old_allocations: dict[str, int] = old_data.pop(ALLOCATIONS_KEY, {})
|
||||
new_allocation: dict[str, dict[str, int]] = {}
|
||||
old_data[ALLOCATIONS_KEY] = new_allocation
|
||||
for allocation_key, iid in old_allocations.items():
|
||||
aid_str, new_allocation_key = allocation_key.split("_", 1)
|
||||
service_type, _, char_type, *_ = new_allocation_key.split("_")
|
||||
accessory_allocation = new_allocation.setdefault(aid_str, {})
|
||||
if service_type == ACCESSORY_INFORMATION_SERVICE and not char_type:
|
||||
accessory_allocation[new_allocation_key] = 1
|
||||
elif iid != 1:
|
||||
accessory_allocation[new_allocation_key] = iid
|
||||
|
||||
return old_data
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AccessoryIIDStorage:
|
||||
"""
|
||||
Provide stable allocation of IIDs for the lifetime of an accessory.
|
||||
|
@ -37,15 +71,15 @@ class AccessoryIIDStorage:
|
|||
def __init__(self, hass: HomeAssistant, entry_id: str) -> None:
|
||||
"""Create a new iid store."""
|
||||
self.hass = hass
|
||||
self.allocations: dict[str, int] = {}
|
||||
self.allocated_iids: list[int] = []
|
||||
self.allocations: dict[str, dict[str, int]] = {}
|
||||
self.allocated_iids: dict[str, list[int]] = {}
|
||||
self.entry_id = entry_id
|
||||
self.store: Store | None = None
|
||||
self.store: IIDStorage | None = None
|
||||
|
||||
async def async_initialize(self) -> None:
|
||||
"""Load the latest IID data."""
|
||||
iid_store = get_iid_storage_filename_for_entry_id(self.entry_id)
|
||||
self.store = Store(self.hass, IID_MANAGER_STORAGE_VERSION, iid_store)
|
||||
self.store = IIDStorage(self.hass, IID_MANAGER_STORAGE_VERSION, iid_store)
|
||||
|
||||
if not (raw_storage := await self.store.async_load()):
|
||||
# There is no data about iid allocations yet
|
||||
|
@ -53,7 +87,8 @@ class AccessoryIIDStorage:
|
|||
|
||||
assert isinstance(raw_storage, dict)
|
||||
self.allocations = raw_storage.get(ALLOCATIONS_KEY, {})
|
||||
self.allocated_iids = sorted(self.allocations.values())
|
||||
for aid_str, allocations in self.allocations.items():
|
||||
self.allocated_iids[aid_str] = sorted(allocations.values())
|
||||
|
||||
def get_or_allocate_iid(
|
||||
self,
|
||||
|
@ -68,16 +103,25 @@ class AccessoryIIDStorage:
|
|||
char_hap_type: str | None = uuid_to_hap_type(char_uuid) if char_uuid else None
|
||||
# Allocation key must be a string since we are saving it to JSON
|
||||
allocation_key = (
|
||||
f'{aid}_{service_hap_type}_{service_unique_id or ""}_'
|
||||
f'{service_hap_type}_{service_unique_id or ""}_'
|
||||
f'{char_hap_type or ""}_{char_unique_id or ""}'
|
||||
)
|
||||
if allocation_key in self.allocations:
|
||||
return self.allocations[allocation_key]
|
||||
next_iid = self.allocated_iids[-1] + 1 if self.allocated_iids else 1
|
||||
self.allocations[allocation_key] = next_iid
|
||||
self.allocated_iids.append(next_iid)
|
||||
# AID must be a string since JSON keys cannot be int
|
||||
aid_str = str(aid)
|
||||
accessory_allocation = self.allocations.setdefault(aid_str, {})
|
||||
accessory_allocated_iids = self.allocated_iids.setdefault(aid_str, [])
|
||||
if service_hap_type == ACCESSORY_INFORMATION_SERVICE and char_uuid is None:
|
||||
allocated_iid = 1
|
||||
elif allocation_key in accessory_allocation:
|
||||
return accessory_allocation[allocation_key]
|
||||
elif accessory_allocated_iids:
|
||||
allocated_iid = accessory_allocated_iids[-1] + 1
|
||||
else:
|
||||
allocated_iid = 2
|
||||
accessory_allocation[allocation_key] = allocated_iid
|
||||
accessory_allocated_iids.append(allocated_iid)
|
||||
self._async_schedule_save()
|
||||
return next_iid
|
||||
return allocated_iid
|
||||
|
||||
@callback
|
||||
def _async_schedule_save(self) -> None:
|
||||
|
@ -91,6 +135,6 @@ class AccessoryIIDStorage:
|
|||
return await self.store.async_save(self._data_to_save())
|
||||
|
||||
@callback
|
||||
def _data_to_save(self) -> dict[str, dict[str, int]]:
|
||||
def _data_to_save(self) -> dict[str, dict[str, dict[str, int]]]:
|
||||
"""Return data of entity map to store in a file."""
|
||||
return {ALLOCATIONS_KEY: self.allocations}
|
||||
|
|
|
@ -6,7 +6,7 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
|
||||
from homeassistant.components.device_tracker.legacy import YAML_DEVICES
|
||||
from homeassistant.components.homekit.accessories import HomeDriver, HomeIIDManager
|
||||
from homeassistant.components.homekit.accessories import HomeDriver
|
||||
from homeassistant.components.homekit.const import BRIDGE_NAME, EVENT_HOMEKIT_CHANGED
|
||||
from homeassistant.components.homekit.iidmanager import AccessoryIIDStorage
|
||||
|
||||
|
@ -39,7 +39,7 @@ def run_driver(hass, loop, iid_storage):
|
|||
entry_id="",
|
||||
entry_title="mock entry",
|
||||
bridge_name=BRIDGE_NAME,
|
||||
iid_manager=HomeIIDManager(iid_storage),
|
||||
iid_storage=iid_storage,
|
||||
address="127.0.0.1",
|
||||
loop=loop,
|
||||
)
|
||||
|
@ -63,7 +63,7 @@ def hk_driver(hass, loop, iid_storage):
|
|||
entry_id="",
|
||||
entry_title="mock entry",
|
||||
bridge_name=BRIDGE_NAME,
|
||||
iid_manager=HomeIIDManager(iid_storage),
|
||||
iid_storage=iid_storage,
|
||||
address="127.0.0.1",
|
||||
loop=loop,
|
||||
)
|
||||
|
@ -91,7 +91,7 @@ def mock_hap(hass, loop, iid_storage, mock_zeroconf):
|
|||
entry_id="",
|
||||
entry_title="mock entry",
|
||||
bridge_name=BRIDGE_NAME,
|
||||
iid_manager=HomeIIDManager(iid_storage),
|
||||
iid_storage=iid_storage,
|
||||
address="127.0.0.1",
|
||||
loop=loop,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "homekit.v1.iids",
|
||||
"data": {
|
||||
"allocations": {
|
||||
"1_3E___": 1,
|
||||
"1_3E__14_": 2,
|
||||
"1_3E__20_": 3,
|
||||
"1_3E__21_": 4,
|
||||
"1_3E__23_": 5,
|
||||
"1_3E__30_": 6,
|
||||
"1_3E__52_": 7,
|
||||
"1_A2___": 8,
|
||||
"1_A2__37_": 9,
|
||||
"935391877_3E___": 10,
|
||||
"935391877_3E__14_": 11,
|
||||
"935391877_3E__20_": 12,
|
||||
"935391877_3E__21_": 13,
|
||||
"935391877_3E__23_": 14,
|
||||
"935391877_3E__30_": 15,
|
||||
"935391877_3E__52_": 16,
|
||||
"935391877_4A___": 17,
|
||||
"935391877_4A__F_": 18,
|
||||
"935391877_4A__33_": 19,
|
||||
"935391877_4A__11_": 20,
|
||||
"935391877_4A__35_": 21,
|
||||
"935391877_4A__36_": 22,
|
||||
"935391877_4A__D_": 23,
|
||||
"935391877_4A__12_": 24,
|
||||
"935391877_4A__34_": 25,
|
||||
"935391877_4A__10_": 26,
|
||||
"935391877_B7___": 27,
|
||||
"935391877_B7__B0_": 28,
|
||||
"935391877_B7__BF_": 29,
|
||||
"935391877_B7__AF_": 30,
|
||||
"985724734_3E___": 31,
|
||||
"985724734_3E__14_": 32,
|
||||
"985724734_3E__20_": 33,
|
||||
"985724734_3E__21_": 34,
|
||||
"985724734_3E__23_": 35,
|
||||
"985724734_3E__30_": 36,
|
||||
"985724734_3E__52_": 37,
|
||||
"985724734_4A___": 38,
|
||||
"985724734_4A__F_": 39,
|
||||
"985724734_4A__33_": 40,
|
||||
"985724734_4A__11_": 41,
|
||||
"985724734_4A__35_": 42,
|
||||
"985724734_4A__36_": 43,
|
||||
"985724734_4A__D_": 44,
|
||||
"985724734_4A__12_": 45,
|
||||
"985724734_4A__34_": 46,
|
||||
"985724734_4A__10_": 47,
|
||||
"985724734_B7___": 48,
|
||||
"985724734_B7__B0_": 49,
|
||||
"985724734_B7__BF_": 50,
|
||||
"985724734_B7__AF_": 51,
|
||||
"3083074204_3E___": 52,
|
||||
"3083074204_3E__14_": 53,
|
||||
"3083074204_3E__20_": 54,
|
||||
"3083074204_3E__21_": 55,
|
||||
"3083074204_3E__23_": 56,
|
||||
"3083074204_3E__30_": 57,
|
||||
"3083074204_3E__52_": 58,
|
||||
"3083074204_4A___": 59,
|
||||
"3083074204_4A__F_": 60,
|
||||
"3083074204_4A__33_": 61,
|
||||
"3083074204_4A__11_": 62,
|
||||
"3083074204_4A__35_": 63,
|
||||
"3083074204_4A__36_": 64,
|
||||
"3083074204_4A__D_": 65,
|
||||
"3083074204_4A__12_": 66,
|
||||
"3083074204_4A__34_": 67,
|
||||
"3083074204_4A__10_": 68,
|
||||
"3083074204_B7___": 69,
|
||||
"3083074204_B7__B0_": 70,
|
||||
"3083074204_B7__BF_": 71,
|
||||
"3083074204_B7__AF_": 72,
|
||||
"3032741347_3E___": 73,
|
||||
"3032741347_3E__14_": 74,
|
||||
"3032741347_3E__20_": 75,
|
||||
"3032741347_3E__21_": 76,
|
||||
"3032741347_3E__23_": 77,
|
||||
"3032741347_3E__30_": 78,
|
||||
"3032741347_3E__52_": 79,
|
||||
"3032741347_4A___": 80,
|
||||
"3032741347_4A__F_": 81,
|
||||
"3032741347_4A__33_": 82,
|
||||
"3032741347_4A__11_": 83,
|
||||
"3032741347_4A__35_": 84,
|
||||
"3032741347_4A__36_": 85,
|
||||
"3032741347_4A__D_": 86,
|
||||
"3032741347_4A__12_": 87,
|
||||
"3032741347_4A__34_": 88,
|
||||
"3032741347_4A__10_": 89,
|
||||
"3032741347_B7___": 90,
|
||||
"3032741347_B7__B0_": 91,
|
||||
"3032741347_B7__BF_": 92,
|
||||
"3032741347_B7__AF_": 93,
|
||||
"3681509609_3E___": 94,
|
||||
"3681509609_3E__14_": 95,
|
||||
"3681509609_3E__20_": 96,
|
||||
"3681509609_3E__21_": 97,
|
||||
"3681509609_3E__23_": 98,
|
||||
"3681509609_3E__30_": 99,
|
||||
"3681509609_3E__52_": 100,
|
||||
"3681509609_4A___": 101,
|
||||
"3681509609_4A__F_": 102,
|
||||
"3681509609_4A__33_": 103,
|
||||
"3681509609_4A__11_": 104,
|
||||
"3681509609_4A__35_": 105,
|
||||
"3681509609_4A__36_": 106,
|
||||
"3681509609_4A__D_": 107,
|
||||
"3681509609_4A__12_": 108,
|
||||
"3681509609_4A__34_": 109,
|
||||
"3681509609_4A__10_": 110,
|
||||
"3681509609_B7___": 111,
|
||||
"3681509609_B7__B0_": 112,
|
||||
"3681509609_B7__BF_": 113,
|
||||
"3681509609_B7__AF_": 114,
|
||||
"3866063418_3E___": 115,
|
||||
"3866063418_3E__14_": 116,
|
||||
"3866063418_3E__20_": 117,
|
||||
"3866063418_3E__21_": 118,
|
||||
"3866063418_3E__23_": 119,
|
||||
"3866063418_3E__30_": 120,
|
||||
"3866063418_3E__52_": 121,
|
||||
"3866063418_4A___": 122,
|
||||
"3866063418_4A__F_": 123,
|
||||
"3866063418_4A__33_": 124,
|
||||
"3866063418_4A__11_": 125,
|
||||
"3866063418_4A__35_": 126,
|
||||
"3866063418_4A__36_": 127,
|
||||
"3866063418_4A__D_": 128,
|
||||
"3866063418_4A__12_": 129,
|
||||
"3866063418_4A__34_": 130,
|
||||
"3866063418_4A__10_": 131,
|
||||
"3866063418_B7___": 132,
|
||||
"3866063418_B7__B0_": 133,
|
||||
"3866063418_B7__BF_": 134,
|
||||
"3866063418_B7__AF_": 135,
|
||||
"3239498961_3E___": 136,
|
||||
"3239498961_3E__14_": 137,
|
||||
"3239498961_3E__20_": 138,
|
||||
"3239498961_3E__21_": 139,
|
||||
"3239498961_3E__23_": 140,
|
||||
"3239498961_3E__30_": 141,
|
||||
"3239498961_3E__52_": 142,
|
||||
"3239498961_4A___": 143,
|
||||
"3239498961_4A__F_": 144,
|
||||
"3239498961_4A__33_": 145,
|
||||
"3239498961_4A__11_": 146,
|
||||
"3239498961_4A__35_": 147,
|
||||
"3239498961_4A__36_": 148,
|
||||
"3239498961_4A__D_": 149,
|
||||
"3239498961_4A__12_": 150,
|
||||
"3239498961_4A__34_": 151,
|
||||
"3239498961_4A__10_": 152,
|
||||
"3239498961_B7___": 153,
|
||||
"3239498961_B7__B0_": 154,
|
||||
"3239498961_B7__BF_": 155,
|
||||
"3239498961_B7__AF_": 156,
|
||||
"3289831818_3E___": 157,
|
||||
"3289831818_3E__14_": 158,
|
||||
"3289831818_3E__20_": 159,
|
||||
"3289831818_3E__21_": 160,
|
||||
"3289831818_3E__23_": 161,
|
||||
"3289831818_3E__30_": 162,
|
||||
"3289831818_3E__52_": 163,
|
||||
"3289831818_4A___": 164,
|
||||
"3289831818_4A__F_": 165,
|
||||
"3289831818_4A__33_": 166,
|
||||
"3289831818_4A__11_": 167,
|
||||
"3289831818_4A__35_": 168,
|
||||
"3289831818_4A__36_": 169,
|
||||
"3289831818_4A__D_": 170,
|
||||
"3289831818_4A__12_": 171,
|
||||
"3289831818_4A__34_": 172,
|
||||
"3289831818_4A__10_": 173,
|
||||
"3289831818_B7___": 174,
|
||||
"3289831818_B7__B0_": 175,
|
||||
"3289831818_B7__BF_": 176,
|
||||
"3289831818_B7__AF_": 177,
|
||||
"3071722771_3E___": 178,
|
||||
"3071722771_3E__14_": 179,
|
||||
"3071722771_3E__20_": 180,
|
||||
"3071722771_3E__21_": 181,
|
||||
"3071722771_3E__23_": 182,
|
||||
"3071722771_3E__30_": 183,
|
||||
"3071722771_3E__52_": 184,
|
||||
"3071722771_4A___": 185,
|
||||
"3071722771_4A__F_": 186,
|
||||
"3071722771_4A__33_": 187,
|
||||
"3071722771_4A__11_": 188,
|
||||
"3071722771_4A__35_": 189,
|
||||
"3071722771_4A__36_": 190,
|
||||
"3071722771_4A__D_": 191,
|
||||
"3071722771_4A__12_": 192,
|
||||
"3071722771_4A__34_": 193,
|
||||
"3071722771_4A__10_": 194,
|
||||
"3071722771_B7___": 195,
|
||||
"3071722771_B7__B0_": 196,
|
||||
"3071722771_B7__BF_": 197,
|
||||
"3071722771_B7__AF_": 198,
|
||||
"3391630365_3E___": 199,
|
||||
"3391630365_3E__14_": 200,
|
||||
"3391630365_3E__20_": 201,
|
||||
"3391630365_3E__21_": 202,
|
||||
"3391630365_3E__23_": 203,
|
||||
"3391630365_3E__30_": 204,
|
||||
"3391630365_3E__52_": 205,
|
||||
"3391630365_4A___": 206,
|
||||
"3391630365_4A__F_": 207,
|
||||
"3391630365_4A__33_": 208,
|
||||
"3391630365_4A__11_": 209,
|
||||
"3391630365_4A__35_": 210,
|
||||
"3391630365_4A__36_": 211,
|
||||
"3391630365_4A__D_": 212,
|
||||
"3391630365_4A__12_": 213,
|
||||
"3391630365_4A__34_": 214,
|
||||
"3391630365_4A__10_": 215,
|
||||
"3391630365_B7___": 216,
|
||||
"3391630365_B7__B0_": 217,
|
||||
"3391630365_B7__BF_": 218,
|
||||
"3391630365_B7__AF_": 219,
|
||||
"3274187032_3E___": 220,
|
||||
"3274187032_3E__14_": 221,
|
||||
"3274187032_3E__20_": 222,
|
||||
"3274187032_3E__21_": 223,
|
||||
"3274187032_3E__23_": 224,
|
||||
"3274187032_3E__30_": 225,
|
||||
"3274187032_3E__52_": 226,
|
||||
"3274187032_4A___": 227,
|
||||
"3274187032_4A__F_": 228,
|
||||
"3274187032_4A__33_": 229,
|
||||
"3274187032_4A__11_": 230,
|
||||
"3274187032_4A__35_": 231,
|
||||
"3274187032_4A__36_": 232,
|
||||
"3274187032_4A__D_": 233,
|
||||
"3274187032_4A__12_": 234,
|
||||
"3274187032_4A__34_": 235,
|
||||
"3274187032_4A__10_": 236,
|
||||
"3274187032_B7___": 237,
|
||||
"3274187032_B7__B0_": 238,
|
||||
"3274187032_B7__BF_": 239,
|
||||
"3274187032_B7__AF_": 240
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "homekit.8a47205bd97c07d7a908f10166ebe636.iids",
|
||||
"data": {
|
||||
"allocations": {
|
||||
"1_3E___": 1,
|
||||
"1_3E__14_": 2,
|
||||
"1_3E__20_": 3,
|
||||
"1_3E__21_": 4,
|
||||
"1_3E__23_": 5,
|
||||
"1_3E__30_": 6,
|
||||
"1_3E__52_": 7,
|
||||
"1_A2___": 8,
|
||||
"1_A2__37_": 9,
|
||||
"1973560704_3E___": 10,
|
||||
"1973560704_3E__14_": 11,
|
||||
"1973560704_3E__20_": 12,
|
||||
"1973560704_3E__21_": 13,
|
||||
"1973560704_3E__23_": 14,
|
||||
"1973560704_3E__30_": 15,
|
||||
"1973560704_3E__52_": 16,
|
||||
"1973560704_3E__53_": 17,
|
||||
"1973560704_89_pressed-__": 18,
|
||||
"1973560704_89_pressed-_73_": 19,
|
||||
"1973560704_89_pressed-_23_": 20,
|
||||
"1973560704_89_pressed-_CB_": 21,
|
||||
"1973560704_CC_pressed-__": 22,
|
||||
"1973560704_CC_pressed-_CD_": 23,
|
||||
"1973560704_89_changed_states-__": 24,
|
||||
"1973560704_89_changed_states-_73_": 25,
|
||||
"1973560704_89_changed_states-_23_": 26,
|
||||
"1973560704_89_changed_states-_CB_": 27,
|
||||
"1973560704_CC_changed_states-__": 28,
|
||||
"1973560704_CC_changed_states-_CD_": 29,
|
||||
"1973560704_89_turned_off-__": 30,
|
||||
"1973560704_89_turned_off-_73_": 31,
|
||||
"1973560704_89_turned_off-_23_": 32,
|
||||
"1973560704_89_turned_off-_CB_": 33,
|
||||
"1973560704_CC_turned_off-__": 34,
|
||||
"1973560704_CC_turned_off-_CD_": 35,
|
||||
"1973560704_89_turned_on-__": 36,
|
||||
"1973560704_89_turned_on-_73_": 37,
|
||||
"1973560704_89_turned_on-_23_": 38,
|
||||
"1973560704_89_turned_on-_CB_": 39,
|
||||
"1973560704_CC_turned_on-__": 40,
|
||||
"1973560704_CC_turned_on-_CD_": 41
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
{
|
||||
"version": 2,
|
||||
"minor_version": 1,
|
||||
"key": "homekit.v2.iids",
|
||||
"data": {
|
||||
"allocations": {
|
||||
"1": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 2,
|
||||
"3E__20_": 3,
|
||||
"3E__21_": 4,
|
||||
"3E__23_": 5,
|
||||
"3E__30_": 6,
|
||||
"3E__52_": 7,
|
||||
"A2___": 8,
|
||||
"A2__37_": 9
|
||||
},
|
||||
"935391877": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 11,
|
||||
"3E__20_": 12,
|
||||
"3E__21_": 13,
|
||||
"3E__23_": 14,
|
||||
"3E__30_": 15,
|
||||
"3E__52_": 16,
|
||||
"4A___": 17,
|
||||
"4A__F_": 18,
|
||||
"4A__33_": 19,
|
||||
"4A__11_": 20,
|
||||
"4A__35_": 21,
|
||||
"4A__36_": 22,
|
||||
"4A__D_": 23,
|
||||
"4A__12_": 24,
|
||||
"4A__34_": 25,
|
||||
"4A__10_": 26,
|
||||
"B7___": 27,
|
||||
"B7__B0_": 28,
|
||||
"B7__BF_": 29,
|
||||
"B7__AF_": 30
|
||||
},
|
||||
"985724734": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 32,
|
||||
"3E__20_": 33,
|
||||
"3E__21_": 34,
|
||||
"3E__23_": 35,
|
||||
"3E__30_": 36,
|
||||
"3E__52_": 37,
|
||||
"4A___": 38,
|
||||
"4A__F_": 39,
|
||||
"4A__33_": 40,
|
||||
"4A__11_": 41,
|
||||
"4A__35_": 42,
|
||||
"4A__36_": 43,
|
||||
"4A__D_": 44,
|
||||
"4A__12_": 45,
|
||||
"4A__34_": 46,
|
||||
"4A__10_": 47,
|
||||
"B7___": 48,
|
||||
"B7__B0_": 49,
|
||||
"B7__BF_": 50,
|
||||
"B7__AF_": 51
|
||||
},
|
||||
"3083074204": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 53,
|
||||
"3E__20_": 54,
|
||||
"3E__21_": 55,
|
||||
"3E__23_": 56,
|
||||
"3E__30_": 57,
|
||||
"3E__52_": 58,
|
||||
"4A___": 59,
|
||||
"4A__F_": 60,
|
||||
"4A__33_": 61,
|
||||
"4A__11_": 62,
|
||||
"4A__35_": 63,
|
||||
"4A__36_": 64,
|
||||
"4A__D_": 65,
|
||||
"4A__12_": 66,
|
||||
"4A__34_": 67,
|
||||
"4A__10_": 68,
|
||||
"B7___": 69,
|
||||
"B7__B0_": 70,
|
||||
"B7__BF_": 71,
|
||||
"B7__AF_": 72
|
||||
},
|
||||
"3032741347": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 74,
|
||||
"3E__20_": 75,
|
||||
"3E__21_": 76,
|
||||
"3E__23_": 77,
|
||||
"3E__30_": 78,
|
||||
"3E__52_": 79,
|
||||
"4A___": 80,
|
||||
"4A__F_": 81,
|
||||
"4A__33_": 82,
|
||||
"4A__11_": 83,
|
||||
"4A__35_": 84,
|
||||
"4A__36_": 85,
|
||||
"4A__D_": 86,
|
||||
"4A__12_": 87,
|
||||
"4A__34_": 88,
|
||||
"4A__10_": 89,
|
||||
"B7___": 90,
|
||||
"B7__B0_": 91,
|
||||
"B7__BF_": 92,
|
||||
"B7__AF_": 93
|
||||
},
|
||||
"3681509609": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 95,
|
||||
"3E__20_": 96,
|
||||
"3E__21_": 97,
|
||||
"3E__23_": 98,
|
||||
"3E__30_": 99,
|
||||
"3E__52_": 100,
|
||||
"4A___": 101,
|
||||
"4A__F_": 102,
|
||||
"4A__33_": 103,
|
||||
"4A__11_": 104,
|
||||
"4A__35_": 105,
|
||||
"4A__36_": 106,
|
||||
"4A__D_": 107,
|
||||
"4A__12_": 108,
|
||||
"4A__34_": 109,
|
||||
"4A__10_": 110,
|
||||
"B7___": 111,
|
||||
"B7__B0_": 112,
|
||||
"B7__BF_": 113,
|
||||
"B7__AF_": 114
|
||||
},
|
||||
"3866063418": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 116,
|
||||
"3E__20_": 117,
|
||||
"3E__21_": 118,
|
||||
"3E__23_": 119,
|
||||
"3E__30_": 120,
|
||||
"3E__52_": 121,
|
||||
"4A___": 122,
|
||||
"4A__F_": 123,
|
||||
"4A__33_": 124,
|
||||
"4A__11_": 125,
|
||||
"4A__35_": 126,
|
||||
"4A__36_": 127,
|
||||
"4A__D_": 128,
|
||||
"4A__12_": 129,
|
||||
"4A__34_": 130,
|
||||
"4A__10_": 131,
|
||||
"B7___": 132,
|
||||
"B7__B0_": 133,
|
||||
"B7__BF_": 134,
|
||||
"B7__AF_": 135
|
||||
},
|
||||
"3239498961": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 137,
|
||||
"3E__20_": 138,
|
||||
"3E__21_": 139,
|
||||
"3E__23_": 140,
|
||||
"3E__30_": 141,
|
||||
"3E__52_": 142,
|
||||
"4A___": 143,
|
||||
"4A__F_": 144,
|
||||
"4A__33_": 145,
|
||||
"4A__11_": 146,
|
||||
"4A__35_": 147,
|
||||
"4A__36_": 148,
|
||||
"4A__D_": 149,
|
||||
"4A__12_": 150,
|
||||
"4A__34_": 151,
|
||||
"4A__10_": 152,
|
||||
"B7___": 153,
|
||||
"B7__B0_": 154,
|
||||
"B7__BF_": 155,
|
||||
"B7__AF_": 156
|
||||
},
|
||||
"3289831818": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 158,
|
||||
"3E__20_": 159,
|
||||
"3E__21_": 160,
|
||||
"3E__23_": 161,
|
||||
"3E__30_": 162,
|
||||
"3E__52_": 163,
|
||||
"4A___": 164,
|
||||
"4A__F_": 165,
|
||||
"4A__33_": 166,
|
||||
"4A__11_": 167,
|
||||
"4A__35_": 168,
|
||||
"4A__36_": 169,
|
||||
"4A__D_": 170,
|
||||
"4A__12_": 171,
|
||||
"4A__34_": 172,
|
||||
"4A__10_": 173,
|
||||
"B7___": 174,
|
||||
"B7__B0_": 175,
|
||||
"B7__BF_": 176,
|
||||
"B7__AF_": 177
|
||||
},
|
||||
"3071722771": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 179,
|
||||
"3E__20_": 180,
|
||||
"3E__21_": 181,
|
||||
"3E__23_": 182,
|
||||
"3E__30_": 183,
|
||||
"3E__52_": 184,
|
||||
"4A___": 185,
|
||||
"4A__F_": 186,
|
||||
"4A__33_": 187,
|
||||
"4A__11_": 188,
|
||||
"4A__35_": 189,
|
||||
"4A__36_": 190,
|
||||
"4A__D_": 191,
|
||||
"4A__12_": 192,
|
||||
"4A__34_": 193,
|
||||
"4A__10_": 194,
|
||||
"B7___": 195,
|
||||
"B7__B0_": 196,
|
||||
"B7__BF_": 197,
|
||||
"B7__AF_": 198
|
||||
},
|
||||
"3391630365": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 200,
|
||||
"3E__20_": 201,
|
||||
"3E__21_": 202,
|
||||
"3E__23_": 203,
|
||||
"3E__30_": 204,
|
||||
"3E__52_": 205,
|
||||
"4A___": 206,
|
||||
"4A__F_": 207,
|
||||
"4A__33_": 208,
|
||||
"4A__11_": 209,
|
||||
"4A__35_": 210,
|
||||
"4A__36_": 211,
|
||||
"4A__D_": 212,
|
||||
"4A__12_": 213,
|
||||
"4A__34_": 214,
|
||||
"4A__10_": 215,
|
||||
"B7___": 216,
|
||||
"B7__B0_": 217,
|
||||
"B7__BF_": 218,
|
||||
"B7__AF_": 219
|
||||
},
|
||||
"3274187032": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 221,
|
||||
"3E__20_": 222,
|
||||
"3E__21_": 223,
|
||||
"3E__23_": 224,
|
||||
"3E__30_": 225,
|
||||
"3E__52_": 226,
|
||||
"4A___": 227,
|
||||
"4A__F_": 228,
|
||||
"4A__33_": 229,
|
||||
"4A__11_": 230,
|
||||
"4A__35_": 231,
|
||||
"4A__36_": 232,
|
||||
"4A__D_": 233,
|
||||
"4A__12_": 234,
|
||||
"4A__34_": 235,
|
||||
"4A__10_": 236,
|
||||
"B7___": 237,
|
||||
"B7__B0_": 238,
|
||||
"B7__BF_": 239,
|
||||
"B7__AF_": 240
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"version": 2,
|
||||
"minor_version": 1,
|
||||
"key": "homekit.8a47205bd97c07d7a908f10166ebe636.iids",
|
||||
"data": {
|
||||
"allocations": {
|
||||
"1": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 2,
|
||||
"3E__20_": 3,
|
||||
"3E__21_": 4,
|
||||
"3E__23_": 5,
|
||||
"3E__30_": 6,
|
||||
"3E__52_": 7,
|
||||
"A2___": 8,
|
||||
"A2__37_": 9
|
||||
},
|
||||
"1973560704": {
|
||||
"3E___": 1,
|
||||
"3E__14_": 11,
|
||||
"3E__20_": 12,
|
||||
"3E__21_": 13,
|
||||
"3E__23_": 14,
|
||||
"3E__30_": 15,
|
||||
"3E__52_": 16,
|
||||
"3E__53_": 17,
|
||||
"89_pressed-__": 18,
|
||||
"89_pressed-_73_": 19,
|
||||
"89_pressed-_23_": 20,
|
||||
"89_pressed-_CB_": 21,
|
||||
"CC_pressed-__": 22,
|
||||
"CC_pressed-_CD_": 23,
|
||||
"89_changed_states-__": 24,
|
||||
"89_changed_states-_73_": 25,
|
||||
"89_changed_states-_23_": 26,
|
||||
"89_changed_states-_CB_": 27,
|
||||
"CC_changed_states-__": 28,
|
||||
"CC_changed_states-_CD_": 29,
|
||||
"89_turned_off-__": 30,
|
||||
"89_turned_off-_73_": 31,
|
||||
"89_turned_off-_23_": 32,
|
||||
"89_turned_off-_CB_": 33,
|
||||
"CC_turned_off-__": 34,
|
||||
"CC_turned_off-_CD_": 35,
|
||||
"89_turned_on-__": 36,
|
||||
"89_turned_on-_73_": 37,
|
||||
"89_turned_on-_23_": 38,
|
||||
"89_turned_on-_CB_": 39,
|
||||
"CC_turned_on-__": 40,
|
||||
"CC_turned_on-_CD_": 41
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@ from homeassistant.components.homekit.accessories import (
|
|||
HomeAccessory,
|
||||
HomeBridge,
|
||||
HomeDriver,
|
||||
HomeIIDManager,
|
||||
)
|
||||
from homeassistant.components.homekit.const import (
|
||||
ATTR_DISPLAY_NAME,
|
||||
|
@ -724,7 +723,7 @@ def test_home_driver(iid_storage):
|
|||
"entry_id",
|
||||
"name",
|
||||
"title",
|
||||
iid_manager=HomeIIDManager(iid_storage),
|
||||
iid_storage=iid_storage,
|
||||
address=ip_address,
|
||||
port=port,
|
||||
persist_file=path,
|
||||
|
@ -752,22 +751,3 @@ def test_home_driver(iid_storage):
|
|||
|
||||
mock_unpair.assert_called_with("client_uuid")
|
||||
mock_show_msg.assert_called_with("hass", "entry_id", "title (any)", pin, "X-HM://0")
|
||||
|
||||
|
||||
async def test_iid_collision_raises(hass, hk_driver):
|
||||
"""Test iid collision raises.
|
||||
|
||||
If we try to allocate the same IID to the an accessory twice, we should
|
||||
raise an exception.
|
||||
"""
|
||||
|
||||
entity_id = "light.accessory"
|
||||
entity_id2 = "light.accessory2"
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(entity_id2, STATE_OFF)
|
||||
|
||||
HomeAccessory(hass, hk_driver, "Home Accessory", entity_id, 2, {})
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
HomeAccessory(hass, hk_driver, "Home Accessory", entity_id2, 2, {})
|
||||
|
|
|
@ -43,6 +43,19 @@ async def test_config_entry_running(hass, hass_client, hk_driver, mock_async_zer
|
|||
diag = await get_diagnostics_for_config_entry(hass, hass_client, entry)
|
||||
assert diag == {
|
||||
"bridge": {},
|
||||
"iid_storage": {
|
||||
"1": {
|
||||
"3E__14_": 2,
|
||||
"3E__20_": 3,
|
||||
"3E__21_": 4,
|
||||
"3E__23_": 5,
|
||||
"3E__30_": 6,
|
||||
"3E__52_": 7,
|
||||
"3E___": 1,
|
||||
"A2__37_": 9,
|
||||
"A2___": 8,
|
||||
}
|
||||
},
|
||||
"accessories": [
|
||||
{
|
||||
"aid": 1,
|
||||
|
@ -257,6 +270,21 @@ async def test_config_entry_accessory(
|
|||
},
|
||||
"config_version": 2,
|
||||
"pairing_id": ANY,
|
||||
"iid_storage": {
|
||||
"1": {
|
||||
"3E__14_": 2,
|
||||
"3E__20_": 3,
|
||||
"3E__21_": 4,
|
||||
"3E__23_": 5,
|
||||
"3E__30_": 6,
|
||||
"3E__52_": 7,
|
||||
"3E___": 1,
|
||||
"43__25_": 11,
|
||||
"43___": 10,
|
||||
"A2__37_": 9,
|
||||
"A2___": 8,
|
||||
}
|
||||
},
|
||||
"status": 1,
|
||||
}
|
||||
with patch("pyhap.accessory_driver.AccessoryDriver.async_start"), patch(
|
||||
|
|
|
@ -262,7 +262,7 @@ async def test_homekit_setup(hass, hk_driver, mock_async_zeroconf):
|
|||
async_zeroconf_instance=zeroconf_mock,
|
||||
zeroconf_server=f"{uuid}-hap.local.",
|
||||
loader=ANY,
|
||||
iid_manager=ANY,
|
||||
iid_storage=ANY,
|
||||
)
|
||||
assert homekit.driver.safe_mode is False
|
||||
|
||||
|
@ -306,7 +306,7 @@ async def test_homekit_setup_ip_address(hass, hk_driver, mock_async_zeroconf):
|
|||
async_zeroconf_instance=mock_async_zeroconf,
|
||||
zeroconf_server=f"{uuid}-hap.local.",
|
||||
loader=ANY,
|
||||
iid_manager=ANY,
|
||||
iid_storage=ANY,
|
||||
)
|
||||
|
||||
|
||||
|
@ -350,7 +350,7 @@ async def test_homekit_setup_advertise_ip(hass, hk_driver, mock_async_zeroconf):
|
|||
async_zeroconf_instance=async_zeroconf_instance,
|
||||
zeroconf_server=f"{uuid}-hap.local.",
|
||||
loader=ANY,
|
||||
iid_manager=ANY,
|
||||
iid_storage=ANY,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for the HomeKit IID manager."""
|
||||
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from homeassistant.components.homekit.const import DOMAIN
|
||||
|
@ -8,9 +7,10 @@ from homeassistant.components.homekit.iidmanager import (
|
|||
AccessoryIIDStorage,
|
||||
get_iid_storage_filename_for_entry_id,
|
||||
)
|
||||
from homeassistant.helpers.json import json_loads
|
||||
from homeassistant.util.uuid import random_uuid_hex
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
|
||||
|
||||
async def test_iid_generation_and_restore(hass, iid_storage, hass_storage):
|
||||
|
@ -77,9 +77,6 @@ async def test_iid_generation_and_restore(hass, iid_storage, hass_storage):
|
|||
unique_service_unique_char_new_aid_iid1
|
||||
== unique_service_unique_char_new_aid_iid2
|
||||
)
|
||||
assert unique_service_unique_char_new_aid_iid1 != iid1
|
||||
assert unique_service_unique_char_new_aid_iid1 != unique_service_unique_char_iid1
|
||||
|
||||
await iid_storage.async_save()
|
||||
|
||||
iid_storage2 = AccessoryIIDStorage(hass, entry.entry_id)
|
||||
|
@ -99,3 +96,79 @@ async def test_iid_storage_filename(hass, iid_storage, hass_storage):
|
|||
assert iid_storage.store.path.endswith(
|
||||
get_iid_storage_filename_for_entry_id(entry.entry_id)
|
||||
)
|
||||
|
||||
|
||||
async def test_iid_migration_to_v2(hass, iid_storage, hass_storage):
|
||||
"""Test iid storage migration."""
|
||||
v1_iids = json_loads(load_fixture("iids_v1", DOMAIN))
|
||||
v2_iids = json_loads(load_fixture("iids_v2", DOMAIN))
|
||||
hass_storage["homekit.v1.iids"] = v1_iids
|
||||
hass_storage["homekit.v2.iids"] = v2_iids
|
||||
|
||||
iid_storage_v2 = AccessoryIIDStorage(hass, "v1")
|
||||
await iid_storage_v2.async_initialize()
|
||||
|
||||
iid_storage_v1 = AccessoryIIDStorage(hass, "v2")
|
||||
await iid_storage_v1.async_initialize()
|
||||
|
||||
assert iid_storage_v1.allocations == iid_storage_v2.allocations
|
||||
assert iid_storage_v1.allocated_iids == iid_storage_v2.allocated_iids
|
||||
|
||||
assert len(iid_storage_v2.allocations) == 12
|
||||
|
||||
for allocations in iid_storage_v2.allocations.values():
|
||||
assert allocations["3E___"] == 1
|
||||
|
||||
|
||||
async def test_iid_migration_to_v2_with_underscore(hass, iid_storage, hass_storage):
|
||||
"""Test iid storage migration with underscore."""
|
||||
v1_iids = json_loads(load_fixture("iids_v1_with_underscore", DOMAIN))
|
||||
v2_iids = json_loads(load_fixture("iids_v2_with_underscore", DOMAIN))
|
||||
hass_storage["homekit.v1_with_underscore.iids"] = v1_iids
|
||||
hass_storage["homekit.v2_with_underscore.iids"] = v2_iids
|
||||
|
||||
iid_storage_v2 = AccessoryIIDStorage(hass, "v1_with_underscore")
|
||||
await iid_storage_v2.async_initialize()
|
||||
|
||||
iid_storage_v1 = AccessoryIIDStorage(hass, "v2_with_underscore")
|
||||
await iid_storage_v1.async_initialize()
|
||||
|
||||
assert iid_storage_v1.allocations == iid_storage_v2.allocations
|
||||
assert iid_storage_v1.allocated_iids == iid_storage_v2.allocated_iids
|
||||
|
||||
assert len(iid_storage_v2.allocations) == 2
|
||||
|
||||
for allocations in iid_storage_v2.allocations.values():
|
||||
assert allocations["3E___"] == 1
|
||||
|
||||
|
||||
async def test_iid_generation_and_restore_v2(hass, iid_storage, hass_storage):
|
||||
"""Test generating iids and restoring them from storage."""
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
|
||||
iid_storage = AccessoryIIDStorage(hass, entry.entry_id)
|
||||
await iid_storage.async_initialize()
|
||||
not_accessory_info_service_iid = iid_storage.get_or_allocate_iid(
|
||||
1, "000000AA-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert not_accessory_info_service_iid == 2
|
||||
not_accessory_info_service_iid_2 = iid_storage.get_or_allocate_iid(
|
||||
1, "000000BB-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert not_accessory_info_service_iid_2 == 3
|
||||
not_accessory_info_service_iid_2 = iid_storage.get_or_allocate_iid(
|
||||
1, "000000BB-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert not_accessory_info_service_iid_2 == 3
|
||||
accessory_info_service_iid = iid_storage.get_or_allocate_iid(
|
||||
1, "0000003E-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert accessory_info_service_iid == 1
|
||||
accessory_info_service_iid = iid_storage.get_or_allocate_iid(
|
||||
1, "0000003E-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert accessory_info_service_iid == 1
|
||||
accessory_info_service_iid = iid_storage.get_or_allocate_iid(
|
||||
2, "0000003E-0000-1000-8000-0026BB765291", None, None, None
|
||||
)
|
||||
assert accessory_info_service_iid == 1
|
||||
|
|
Loading…
Reference in New Issue