diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index d8aafb8e238..4c300e0a934 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -31,6 +31,7 @@ from homeassistant.util.decorator import Registry from .const import ( BRIDGE_NAME, + CONF_ADVERTISE_IP, CONF_AUTO_START, CONF_ENTITY_CONFIG, CONF_FEATURE_LIST, @@ -89,6 +90,9 @@ CONFIG_SCHEMA = vol.Schema( ), vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_IP_ADDRESS): vol.All(ipaddress.ip_address, cv.string), + vol.Optional(CONF_ADVERTISE_IP): vol.All( + ipaddress.ip_address, cv.string + ), vol.Optional(CONF_AUTO_START, default=DEFAULT_AUTO_START): cv.boolean, vol.Optional(CONF_SAFE_MODE, default=DEFAULT_SAFE_MODE): cv.boolean, vol.Optional(CONF_FILTER, default={}): FILTER_SCHEMA, @@ -112,13 +116,21 @@ async def async_setup(hass, config): name = conf[CONF_NAME] port = conf[CONF_PORT] ip_address = conf.get(CONF_IP_ADDRESS) + advertise_ip = conf.get(CONF_ADVERTISE_IP) auto_start = conf[CONF_AUTO_START] safe_mode = conf[CONF_SAFE_MODE] entity_filter = conf[CONF_FILTER] entity_config = conf[CONF_ENTITY_CONFIG] homekit = HomeKit( - hass, name, port, ip_address, entity_filter, entity_config, safe_mode + hass, + name, + port, + ip_address, + entity_filter, + entity_config, + safe_mode, + advertise_ip, ) await hass.async_add_executor_job(homekit.setup) @@ -265,7 +277,15 @@ class HomeKit: """Class to handle all actions between HomeKit and Home Assistant.""" def __init__( - self, hass, name, port, ip_address, entity_filter, entity_config, safe_mode + self, + hass, + name, + port, + ip_address, + entity_filter, + entity_config, + safe_mode, + advertise_ip=None, ): """Initialize a HomeKit object.""" self.hass = hass @@ -275,6 +295,7 @@ class HomeKit: self._filter = entity_filter self._config = entity_config self._safe_mode = safe_mode + self._advertise_ip = advertise_ip self.status = STATUS_READY self.bridge = None @@ -289,7 +310,11 @@ class HomeKit: ip_addr = self._ip_address or get_local_ip() path = self.hass.config.path(HOMEKIT_FILE) self.driver = HomeDriver( - self.hass, address=ip_addr, port=self._port, persist_file=path + self.hass, + address=ip_addr, + port=self._port, + persist_file=path, + advertised_address=self._advertise_ip, ) self.bridge = HomeBridge(self.hass, self.driver, self._name) if self._safe_mode: diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index d225225237f..82ec296da4b 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -10,6 +10,7 @@ ATTR_DISPLAY_NAME = "display_name" ATTR_VALUE = "value" # #### Config #### +CONF_ADVERTISE_IP = "advertise_ip" CONF_AUTO_START = "auto_start" CONF_ENTITY_CONFIG = "entity_config" CONF_FEATURE = "feature" diff --git a/tests/components/homekit/test_homekit.py b/tests/components/homekit/test_homekit.py index 61893af7008..97838eaa852 100644 --- a/tests/components/homekit/test_homekit.py +++ b/tests/components/homekit/test_homekit.py @@ -69,7 +69,7 @@ async def test_setup_min(hass): assert await setup.async_setup_component(hass, DOMAIN, {DOMAIN: {}}) mock_homekit.assert_any_call( - hass, BRIDGE_NAME, DEFAULT_PORT, None, ANY, {}, DEFAULT_SAFE_MODE + hass, BRIDGE_NAME, DEFAULT_PORT, None, ANY, {}, DEFAULT_SAFE_MODE, None ) assert mock_homekit().setup.called is True @@ -98,7 +98,7 @@ async def test_setup_auto_start_disabled(hass): assert await setup.async_setup_component(hass, DOMAIN, config) mock_homekit.assert_any_call( - hass, "Test Name", 11111, "172.0.0.0", ANY, {}, DEFAULT_SAFE_MODE + hass, "Test Name", 11111, "172.0.0.0", ANY, {}, DEFAULT_SAFE_MODE, None ) assert mock_homekit().setup.called is True @@ -136,7 +136,11 @@ async def test_homekit_setup(hass, hk_driver): path = hass.config.path(HOMEKIT_FILE) assert isinstance(homekit.bridge, HomeBridge) mock_driver.assert_called_with( - hass, address=IP_ADDRESS, port=DEFAULT_PORT, persist_file=path + hass, + address=IP_ADDRESS, + port=DEFAULT_PORT, + persist_file=path, + advertised_address=None, ) assert homekit.driver.safe_mode is False @@ -153,7 +157,30 @@ async def test_homekit_setup_ip_address(hass, hk_driver): ) as mock_driver: await hass.async_add_job(homekit.setup) mock_driver.assert_called_with( - hass, address="172.0.0.0", port=DEFAULT_PORT, persist_file=ANY + hass, + address="172.0.0.0", + port=DEFAULT_PORT, + persist_file=ANY, + advertised_address=None, + ) + + +async def test_homekit_setup_advertise_ip(hass, hk_driver): + """Test setup with given IP address to advertise.""" + homekit = HomeKit( + hass, BRIDGE_NAME, DEFAULT_PORT, "0.0.0.0", {}, {}, None, "192.168.1.100" + ) + + with patch( + PATH_HOMEKIT + ".accessories.HomeDriver", return_value=hk_driver + ) as mock_driver: + await hass.async_add_job(homekit.setup) + mock_driver.assert_called_with( + hass, + address="0.0.0.0", + port=DEFAULT_PORT, + persist_file=ANY, + advertised_address="192.168.1.100", )