mirror of
https://github.com/home-assistant/core.git
synced 2025-11-16 14:30:22 +00:00
Refactor homekit_controller to be fully asynchronous (#32111)
* Port homekit_controller to aiohomekit * Remove succeed() test helper * Remove fail() test helper
This commit is contained in:
@@ -4,8 +4,9 @@ import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
import homekit
|
||||
from homekit.controller.ip_implementation import IpPairing
|
||||
import aiohomekit
|
||||
from aiohomekit import Controller
|
||||
from aiohomekit.controller.ip import IpPairing
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
@@ -72,7 +73,7 @@ def ensure_pin_format(pin):
|
||||
"""
|
||||
match = PIN_FORMAT.search(pin)
|
||||
if not match:
|
||||
raise homekit.exceptions.MalformedPinError(f"Invalid PIN code f{pin}")
|
||||
raise aiohomekit.exceptions.MalformedPinError(f"Invalid PIN code f{pin}")
|
||||
return "{}-{}-{}".format(*match.groups())
|
||||
|
||||
|
||||
@@ -88,7 +89,7 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
||||
self.model = None
|
||||
self.hkid = None
|
||||
self.devices = {}
|
||||
self.controller = homekit.Controller()
|
||||
self.controller = Controller()
|
||||
self.finish_pairing = None
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
@@ -97,22 +98,22 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
||||
|
||||
if user_input is not None:
|
||||
key = user_input["device"]
|
||||
self.hkid = self.devices[key]["id"]
|
||||
self.model = self.devices[key]["md"]
|
||||
self.hkid = self.devices[key].device_id
|
||||
self.model = self.devices[key].info["md"]
|
||||
await self.async_set_unique_id(
|
||||
normalize_hkid(self.hkid), raise_on_progress=False
|
||||
)
|
||||
return await self.async_step_pair()
|
||||
|
||||
all_hosts = await self.hass.async_add_executor_job(self.controller.discover, 5)
|
||||
all_hosts = await self.controller.discover_ip()
|
||||
|
||||
self.devices = {}
|
||||
for host in all_hosts:
|
||||
status_flags = int(host["sf"])
|
||||
status_flags = int(host.info["sf"])
|
||||
paired = not status_flags & 0x01
|
||||
if paired:
|
||||
continue
|
||||
self.devices[host["name"]] = host
|
||||
self.devices[host.info["name"]] = host
|
||||
|
||||
if not self.devices:
|
||||
return self.async_abort(reason="no_devices")
|
||||
@@ -130,10 +131,11 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
||||
unique_id = user_input["unique_id"]
|
||||
await self.async_set_unique_id(unique_id)
|
||||
|
||||
records = await self.hass.async_add_executor_job(self.controller.discover, 5)
|
||||
for record in records:
|
||||
if normalize_hkid(record["id"]) != unique_id:
|
||||
devices = await self.controller.discover_ip(5)
|
||||
for device in devices:
|
||||
if normalize_hkid(device.device_id) != unique_id:
|
||||
continue
|
||||
record = device.info
|
||||
return await self.async_step_zeroconf(
|
||||
{
|
||||
"host": record["address"],
|
||||
@@ -295,55 +297,49 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
||||
code = pair_info["pairing_code"]
|
||||
try:
|
||||
code = ensure_pin_format(code)
|
||||
|
||||
await self.hass.async_add_executor_job(self.finish_pairing, code)
|
||||
|
||||
pairing = self.controller.pairings.get(self.hkid)
|
||||
if pairing:
|
||||
return await self._entry_from_accessory(pairing)
|
||||
|
||||
errors["pairing_code"] = "unable_to_pair"
|
||||
except homekit.exceptions.MalformedPinError:
|
||||
pairing = await self.finish_pairing(code)
|
||||
return await self._entry_from_accessory(pairing)
|
||||
except aiohomekit.exceptions.MalformedPinError:
|
||||
# Library claimed pin was invalid before even making an API call
|
||||
errors["pairing_code"] = "authentication_error"
|
||||
except homekit.AuthenticationError:
|
||||
except aiohomekit.AuthenticationError:
|
||||
# PairSetup M4 - SRP proof failed
|
||||
# PairSetup M6 - Ed25519 signature verification failed
|
||||
# PairVerify M4 - Decryption failed
|
||||
# PairVerify M4 - Device not recognised
|
||||
# PairVerify M4 - Ed25519 signature verification failed
|
||||
errors["pairing_code"] = "authentication_error"
|
||||
except homekit.UnknownError:
|
||||
except aiohomekit.UnknownError:
|
||||
# An error occurred on the device whilst performing this
|
||||
# operation.
|
||||
errors["pairing_code"] = "unknown_error"
|
||||
except homekit.MaxPeersError:
|
||||
except aiohomekit.MaxPeersError:
|
||||
# The device can't pair with any more accessories.
|
||||
errors["pairing_code"] = "max_peers_error"
|
||||
except homekit.AccessoryNotFoundError:
|
||||
except aiohomekit.AccessoryNotFoundError:
|
||||
# Can no longer find the device on the network
|
||||
return self.async_abort(reason="accessory_not_found_error")
|
||||
except Exception: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Pairing attempt failed with an unhandled exception")
|
||||
errors["pairing_code"] = "pairing_failed"
|
||||
|
||||
start_pairing = self.controller.start_pairing
|
||||
discovery = await self.controller.find_ip_by_device_id(self.hkid)
|
||||
|
||||
try:
|
||||
self.finish_pairing = await self.hass.async_add_executor_job(
|
||||
start_pairing, self.hkid, self.hkid
|
||||
)
|
||||
except homekit.BusyError:
|
||||
self.finish_pairing = await discovery.start_pairing(self.hkid)
|
||||
|
||||
except aiohomekit.BusyError:
|
||||
# Already performing a pair setup operation with a different
|
||||
# controller
|
||||
errors["pairing_code"] = "busy_error"
|
||||
except homekit.MaxTriesError:
|
||||
except aiohomekit.MaxTriesError:
|
||||
# The accessory has received more than 100 unsuccessful auth
|
||||
# attempts.
|
||||
errors["pairing_code"] = "max_tries_error"
|
||||
except homekit.UnavailableError:
|
||||
except aiohomekit.UnavailableError:
|
||||
# The accessory is already paired - cannot try to pair again.
|
||||
return self.async_abort(reason="already_paired")
|
||||
except homekit.AccessoryNotFoundError:
|
||||
except aiohomekit.AccessoryNotFoundError:
|
||||
# Can no longer find the device on the network
|
||||
return self.async_abort(reason="accessory_not_found_error")
|
||||
except Exception: # pylint: disable=broad-except
|
||||
@@ -376,9 +372,7 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
||||
# the same time.
|
||||
accessories = pairing_data.pop("accessories", None)
|
||||
if not accessories:
|
||||
accessories = await self.hass.async_add_executor_job(
|
||||
pairing.list_accessories_and_characteristics
|
||||
)
|
||||
accessories = await pairing.list_accessories_and_characteristics()
|
||||
|
||||
bridge_info = get_bridge_information(accessories)
|
||||
name = get_accessory_name(bridge_info)
|
||||
|
||||
Reference in New Issue
Block a user