mirror of
https://github.com/home-assistant/core.git
synced 2025-11-09 02:49:40 +00:00
Handle location scope in Tesla Fleet vehicle coordinator (#154731)
This commit is contained in:
committed by
Franck Nijhof
parent
03abd5d277
commit
6ac4d2dd59
@@ -134,7 +134,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -
|
|||||||
api = tesla.vehicles.createSigned(vin)
|
api = tesla.vehicles.createSigned(vin)
|
||||||
else:
|
else:
|
||||||
api = tesla.vehicles.createFleet(vin)
|
api = tesla.vehicles.createFleet(vin)
|
||||||
coordinator = TeslaFleetVehicleDataCoordinator(hass, entry, api, product)
|
coordinator = TeslaFleetVehicleDataCoordinator(
|
||||||
|
hass, entry, api, product, Scope.VEHICLE_LOCATION in scopes
|
||||||
|
)
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ ENDPOINTS = [
|
|||||||
VehicleDataEndpoint.CHARGE_STATE,
|
VehicleDataEndpoint.CHARGE_STATE,
|
||||||
VehicleDataEndpoint.CLIMATE_STATE,
|
VehicleDataEndpoint.CLIMATE_STATE,
|
||||||
VehicleDataEndpoint.DRIVE_STATE,
|
VehicleDataEndpoint.DRIVE_STATE,
|
||||||
VehicleDataEndpoint.LOCATION_DATA,
|
|
||||||
VehicleDataEndpoint.VEHICLE_STATE,
|
VehicleDataEndpoint.VEHICLE_STATE,
|
||||||
VehicleDataEndpoint.VEHICLE_CONFIG,
|
VehicleDataEndpoint.VEHICLE_CONFIG,
|
||||||
|
VehicleDataEndpoint.LOCATION_DATA,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +65,7 @@ class TeslaFleetVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
updated_once: bool
|
updated_once: bool
|
||||||
pre2021: bool
|
pre2021: bool
|
||||||
last_active: datetime
|
last_active: datetime
|
||||||
|
endpoints: list[VehicleDataEndpoint]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -72,6 +73,7 @@ class TeslaFleetVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
config_entry: TeslaFleetConfigEntry,
|
config_entry: TeslaFleetConfigEntry,
|
||||||
api: VehicleFleet,
|
api: VehicleFleet,
|
||||||
product: dict,
|
product: dict,
|
||||||
|
location: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize TeslaFleet Vehicle Update Coordinator."""
|
"""Initialize TeslaFleet Vehicle Update Coordinator."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@@ -85,6 +87,11 @@ class TeslaFleetVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
self.data = flatten(product)
|
self.data = flatten(product)
|
||||||
self.updated_once = False
|
self.updated_once = False
|
||||||
self.last_active = datetime.now()
|
self.last_active = datetime.now()
|
||||||
|
self.endpoints = (
|
||||||
|
ENDPOINTS
|
||||||
|
if location
|
||||||
|
else [ep for ep in ENDPOINTS if ep != VehicleDataEndpoint.LOCATION_DATA]
|
||||||
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[str, Any]:
|
async def _async_update_data(self) -> dict[str, Any]:
|
||||||
"""Update vehicle data using TeslaFleet API."""
|
"""Update vehicle data using TeslaFleet API."""
|
||||||
@@ -97,7 +104,7 @@ class TeslaFleetVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
if self.data["state"] != TeslaFleetState.ONLINE:
|
if self.data["state"] != TeslaFleetState.ONLINE:
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
response = await self.api.vehicle_data(endpoints=ENDPOINTS)
|
response = await self.api.vehicle_data(endpoints=self.endpoints)
|
||||||
data = response["response"]
|
data = response["response"]
|
||||||
|
|
||||||
except VehicleOffline:
|
except VehicleOffline:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from aiohttp.client_exceptions import ClientResponseError
|
|||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
from tesla_fleet_api.const import Scope, VehicleDataEndpoint
|
||||||
from tesla_fleet_api.exceptions import (
|
from tesla_fleet_api.exceptions import (
|
||||||
InvalidRegion,
|
InvalidRegion,
|
||||||
InvalidToken,
|
InvalidToken,
|
||||||
@@ -36,6 +37,7 @@ from homeassistant.data_entry_flow import FlowResultType
|
|||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
|
||||||
from . import setup_platform
|
from . import setup_platform
|
||||||
|
from .conftest import create_config_entry
|
||||||
from .const import VEHICLE_ASLEEP, VEHICLE_DATA_ALT
|
from .const import VEHICLE_ASLEEP, VEHICLE_DATA_ALT
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
@@ -497,3 +499,65 @@ async def test_bad_implementation(
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "reauth_confirm"
|
assert result["step_id"] == "reauth_confirm"
|
||||||
assert not result["errors"]
|
assert not result["errors"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_vehicle_without_location_scope(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
expires_at: int,
|
||||||
|
mock_vehicle_data: AsyncMock,
|
||||||
|
) -> None:
|
||||||
|
"""Test vehicle setup without VEHICLE_LOCATION scope excludes location endpoint."""
|
||||||
|
|
||||||
|
# Create config entry without VEHICLE_LOCATION scope
|
||||||
|
config_entry = create_config_entry(
|
||||||
|
expires_at,
|
||||||
|
[
|
||||||
|
Scope.OPENID,
|
||||||
|
Scope.OFFLINE_ACCESS,
|
||||||
|
Scope.VEHICLE_DEVICE_DATA,
|
||||||
|
# Deliberately exclude Scope.VEHICLE_LOCATION
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
await setup_platform(hass, config_entry)
|
||||||
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
# Verify that vehicle_data was called without LOCATION_DATA endpoint
|
||||||
|
mock_vehicle_data.assert_called()
|
||||||
|
call_args = mock_vehicle_data.call_args
|
||||||
|
endpoints = call_args.kwargs.get("endpoints", [])
|
||||||
|
|
||||||
|
# Should not include LOCATION_DATA endpoint
|
||||||
|
assert VehicleDataEndpoint.LOCATION_DATA not in endpoints
|
||||||
|
|
||||||
|
# Should include other endpoints
|
||||||
|
assert VehicleDataEndpoint.CHARGE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.CLIMATE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.DRIVE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.VEHICLE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.VEHICLE_CONFIG in endpoints
|
||||||
|
|
||||||
|
|
||||||
|
async def test_vehicle_with_location_scope(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
normal_config_entry: MockConfigEntry,
|
||||||
|
mock_vehicle_data: AsyncMock,
|
||||||
|
) -> None:
|
||||||
|
"""Test vehicle setup with VEHICLE_LOCATION scope includes location endpoint."""
|
||||||
|
await setup_platform(hass, normal_config_entry)
|
||||||
|
assert normal_config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
# Verify that vehicle_data was called with LOCATION_DATA endpoint
|
||||||
|
mock_vehicle_data.assert_called()
|
||||||
|
call_args = mock_vehicle_data.call_args
|
||||||
|
endpoints = call_args.kwargs.get("endpoints", [])
|
||||||
|
|
||||||
|
# Should include LOCATION_DATA endpoint when scope is present
|
||||||
|
assert VehicleDataEndpoint.LOCATION_DATA in endpoints
|
||||||
|
|
||||||
|
# Should include all other endpoints
|
||||||
|
assert VehicleDataEndpoint.CHARGE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.CLIMATE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.DRIVE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.VEHICLE_STATE in endpoints
|
||||||
|
assert VehicleDataEndpoint.VEHICLE_CONFIG in endpoints
|
||||||
|
|||||||
Reference in New Issue
Block a user