Check Tessie scopes to fix startup bug (#120710)

* Add scope check

* Add tests

* Bump Teslemetry
This commit is contained in:
Brett Adams 2024-06-28 19:21:59 +10:00 committed by Franck Nijhof
parent 35d145d3bc
commit 3932ce57b9
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
8 changed files with 76 additions and 36 deletions

View File

@ -7,5 +7,5 @@
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"quality_scale": "platinum",
"requirements": ["tesla-fleet-api==0.6.1"]
"requirements": ["tesla-fleet-api==0.6.2"]
}

View File

@ -6,6 +6,7 @@ import logging
from aiohttp import ClientError, ClientResponseError
from tesla_fleet_api import EnergySpecific, Tessie
from tesla_fleet_api.const import Scope
from tesla_fleet_api.exceptions import TeslaFleetError
from tessie_api import get_state_of_all_vehicles
@ -94,41 +95,48 @@ async def async_setup_entry(hass: HomeAssistant, entry: TessieConfigEntry) -> bo
# Energy Sites
tessie = Tessie(session, api_key)
energysites: list[TessieEnergyData] = []
try:
products = (await tessie.products())["response"]
scopes = await tessie.scopes()
except TeslaFleetError as e:
raise ConfigEntryNotReady from e
energysites: list[TessieEnergyData] = []
for product in products:
if "energy_site_id" in product:
site_id = product["energy_site_id"]
api = EnergySpecific(tessie.energy, site_id)
energysites.append(
TessieEnergyData(
api=api,
id=site_id,
live_coordinator=TessieEnergySiteLiveCoordinator(hass, api),
info_coordinator=TessieEnergySiteInfoCoordinator(hass, api),
device=DeviceInfo(
identifiers={(DOMAIN, str(site_id))},
manufacturer="Tesla",
name=product.get("site_name", "Energy Site"),
),
)
)
if Scope.ENERGY_DEVICE_DATA in scopes:
try:
products = (await tessie.products())["response"]
except TeslaFleetError as e:
raise ConfigEntryNotReady from e
# Populate coordinator data before forwarding to platforms
await asyncio.gather(
*(
energysite.live_coordinator.async_config_entry_first_refresh()
for energysite in energysites
),
*(
energysite.info_coordinator.async_config_entry_first_refresh()
for energysite in energysites
),
)
for product in products:
if "energy_site_id" in product:
site_id = product["energy_site_id"]
api = EnergySpecific(tessie.energy, site_id)
energysites.append(
TessieEnergyData(
api=api,
id=site_id,
live_coordinator=TessieEnergySiteLiveCoordinator(hass, api),
info_coordinator=TessieEnergySiteInfoCoordinator(hass, api),
device=DeviceInfo(
identifiers={(DOMAIN, str(site_id))},
manufacturer="Tesla",
name=product.get("site_name", "Energy Site"),
),
)
)
# Populate coordinator data before forwarding to platforms
await asyncio.gather(
*(
energysite.live_coordinator.async_config_entry_first_refresh()
for energysite in energysites
),
*(
energysite.info_coordinator.async_config_entry_first_refresh()
for energysite in energysites
),
)
entry.runtime_data = TessieData(vehicles, energysites)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/tessie",
"iot_class": "cloud_polling",
"loggers": ["tessie"],
"requirements": ["tessie-api==0.0.9", "tesla-fleet-api==0.6.1"]
"requirements": ["tessie-api==0.0.9", "tesla-fleet-api==0.6.2"]
}

View File

@ -2711,7 +2711,7 @@ temperusb==1.6.1
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==0.6.1
tesla-fleet-api==0.6.2
# homeassistant.components.powerwall
tesla-powerwall==0.5.2

View File

@ -2109,7 +2109,7 @@ temperusb==1.6.1
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==0.6.1
tesla-fleet-api==0.6.2
# homeassistant.components.powerwall
tesla-powerwall==0.5.2

View File

@ -54,6 +54,17 @@ LIVE_STATUS = load_json_object_fixture("live_status.json", DOMAIN)
SITE_INFO = load_json_object_fixture("site_info.json", DOMAIN)
RESPONSE_OK = {"response": {}, "error": None}
COMMAND_OK = {"response": {"result": True, "reason": ""}}
SCOPES = [
"user_data",
"vehicle_device_data",
"vehicle_cmds",
"vehicle_charging_cmds",
"energy_device_data",
"energy_cmds",
"offline_access",
"openid",
]
NO_SCOPES = ["user_data", "offline_access", "openid"]
async def setup_platform(

View File

@ -11,6 +11,7 @@ from .common import (
COMMAND_OK,
LIVE_STATUS,
PRODUCTS,
SCOPES,
SITE_INFO,
TEST_STATE_OF_ALL_VEHICLES,
TEST_VEHICLE_STATE_ONLINE,
@ -51,6 +52,16 @@ def mock_get_state_of_all_vehicles():
# Fleet API
@pytest.fixture(autouse=True)
def mock_scopes():
"""Mock scopes function."""
with patch(
"homeassistant.components.tessie.Tessie.scopes",
return_value=SCOPES,
) as mock_scopes:
yield mock_scopes
@pytest.fixture(autouse=True)
def mock_products():
"""Mock Tesla Fleet Api products method."""

View File

@ -50,11 +50,21 @@ async def test_connection_failure(
assert entry.state is ConfigEntryState.SETUP_RETRY
async def test_fleet_error(hass: HomeAssistant) -> None:
"""Test init with a fleet error."""
async def test_products_error(hass: HomeAssistant) -> None:
"""Test init with a fleet error on products."""
with patch(
"homeassistant.components.tessie.Tessie.products", side_effect=TeslaFleetError
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.SETUP_RETRY
async def test_scopes_error(hass: HomeAssistant) -> None:
"""Test init with a fleet error on scopes."""
with patch(
"homeassistant.components.tessie.Tessie.scopes", side_effect=TeslaFleetError
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.SETUP_RETRY