Support HomeKit Controller Thread Provisioning (#87809)

This commit is contained in:
Jc2k 2023-02-15 16:41:07 +00:00 committed by GitHub
parent 402170d49e
commit f5a05c1bd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 220 additions and 4 deletions

View file

@ -9,6 +9,7 @@ from types import MappingProxyType
from typing import Any
from aiohomekit import Controller
from aiohomekit.controller import TransportType
from aiohomekit.exceptions import (
AccessoryDisconnectedError,
AccessoryNotFoundError,
@ -16,11 +17,13 @@ from aiohomekit.exceptions import (
)
from aiohomekit.model import Accessories, Accessory, Transport
from aiohomekit.model.characteristics import Characteristic
from aiohomekit.model.services import Service
from aiohomekit.model.services import Service, ServicesTypes
from homeassistant.components.thread.dataset_store import async_get_preferred_dataset
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_VIA_DEVICE, EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import CoreState, Event, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -772,6 +775,59 @@ class HKDevice:
"""Control a HomeKit device state from Home Assistant."""
await self.pairing.put_characteristics(characteristics)
@property
def is_unprovisioned_thread_device(self) -> bool:
"""Is this a thread capable device not connected by CoAP."""
if self.pairing.controller.transport_type != TransportType.BLE:
return False
if not self.entity_map.aid(1).services.first(
service_type=ServicesTypes.THREAD_TRANSPORT
):
return False
return True
async def async_thread_provision(self) -> None:
"""Migrate a HomeKit pairing to CoAP (Thread)."""
if self.pairing.controller.transport_type == TransportType.COAP:
raise HomeAssistantError("Already connected to a thread network")
if not (dataset := await async_get_preferred_dataset(self.hass)):
raise HomeAssistantError("No thread network credentials available")
await self.pairing.thread_provision(dataset)
try:
discovery = (
await self.hass.data[CONTROLLER]
.transports[TransportType.COAP]
.async_find(self.unique_id, timeout=30)
)
self.hass.config_entries.async_update_entry(
self.config_entry,
data={
**self.config_entry.data,
"Connection": "CoAP",
"AccessoryIP": discovery.description.address,
"AccessoryPort": discovery.description.port,
},
)
_LOGGER.debug(
"%s: Found device on local network, migrating integration to Thread",
self.unique_id,
)
except AccessoryNotFoundError as exc:
_LOGGER.debug(
"%s: Failed to appear on local network as a Thread device, reverting to BLE",
self.unique_id,
)
raise HomeAssistantError("Could not migrate device to Thread") from exc
finally:
await self.hass.config_entries.async_reload(self.config_entry.entry_id)
@property
def unique_id(self) -> str:
"""Return a unique id for this accessory or bridge.