From e37a8cfa98262b67ffcff6cdfc70f148b4d2a188 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Sat, 5 Sep 2026 16:30:15 +1000 Subject: [PATCH] Leave Powerwall gateway host blank when discovery fails (#181336) --- .../components/teslemetry/config_flow.py | 14 +++---- .../components/teslemetry/test_config_flow.py | 42 +++++++++++++++++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/teslemetry/config_flow.py b/homeassistant/components/teslemetry/config_flow.py index c155bcbc68c2..cec2ed7198ff 100644 --- a/homeassistant/components/teslemetry/config_flow.py +++ b/homeassistant/components/teslemetry/config_flow.py @@ -6,12 +6,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, cast, override from aiohttp import ClientError -from aiopowerwall import ( - DEFAULT_GATEWAY_HOST, - PowerwallAuthenticationError, - PowerwallClient, - PowerwallError, -) +from aiopowerwall import PowerwallAuthenticationError, PowerwallClient, PowerwallError from tesla_fleet_api.const import ( AuthorizedClientKeyType, AuthorizedClientState, @@ -271,8 +266,11 @@ class EnergySiteSubentryFlowHandler(ConfigSubentryFlow): try: self._discovered_host = await energy_site.find_gateway_address() or "" except (ClientError, TeslaFleetError) as err: - LOGGER.debug("Gateway address discovery failed: %s", err) + LOGGER.warning("Gateway address discovery failed: %s", err) self._discovered_host = "" + else: + if not self._discovered_host: + LOGGER.warning("Gateway address discovery returned no address") path = self.hass.config.path(POWERWALL_KEY_FILE) keyholder = Teslemetry( @@ -424,7 +422,7 @@ class EnergySiteSubentryFlowHandler(ConfigSubentryFlow): { vol.Required( CONF_HOST, - default=self._discovered_host or DEFAULT_GATEWAY_HOST, + default=self._discovered_host or vol.UNDEFINED, ): str, vol.Required(CONF_PASSWORD): str, } diff --git a/tests/components/teslemetry/test_config_flow.py b/tests/components/teslemetry/test_config_flow.py index 5859531a489c..5cc5491a3994 100644 --- a/tests/components/teslemetry/test_config_flow.py +++ b/tests/components/teslemetry/test_config_flow.py @@ -9,7 +9,6 @@ from urllib.parse import parse_qs, urlparse from aiohttp import ClientConnectionError, ClientError from aiopowerwall import ( - DEFAULT_GATEWAY_HOST, PowerwallAuthenticationError, PowerwallConnectionError, PowerwallFaultError, @@ -25,6 +24,7 @@ from tesla_fleet_api.exceptions import ( TeslaFleetError, ) from tesla_fleet_api.teslemetry.energysite import AuthorizedClient, AuthorizedClients +import voluptuous as vol from homeassistant.components.application_credentials import ( ClientCredential, @@ -838,6 +838,14 @@ def _credentials_host_default(result: SubentryFlowResult) -> str: raise AssertionError("CONF_HOST field not found in credentials schema") +def _credentials_host_is_blank(result: SubentryFlowResult) -> bool: + """Return whether the CONF_HOST field carries no schema default (left blank).""" + for key in result["data_schema"].schema: + if key == CONF_HOST: + return key.default is vol.UNDEFINED + raise AssertionError("CONF_HOST field not found in credentials schema") + + @pytest.mark.usefixtures("mock_rsa_key") async def test_energy_subentry_pairing_requires_key_approval( hass: HomeAssistant, @@ -1249,10 +1257,10 @@ async def test_add_flow_aborts_when_entry_not_loaded(hass: HomeAssistant) -> Non @pytest.mark.usefixtures("mock_rsa_key") -async def test_gateway_discovery_failure_proceeds_without_host( +async def test_gateway_discovery_failure_leaves_host_blank( hass: HomeAssistant, ) -> None: - """A failed gateway-address discovery leaves the host default unset.""" + """A failed gateway-address discovery leaves the host field blank and proceeds.""" entry = await _setup_account_no_subentry(hass) with ( @@ -1271,7 +1279,33 @@ async def test_gateway_discovery_failure_proceeds_without_host( assert result["type"] is FlowResultType.FORM assert result["step_id"] == "credentials" - assert _credentials_host_default(result) == DEFAULT_GATEWAY_HOST + assert _credentials_host_is_blank(result) + + +@pytest.mark.usefixtures("mock_rsa_key") +async def test_gateway_discovery_empty_leaves_host_blank( + hass: HomeAssistant, +) -> None: + """Discovery returning no address (without raising) leaves the host blank and proceeds.""" + entry = await _setup_account_no_subentry(hass) + + with ( + patch( + "tesla_fleet_api.teslemetry.energysite.TeslemetryEnergySite.find_gateway_address", + new=AsyncMock(return_value=None), + ), + patch( + "tesla_fleet_api.teslemetry.energysite.TeslemetryEnergySite.find_authorized_clients", + new=AsyncMock( + return_value=_own_key_clients(AuthorizedClientState.VERIFIED) + ), + ), + ): + result = await _start_add_flow_select_site(hass, entry) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "credentials" + assert _credentials_host_is_blank(result) @pytest.mark.usefixtures("mock_rsa_key")