Use system zeroconf singleton for homekit (#35502)
Zeroconf instances are expensive so we share a single instance instead of running multiple.
This commit is contained in:
parent
48899c7a1c
commit
751529feca
4 changed files with 41 additions and 1 deletions
|
@ -7,6 +7,7 @@ from aiohttp import web
|
|||
import voluptuous as vol
|
||||
from zeroconf import InterfaceChoice
|
||||
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.binary_sensor import DEVICE_CLASS_BATTERY_CHARGING
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
|
@ -242,6 +243,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
entry.entry_id,
|
||||
)
|
||||
await hass.async_add_executor_job(homekit.setup)
|
||||
await homekit.async_setup_zeroconf()
|
||||
|
||||
undo_listener = entry.add_update_listener(_async_update_listener)
|
||||
|
||||
|
@ -420,6 +422,7 @@ class HomeKit:
|
|||
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.async_stop)
|
||||
ip_addr = self._ip_address or get_local_ip()
|
||||
persist_file = get_persist_fullpath_for_entry_id(self.hass, self._entry_id)
|
||||
|
||||
self.driver = HomeDriver(
|
||||
self.hass,
|
||||
self._entry_id,
|
||||
|
@ -430,11 +433,18 @@ class HomeKit:
|
|||
advertised_address=self._advertise_ip,
|
||||
interface_choice=self._interface_choice,
|
||||
)
|
||||
|
||||
self.bridge = HomeBridge(self.hass, self.driver, self._name)
|
||||
if self._safe_mode:
|
||||
_LOGGER.debug("Safe_mode selected for %s", self._name)
|
||||
self.driver.safe_mode = True
|
||||
|
||||
async def async_setup_zeroconf(self):
|
||||
"""Share the system zeroconf instance."""
|
||||
# Replace the existing zeroconf instance.
|
||||
await self.hass.async_add_executor_job(self.driver.advertiser.close)
|
||||
self.driver.advertiser = await zeroconf.async_get_instance(self.hass)
|
||||
|
||||
def reset_accessories(self, entity_ids):
|
||||
"""Reset the accessory to load the latest configuration."""
|
||||
aid_storage = self.hass.data[DOMAIN][self._entry_id][AID_STORAGE]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"documentation": "https://www.home-assistant.io/integrations/homekit",
|
||||
"requirements": ["HAP-python==2.8.3","fnvhash==0.1.0","PyQRCode==1.2.1","base36==0.1.1","PyTurboJPEG==1.4.0"],
|
||||
"dependencies": ["http", "camera", "ffmpeg"],
|
||||
"after_dependencies": ["logbook"],
|
||||
"after_dependencies": ["logbook", "zeroconf"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"config_flow": true
|
||||
}
|
||||
|
|
|
@ -29,3 +29,10 @@ def events(hass):
|
|||
EVENT_HOMEKIT_CHANGED, ha_callback(lambda e: events.append(e))
|
||||
)
|
||||
yield events
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_zeroconf():
|
||||
"""Mock zeroconf."""
|
||||
with patch("homeassistant.components.zeroconf.HaZeroconf") as mock_zc:
|
||||
yield mock_zc.return_value
|
||||
|
|
|
@ -5,6 +5,7 @@ from typing import Dict
|
|||
import pytest
|
||||
from zeroconf import InterfaceChoice
|
||||
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.binary_sensor import DEVICE_CLASS_BATTERY_CHARGING
|
||||
from homeassistant.components.homekit import (
|
||||
MAX_DEVICES,
|
||||
|
@ -94,6 +95,7 @@ async def test_setup_min(hass):
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit:
|
||||
mock_homekit.return_value = homekit = Mock()
|
||||
type(homekit).async_start = AsyncMock()
|
||||
type(homekit).async_setup_zeroconf = AsyncMock()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -135,6 +137,7 @@ async def test_setup_auto_start_disabled(hass):
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit:
|
||||
mock_homekit.return_value = homekit = Mock()
|
||||
type(homekit).async_start = AsyncMock()
|
||||
type(homekit).async_setup_zeroconf = AsyncMock()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -787,6 +790,7 @@ async def test_setup_imported(hass):
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit:
|
||||
mock_homekit.return_value = homekit = Mock()
|
||||
type(homekit).async_start = AsyncMock()
|
||||
type(homekit).async_setup_zeroconf = AsyncMock()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -841,6 +845,7 @@ async def test_yaml_updates_update_config_entry_for_name(hass):
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit:
|
||||
mock_homekit.return_value = homekit = Mock()
|
||||
type(homekit).async_start = AsyncMock()
|
||||
type(homekit).async_setup_zeroconf = AsyncMock()
|
||||
assert await async_setup_component(
|
||||
hass, "homekit", {"homekit": {CONF_NAME: BRIDGE_NAME, CONF_PORT: 12345}}
|
||||
)
|
||||
|
@ -885,6 +890,24 @@ async def test_raise_config_entry_not_ready(hass):
|
|||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_homekit_uses_system_zeroconf(hass, hk_driver, mock_zeroconf):
|
||||
"""Test HomeKit uses system zeroconf."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={CONF_NAME: BRIDGE_NAME, CONF_PORT: DEFAULT_PORT},
|
||||
options={},
|
||||
)
|
||||
system_zc = await zeroconf.async_get_instance(hass)
|
||||
|
||||
with patch(f"{PATH_HOMEKIT}.accessories.HomeDriver", return_value=hk_driver), patch(
|
||||
f"{PATH_HOMEKIT}.HomeKit.async_start"
|
||||
):
|
||||
entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert hk_driver.advertiser == system_zc
|
||||
|
||||
|
||||
def _write_data(path: str, data: Dict) -> None:
|
||||
"""Write the data."""
|
||||
if not os.path.isdir(os.path.dirname(path)):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue