From e1efb35a971d0396200553bf46a83a3ccb96b4dd Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Sat, 5 Sep 2026 16:24:38 +1000 Subject: [PATCH] Split Teslemetry local-control abort into two reasons (#181319) --- .../components/teslemetry/config_flow.py | 14 ++++-- .../components/teslemetry/strings.json | 3 +- .../components/teslemetry/test_config_flow.py | 48 ++++++++++++++++++- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/teslemetry/config_flow.py b/homeassistant/components/teslemetry/config_flow.py index c82e882f8d81..c155bcbc68c2 100644 --- a/homeassistant/components/teslemetry/config_flow.py +++ b/homeassistant/components/teslemetry/config_flow.py @@ -219,14 +219,20 @@ class EnergySiteSubentryFlowHandler(ConfigSubentryFlow): for subentry in entry.subentries.values() if subentry.subentry_type == SUBENTRY_TYPE_ENERGY_SITE } - available = { - str(energy_data.id): energy_data + local_control_sites = [ + energy_data for energy_data in entry.runtime_data.energysites if energy_data.can_local_control - and str(energy_data.id) not in added_site_ids + ] + available = { + str(energy_data.id): energy_data + for energy_data in local_control_sites + if str(energy_data.id) not in added_site_ids } if not available: - return self.async_abort(reason="no_energy_sites") + return self.async_abort( + reason="all_sites_added" if local_control_sites else "no_powerwall" + ) if user_input is not None: energy_data = available[user_input[CONF_SITE_ID]] diff --git a/homeassistant/components/teslemetry/strings.json b/homeassistant/components/teslemetry/strings.json index c2ce2080a615..2613bdae8214 100644 --- a/homeassistant/components/teslemetry/strings.json +++ b/homeassistant/components/teslemetry/strings.json @@ -49,9 +49,10 @@ "config_subentries": { "energy_site": { "abort": { + "all_sites_added": "Every accessible energy site with a Powerwall on your Teslemetry account has already been added for local control.", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "entry_not_loaded": "The Teslemetry account must be loaded before setting up local control. Try again once it has finished loading.", - "no_energy_sites": "No energy sites on your Teslemetry account are available for local control. This may be because they lack a Powerwall or have already been added." + "no_powerwall": "Local control requires a Powerwall, and no energy site with one is currently accessible on your Teslemetry account." }, "entry_type": "Energy site", "error": { diff --git a/tests/components/teslemetry/test_config_flow.py b/tests/components/teslemetry/test_config_flow.py index 8092128f9559..5859531a489c 100644 --- a/tests/components/teslemetry/test_config_flow.py +++ b/tests/components/teslemetry/test_config_flow.py @@ -1047,7 +1047,53 @@ async def test_add_flow_aborts_when_all_sites_added(hass: HomeAssistant) -> None ) assert result["type"] is FlowResultType.ABORT - assert result["reason"] == "no_energy_sites" + assert result["reason"] == "all_sites_added" + + +async def test_add_flow_aborts_when_no_powerwall(hass: HomeAssistant) -> None: + """The add flow aborts when the account has no Powerwall-capable site.""" + products = deepcopy(PRODUCTS) + products["response"] = [ + product + for product in products["response"] + if product.get("energy_site_id") != SITE_ID + ] + products["response"].append( + { + "energy_site_id": WALL_CONNECTOR_SITE_ID, + "site_name": "Wall Connector Site", + "components": { + "battery": False, + "solar": False, + "grid": True, + "wall_connectors": [{"device_id": "wc-1", "din": "WC-DIN-1"}], + }, + } + ) + metadata = deepcopy(METADATA) + del metadata["energy_sites"][str(SITE_ID)] + metadata["energy_sites"][str(WALL_CONNECTOR_SITE_ID)] = { + "access": True, + "name": "Wall Connector Site", + } + + entry = mock_config_entry() + entry.add_to_hass(hass) + with ( + patch("tesla_fleet_api.teslemetry.Teslemetry.products", return_value=products), + patch("tesla_fleet_api.teslemetry.Teslemetry.metadata", return_value=metadata), + patch("homeassistant.components.teslemetry.PLATFORMS", []), + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + result = await hass.config_entries.subentries.async_init( + (entry.entry_id, SUBENTRY_TYPE_ENERGY_SITE), + context={"source": "user"}, + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "no_powerwall" @pytest.mark.usefixtures("mock_rsa_key")