mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Handle homekit accessories where the pairing flag is wrong (#53385)
This commit is contained in:
parent
bf3a16eed4
commit
0db160e372
@ -3,6 +3,7 @@ import logging
|
||||
import re
|
||||
|
||||
import aiohomekit
|
||||
from aiohomekit.exceptions import AuthenticationError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
@ -270,7 +271,29 @@ class HomekitControllerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
# invalid. Remove it automatically.
|
||||
existing = find_existing_host(self.hass, hkid)
|
||||
if not paired and existing:
|
||||
await self.hass.config_entries.async_remove(existing.entry_id)
|
||||
if self.controller is None:
|
||||
await self._async_setup_controller()
|
||||
|
||||
pairing = self.controller.load_pairing(
|
||||
existing.data["AccessoryPairingID"], dict(existing.data)
|
||||
)
|
||||
try:
|
||||
await pairing.list_accessories_and_characteristics()
|
||||
_LOGGER.debug(
|
||||
"%s (%s - %s) claims to be unpaired but isn't. It's implementation of HomeKit is defective or a zeroconf relay is broadcasting stale data",
|
||||
name,
|
||||
model,
|
||||
hkid,
|
||||
)
|
||||
return self.async_abort(reason="already_paired")
|
||||
except AuthenticationError:
|
||||
_LOGGER.debug(
|
||||
"%s (%s - %s) is unpaired. Removing invalid pairing for this device",
|
||||
name,
|
||||
model,
|
||||
hkid,
|
||||
)
|
||||
await self.hass.config_entries.async_remove(existing.entry_id)
|
||||
|
||||
# Set unique-id and error out if it's already configured
|
||||
self._abort_if_unique_id_configured(updates=updated_ip_port)
|
||||
|
@ -4,6 +4,7 @@ import unittest.mock
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import aiohomekit
|
||||
from aiohomekit.exceptions import AuthenticationError
|
||||
from aiohomekit.model import Accessories, Accessory
|
||||
from aiohomekit.model.characteristics import CharacteristicsTypes
|
||||
from aiohomekit.model.services import ServicesTypes
|
||||
@ -351,8 +352,48 @@ async def test_discovery_does_not_ignore_non_homekit(hass, controller):
|
||||
assert result["type"] == "form"
|
||||
|
||||
|
||||
async def test_discovery_broken_pairing_flag(hass, controller):
|
||||
"""
|
||||
There is already a config entry for the pairing and its pairing flag is wrong in zeroconf.
|
||||
|
||||
We have seen this particular implementation error in 2 different devices.
|
||||
"""
|
||||
await controller.add_paired_device(Accessories(), "00:00:00:00:00:00")
|
||||
|
||||
MockConfigEntry(
|
||||
domain="homekit_controller",
|
||||
data={"AccessoryPairingID": "00:00:00:00:00:00"},
|
||||
unique_id="00:00:00:00:00:00",
|
||||
).add_to_hass(hass)
|
||||
|
||||
# We just added a mock config entry so it must be visible in hass
|
||||
assert len(hass.config_entries.async_entries()) == 1
|
||||
|
||||
device = setup_mock_accessory(controller)
|
||||
discovery_info = get_device_discovery_info(device)
|
||||
|
||||
# Make sure that we are pairable
|
||||
assert discovery_info["properties"]["sf"] != 0x0
|
||||
|
||||
# Device is discovered
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"homekit_controller",
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data=discovery_info,
|
||||
)
|
||||
|
||||
# Should still be paired.
|
||||
config_entry_count = len(hass.config_entries.async_entries())
|
||||
assert config_entry_count == 1
|
||||
|
||||
# Even though discovered as pairable, we bail out as already paired.
|
||||
assert result["reason"] == "already_paired"
|
||||
|
||||
|
||||
async def test_discovery_invalid_config_entry(hass, controller):
|
||||
"""There is already a config entry for the pairing id but it's invalid."""
|
||||
pairing = await controller.add_paired_device(Accessories(), "00:00:00:00:00:00")
|
||||
|
||||
MockConfigEntry(
|
||||
domain="homekit_controller",
|
||||
data={"AccessoryPairingID": "00:00:00:00:00:00"},
|
||||
@ -366,11 +407,16 @@ async def test_discovery_invalid_config_entry(hass, 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,
|
||||
)
|
||||
with patch.object(
|
||||
pairing,
|
||||
"list_accessories_and_characteristics",
|
||||
side_effect=AuthenticationError("Invalid pairing keys"),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"homekit_controller",
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data=discovery_info,
|
||||
)
|
||||
|
||||
# Discovery of a HKID that is in a pairable state but for which there is
|
||||
# already a config entry - in that case the stale config entry is
|
||||
|
Loading…
x
Reference in New Issue
Block a user