Improve error when HomeKit accessory underlying entity is missing (#51713)

* Improve error when HomeKit accessory underlying entity is missing

* docstring in test
This commit is contained in:
J. Nick Koston 2021-06-13 12:27:04 -10:00 committed by GitHub
parent d755952148
commit 75d6ffebc8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 2 deletions

View file

@ -599,7 +599,8 @@ class HomeKit:
await self.hass.async_add_executor_job(self.setup, async_zc_instance)
self.aid_storage = AccessoryAidStorage(self.hass, self._entry_id)
await self.aid_storage.async_initialize()
await self._async_create_accessories()
if not await self._async_create_accessories():
return
self._async_register_bridge()
_LOGGER.debug("Driver start for %s", self._name)
await self.driver.async_start()
@ -666,6 +667,13 @@ class HomeKit:
"""Create the accessories."""
entity_states = await self.async_configure_accessories()
if self._homekit_mode == HOMEKIT_MODE_ACCESSORY:
if not entity_states:
_LOGGER.error(
"HomeKit %s cannot startup: entity not available: %s",
self._name,
self._filter.config,
)
return False
state = entity_states[0]
conf = self._config.pop(state.entity_id, {})
acc = get_accessory(self.hass, self.driver, state, STANDALONE_AID, conf)
@ -677,6 +685,7 @@ class HomeKit:
# No need to load/persist as we do it in setup
self.driver.accessory = acc
return True
async def async_stop(self, *args):
"""Stop the accessory driver."""

View file

@ -54,7 +54,15 @@ from homeassistant.const import (
)
from homeassistant.core import State
from homeassistant.helpers import device_registry
from homeassistant.helpers.entityfilter import generate_filter
from homeassistant.helpers.entityfilter import (
CONF_EXCLUDE_DOMAINS,
CONF_EXCLUDE_ENTITIES,
CONF_EXCLUDE_ENTITY_GLOBS,
CONF_INCLUDE_DOMAINS,
CONF_INCLUDE_ENTITIES,
CONF_INCLUDE_ENTITY_GLOBS,
convert_filter,
)
from homeassistant.setup import async_setup_component
from homeassistant.util import json as json_util
@ -65,6 +73,27 @@ from tests.common import MockConfigEntry, mock_device_registry, mock_registry
IP_ADDRESS = "127.0.0.1"
def generate_filter(
include_domains,
include_entities,
exclude_domains,
exclude_entites,
include_globs=None,
exclude_globs=None,
):
"""Generate an entity filter using the standard method."""
return convert_filter(
{
CONF_INCLUDE_DOMAINS: include_domains,
CONF_INCLUDE_ENTITIES: include_entities,
CONF_EXCLUDE_DOMAINS: exclude_domains,
CONF_EXCLUDE_ENTITIES: exclude_entites,
CONF_INCLUDE_ENTITY_GLOBS: include_globs or [],
CONF_EXCLUDE_ENTITY_GLOBS: exclude_globs or [],
}
)
@pytest.fixture(autouse=True)
def always_patch_driver(hk_driver):
"""Load the hk_driver fixture."""
@ -1173,6 +1202,31 @@ async def test_homekit_start_in_accessory_mode(
assert homekit.status == STATUS_RUNNING
async def test_homekit_start_in_accessory_mode_missing_entity(
hass, hk_driver, mock_zeroconf, device_reg, caplog
):
"""Test HomeKit start method in accessory mode when entity is not available."""
entry = await async_init_integration(hass)
homekit = _mock_homekit(hass, entry, HOMEKIT_MODE_ACCESSORY)
homekit.bridge = Mock()
homekit.bridge.accessories = []
homekit.driver = hk_driver
homekit.driver.accessory = Accessory(hk_driver, "any")
with patch(f"{PATH_HOMEKIT}.HomeKit.add_bridge_accessory") as mock_add_acc, patch(
f"{PATH_HOMEKIT}.show_setup_message"
), patch("pyhap.accessory_driver.AccessoryDriver.async_start"):
await homekit.async_start()
await hass.async_block_till_done()
mock_add_acc.assert_not_called()
assert homekit.status == STATUS_WAIT
assert "entity not available" in caplog.text
async def test_wait_for_port_to_free(hass, hk_driver, mock_zeroconf, caplog):
"""Test we wait for the port to free before declaring unload success."""
await async_setup_component(hass, "persistent_notification", {})