Show HomeKit Controller unhandled pairing error reason in the UI (#82505)
parent
a7caa038be
commit
7df711f1f3
|
@ -420,6 +420,7 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
# Should never call this step without setting self.hkid
|
||||
assert self.hkid
|
||||
description_placeholders = {}
|
||||
|
||||
errors = {}
|
||||
|
||||
|
@ -465,10 +466,11 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return self.async_abort(reason="accessory_not_found_error")
|
||||
except InsecureSetupCode:
|
||||
errors["pairing_code"] = "insecure_setup_code"
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Pairing attempt failed with an unhandled exception")
|
||||
self.finish_pairing = None
|
||||
errors["pairing_code"] = "pairing_failed"
|
||||
description_placeholders["error"] = str(err)
|
||||
|
||||
if not self.finish_pairing:
|
||||
# Its possible that the first try may have been busy so
|
||||
|
@ -496,11 +498,12 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
# 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
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Pairing attempt failed with an unhandled exception")
|
||||
errors["pairing_code"] = "pairing_failed"
|
||||
description_placeholders["error"] = str(err)
|
||||
|
||||
return self._async_step_pair_show_form(errors)
|
||||
return self._async_step_pair_show_form(errors, description_placeholders)
|
||||
|
||||
async def async_step_busy_error(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
|
@ -531,7 +534,9 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
@callback
|
||||
def _async_step_pair_show_form(
|
||||
self, errors: dict[str, str] | None = None
|
||||
self,
|
||||
errors: dict[str, str] | None = None,
|
||||
description_placeholders: dict[str, str] | None = None,
|
||||
) -> FlowResult:
|
||||
assert self.category
|
||||
|
||||
|
@ -547,7 +552,7 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return self.async_show_form(
|
||||
step_id="pair",
|
||||
errors=errors or {},
|
||||
description_placeholders=placeholders,
|
||||
description_placeholders=placeholders | (description_placeholders or {}),
|
||||
data_schema=vol.Schema(schema),
|
||||
)
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
"unknown_error": "Device reported an unknown error. Pairing failed.",
|
||||
"authentication_error": "Incorrect HomeKit code. Please check it and try again.",
|
||||
"max_peers_error": "Device refused to add pairing as it has no free pairing storage.",
|
||||
"pairing_failed": "An unhandled error occurred while attempting to pair with this device. This may be a temporary failure or your device may not be supported currently."
|
||||
"pairing_failed": "An unhandled error occurred while attempting to pair with this device. This may be a temporary failure or your device may not be supported currently: {error}"
|
||||
},
|
||||
"abort": {
|
||||
"no_devices": "No unpaired devices could be found",
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"authentication_error": "Incorrect HomeKit code. Please check it and try again.",
|
||||
"insecure_setup_code": "The requested setup code is insecure because of its trivial nature. This accessory fails to meet basic security requirements.",
|
||||
"max_peers_error": "Device refused to add pairing as it has no free pairing storage.",
|
||||
"pairing_failed": "An unhandled error occurred while attempting to pair with this device. This may be a temporary failure or your device may not be supported currently.",
|
||||
"pairing_failed": "An unhandled error occurred while attempting to pair with this device. This may be a temporary failure or your device may not be supported currently: {error}",
|
||||
"unable_to_pair": "Unable to pair, please try again.",
|
||||
"unknown_error": "Device reported an unknown error. Pairing failed."
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ from aiohomekit.exceptions import AuthenticationError
|
|||
from aiohomekit.model import Accessories, Accessory
|
||||
from aiohomekit.model.characteristics import CharacteristicsTypes
|
||||
from aiohomekit.model.services import ServicesTypes
|
||||
from bleak.exc import BleakError
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -743,6 +744,57 @@ async def test_pair_form_errors_on_finish(hass, controller, exception, expected)
|
|||
}
|
||||
|
||||
|
||||
async def test_pair_unknown_errors(hass, controller):
|
||||
"""Test describing unknown errors."""
|
||||
device = setup_mock_accessory(controller)
|
||||
discovery_info = get_device_discovery_info(device)
|
||||
|
||||
# Device is discovered
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"homekit_controller",
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data=discovery_info,
|
||||
)
|
||||
|
||||
assert get_flow_context(hass, result) == {
|
||||
"title_placeholders": {"name": "TestDevice", "category": "Outlet"},
|
||||
"unique_id": "00:00:00:00:00:00",
|
||||
"source": config_entries.SOURCE_ZEROCONF,
|
||||
}
|
||||
|
||||
# User initiates pairing - this triggers the device to show a pairing code
|
||||
# and then HA to show a pairing form
|
||||
finish_pairing = unittest.mock.AsyncMock(
|
||||
side_effect=BleakError("The bluetooth connection failed")
|
||||
)
|
||||
with patch.object(device, "async_start_pairing", return_value=finish_pairing):
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert get_flow_context(hass, result) == {
|
||||
"title_placeholders": {"name": "TestDevice", "category": "Outlet"},
|
||||
"unique_id": "00:00:00:00:00:00",
|
||||
"source": config_entries.SOURCE_ZEROCONF,
|
||||
}
|
||||
|
||||
# User enters pairing code
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={"pairing_code": "111-22-333"}
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"]["pairing_code"] == "pairing_failed"
|
||||
assert (
|
||||
result["description_placeholders"]["error"] == "The bluetooth connection failed"
|
||||
)
|
||||
|
||||
assert get_flow_context(hass, result) == {
|
||||
"title_placeholders": {"name": "TestDevice", "category": "Outlet"},
|
||||
"unique_id": "00:00:00:00:00:00",
|
||||
"source": config_entries.SOURCE_ZEROCONF,
|
||||
"pairing": True,
|
||||
}
|
||||
|
||||
|
||||
async def test_user_works(hass, controller):
|
||||
"""Test user initiated disovers devices."""
|
||||
setup_mock_accessory(controller)
|
||||
|
|
Loading…
Reference in New Issue