Fix homekit_controller pairing retry when the first attempt is busy (#38605)
* Fix homekit_controller pairing retry If the device was busy on the first pairing attempt, it was not possible to retry. * always restart pairing on recoverable execptions * move code * malformed pin is safe to restart * make busy_error an abort * switch max retries, simplify tests * try pairing later * try pairing later * merge * s/tlv_error/protocol_error/g * Adjust wording
This commit is contained in:
parent
4e56339ba1
commit
9bb7b3b125
4 changed files with 137 additions and 63 deletions
|
@ -238,10 +238,42 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
|||
# in.
|
||||
|
||||
errors = {}
|
||||
|
||||
if self.controller is None:
|
||||
await self._async_setup_controller()
|
||||
|
||||
if pair_info:
|
||||
if not self.finish_pairing:
|
||||
# Its possible that the first try may have been busy so
|
||||
# we always check to see if self.finish_paring has been
|
||||
# set.
|
||||
discovery = await self.controller.find_ip_by_device_id(self.hkid)
|
||||
|
||||
try:
|
||||
self.finish_pairing = await discovery.start_pairing(self.hkid)
|
||||
|
||||
except aiohomekit.BusyError:
|
||||
# Already performing a pair setup operation with a different
|
||||
# controller
|
||||
errors["base"] = "busy_error"
|
||||
except aiohomekit.MaxTriesError:
|
||||
# The accessory has received more than 100 unsuccessful auth
|
||||
# attempts.
|
||||
errors["base"] = "max_tries_error"
|
||||
except aiohomekit.UnavailableError:
|
||||
# The accessory is already paired - cannot try to pair again.
|
||||
return self.async_abort(reason="already_paired")
|
||||
except aiohomekit.AccessoryNotFoundError:
|
||||
# Can no longer find the device on the network
|
||||
return self.async_abort(reason="accessory_not_found_error")
|
||||
except IndexError:
|
||||
# TLV error, usually not in pairing mode
|
||||
_LOGGER.exception("Pairing communication failed")
|
||||
errors["base"] = "protocol_error"
|
||||
except Exception: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Pairing attempt failed with an unhandled exception")
|
||||
errors["pairing_code"] = "pairing_failed"
|
||||
|
||||
if pair_info and self.finish_pairing:
|
||||
code = pair_info["pairing_code"]
|
||||
try:
|
||||
code = ensure_pin_format(code)
|
||||
|
@ -257,45 +289,33 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
|
|||
# PairVerify M4 - Device not recognised
|
||||
# PairVerify M4 - Ed25519 signature verification failed
|
||||
errors["pairing_code"] = "authentication_error"
|
||||
self.finish_pairing = None
|
||||
except aiohomekit.UnknownError:
|
||||
# An error occurred on the device whilst performing this
|
||||
# operation.
|
||||
errors["pairing_code"] = "unknown_error"
|
||||
self.finish_pairing = None
|
||||
except aiohomekit.MaxPeersError:
|
||||
# The device can't pair with any more accessories.
|
||||
errors["pairing_code"] = "max_peers_error"
|
||||
self.finish_pairing = None
|
||||
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")
|
||||
self.finish_pairing = None
|
||||
errors["pairing_code"] = "pairing_failed"
|
||||
|
||||
discovery = await self.controller.find_ip_by_device_id(self.hkid)
|
||||
|
||||
try:
|
||||
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 aiohomekit.MaxTriesError:
|
||||
# The accessory has received more than 100 unsuccessful auth
|
||||
# attempts.
|
||||
errors["pairing_code"] = "max_tries_error"
|
||||
except aiohomekit.UnavailableError:
|
||||
# The accessory is already paired - cannot try to pair again.
|
||||
return self.async_abort(reason="already_paired")
|
||||
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"
|
||||
if errors and "base" in errors:
|
||||
return self.async_show_form(step_id="try_pair_later", errors=errors)
|
||||
|
||||
return self._async_step_pair_show_form(errors)
|
||||
|
||||
async def async_step_try_pair_later(self, pair_info=None):
|
||||
"""Retry pairing after the accessory is busy or unavailable."""
|
||||
return await self.async_step_pair(pair_info)
|
||||
|
||||
@callback
|
||||
def _async_step_pair_show_form(self, errors=None):
|
||||
return self.async_show_form(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue