Disconnect homekit reload dispatcher when start did not finish (#183303)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Franck Nijhof
2026-09-29 17:05:20 +01:00
committed by GitHub
co-authored by Claude
parent 1c1dcfd950
commit 69319a7137
4 changed files with 23 additions and 5 deletions
+5 -5
View File
@@ -424,9 +424,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: HomeKitConfigEntry) ->
async_dismiss_setup_message(hass, entry.entry_id)
entry_data = entry.runtime_data
homekit = entry_data.homekit
if homekit.status == STATUS_RUNNING:
await homekit.async_stop()
await homekit.async_stop()
logged_shutdown_wait = False
for _ in range(SHUTDOWN_TIMEOUT):
@@ -1144,12 +1142,14 @@ class HomeKit:
async def async_stop(self, *args: Any) -> None:
"""Stop the accessory driver."""
# The dispatcher is connected before the start can bail out early.
if self._cancel_reload_dispatcher:
self._cancel_reload_dispatcher()
self._cancel_reload_dispatcher = None
if self.status != STATUS_RUNNING:
return
async with self._reset_lock:
self.status = STATUS_STOPPED
assert self._cancel_reload_dispatcher is not None
self._cancel_reload_dispatcher()
_LOGGER.debug("Driver stop for %s", self._name)
if self.driver:
await self.driver.async_stop()
@@ -401,6 +401,7 @@ async def test_options_flow_devices(
with patch("homeassistant.components.homekit.HomeKit") as mock_homekit:
mock_homekit.return_value = homekit = Mock(bridge=None, driver=None)
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(hass, DOMAIN, {"homekit": {}})
assert await async_setup_component(hass, "homeassistant", {})
assert await async_setup_component(hass, "demo", {"demo": {}})
+16
View File
@@ -33,6 +33,7 @@ from homeassistant.components.homekit.const import (
HOMEKIT_MODE_BRIDGE,
SERVICE_HOMEKIT_RESET_ACCESSORY,
SERVICE_HOMEKIT_UNPAIR,
SIGNAL_RELOAD_ENTITIES,
)
from homeassistant.components.homekit.models import HomeKitEntryData
from homeassistant.components.homekit.type_triggers import DeviceTriggerAccessory
@@ -67,6 +68,7 @@ from homeassistant.helpers import (
entity_registry as er,
instance_id,
)
from homeassistant.helpers.dispatcher import DATA_DISPATCHER
from homeassistant.helpers.entityfilter import (
CONF_EXCLUDE_DOMAINS,
CONF_EXCLUDE_ENTITIES,
@@ -184,6 +186,7 @@ async def test_setup_min(hass: HomeAssistant) -> None:
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
@@ -229,6 +232,7 @@ async def test_removing_entry(port_mock, hass: HomeAssistant) -> None:
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
@@ -1849,6 +1853,7 @@ async def test_yaml_updates_update_config_entry_for_name(hass: HomeAssistant) ->
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(
hass, DOMAIN, {"homekit": {CONF_NAME: BRIDGE_NAME, CONF_PORT: 12345}}
)
@@ -1897,6 +1902,7 @@ async def test_yaml_can_link_with_default_name(hass: HomeAssistant) -> None:
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(
hass,
DOMAIN,
@@ -1943,6 +1949,7 @@ async def test_yaml_can_link_with_port(hass: HomeAssistant) -> None:
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(
hass,
DOMAIN,
@@ -2432,11 +2439,13 @@ async def test_reload(mock_port_available: MagicMock, hass: HomeAssistant) -> No
):
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(
hass, DOMAIN, {"homekit": {CONF_NAME: "reloadable", CONF_PORT: 12345}}
)
await hass.async_block_till_done()
old_homekit = homekit
mock_homekit.assert_any_call(
hass,
"reloadable",
@@ -2469,6 +2478,7 @@ async def test_reload(mock_port_available: MagicMock, hass: HomeAssistant) -> No
):
mock_homekit2.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
await hass.services.async_call(
"homekit",
SERVICE_RELOAD,
@@ -2477,6 +2487,7 @@ async def test_reload(mock_port_available: MagicMock, hass: HomeAssistant) -> No
)
await hass.async_block_till_done()
old_homekit.async_stop.assert_awaited_once()
mock_homekit2.assert_any_call(
hass,
"reloadable",
@@ -2604,6 +2615,11 @@ async def test_homekit_start_in_accessory_mode_missing_entity(
assert "entity not available" in caplog.text
signal = SIGNAL_RELOAD_ENTITIES.format(entry.entry_id)
assert hass.data[DATA_DISPATCHER][signal]
await homekit.async_stop()
assert not hass.data[DATA_DISPATCHER][signal]
@pytest.mark.usefixtures("mock_async_zeroconf")
async def test_wait_for_port_to_free(
+1
View File
@@ -32,6 +32,7 @@ async def test_humanify_homekit_changed_event(hass: HomeAssistant, hk_driver) ->
with patch("homeassistant.components.homekit.HomeKit") as mock_homekit:
mock_homekit.return_value = homekit = Mock()
type(homekit).async_start = AsyncMock()
type(homekit).async_stop = AsyncMock()
assert await async_setup_component(hass, DOMAIN, {"homekit": {}})
assert await async_setup_component(hass, "logbook", {})
await hass.async_block_till_done()