Adjust homekit controller pairing to have a new step for each potentially recoverable error (#38742)

* Adjust homekit controller pairing errors back to a single step

* adjust test

* Revert "Adjust homekit controller pairing errors back to a single step"

This reverts commit e5ed89bbbb.

* Revert "adjust test"

This reverts commit c2e9f21a8401c144315260f6fdf71ea8060f8ca3.

* adjust

* prune

* prune

* merge

* Update tests

* remove debug

* adjust

* Multiple steps

* adjust the test
This commit is contained in:
J. Nick Koston 2020-08-14 10:34:52 -05:00 committed by GitHub
parent 4ecdb1f19f
commit 483d09b9c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 54 deletions

View file

@ -242,37 +242,6 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
if self.controller is None:
await self._async_setup_controller()
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:
@ -307,14 +276,59 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow):
self.finish_pairing = None
errors["pairing_code"] = "pairing_failed"
if errors and "base" in errors:
return self.async_show_form(step_id="try_pair_later", errors=errors)
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
return await self.async_step_busy_error()
except aiohomekit.MaxTriesError:
# The accessory has received more than 100 unsuccessful auth
# attempts.
return await self.async_step_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")
return await self.async_step_protocol_error()
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Pairing attempt failed with an unhandled exception")
errors["pairing_code"] = "pairing_failed"
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)
async def async_step_busy_error(self, user_input=None):
"""Retry pairing after the accessory is busy."""
if user_input is not None:
return await self.async_step_pair()
return self.async_show_form(step_id="busy_error")
async def async_step_max_tries_error(self, user_input=None):
"""Retry pairing after the accessory has reached max tries."""
if user_input is not None:
return await self.async_step_pair()
return self.async_show_form(step_id="max_tries_error")
async def async_step_protocol_error(self, user_input=None):
"""Retry pairing after the accessory has a protocol error."""
if user_input is not None:
return await self.async_step_pair()
return self.async_show_form(step_id="protocol_error")
@callback
def _async_step_pair_show_form(self, errors=None):