Skip to content

Commit 6ac4d2d

Browse files
Bre77frenck
authored andcommitted
Handle location scope in Tesla Fleet vehicle coordinator (home-assistant#154731)
1 parent 03abd5d commit 6ac4d2d

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

homeassistant/components/tesla_fleet/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ async def _refresh_token() -> str:
134134
api = tesla.vehicles.createSigned(vin)
135135
else:
136136
api = tesla.vehicles.createFleet(vin)
137-
coordinator = TeslaFleetVehicleDataCoordinator(hass, entry, api, product)
137+
coordinator = TeslaFleetVehicleDataCoordinator(
138+
hass, entry, api, product, Scope.VEHICLE_LOCATION in scopes
139+
)
138140

139141
await coordinator.async_config_entry_first_refresh()
140142

homeassistant/components/tesla_fleet/coordinator.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
VehicleDataEndpoint.CHARGE_STATE,
4040
VehicleDataEndpoint.CLIMATE_STATE,
4141
VehicleDataEndpoint.DRIVE_STATE,
42-
VehicleDataEndpoint.LOCATION_DATA,
4342
VehicleDataEndpoint.VEHICLE_STATE,
4443
VehicleDataEndpoint.VEHICLE_CONFIG,
44+
VehicleDataEndpoint.LOCATION_DATA,
4545
]
4646

4747

@@ -65,13 +65,15 @@ class TeslaFleetVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
6565
updated_once: bool
6666
pre2021: bool
6767
last_active: datetime
68+
endpoints: list[VehicleDataEndpoint]
6869

6970
def __init__(
7071
self,
7172
hass: HomeAssistant,
7273
config_entry: TeslaFleetConfigEntry,
7374
api: VehicleFleet,
7475
product: dict,
76+
location: bool,
7577
) -> None:
7678
"""Initialize TeslaFleet Vehicle Update Coordinator."""
7779
super().__init__(
@@ -85,6 +87,11 @@ def __init__(
8587
self.data = flatten(product)
8688
self.updated_once = False
8789
self.last_active = datetime.now()
90+
self.endpoints = (
91+
ENDPOINTS
92+
if location
93+
else [ep for ep in ENDPOINTS if ep != VehicleDataEndpoint.LOCATION_DATA]
94+
)
8895

8996
async def _async_update_data(self) -> dict[str, Any]:
9097
"""Update vehicle data using TeslaFleet API."""
@@ -97,7 +104,7 @@ async def _async_update_data(self) -> dict[str, Any]:
97104
if self.data["state"] != TeslaFleetState.ONLINE:
98105
return self.data
99106

100-
response = await self.api.vehicle_data(endpoints=ENDPOINTS)
107+
response = await self.api.vehicle_data(endpoints=self.endpoints)
101108
data = response["response"]
102109

103110
except VehicleOffline:

tests/components/tesla_fleet/test_init.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from freezegun.api import FrozenDateTimeFactory
1010
import pytest
1111
from syrupy.assertion import SnapshotAssertion
12+
from tesla_fleet_api.const import Scope, VehicleDataEndpoint
1213
from tesla_fleet_api.exceptions import (
1314
InvalidRegion,
1415
InvalidToken,
@@ -36,6 +37,7 @@
3637
from homeassistant.helpers import device_registry as dr
3738

3839
from . import setup_platform
40+
from .conftest import create_config_entry
3941
from .const import VEHICLE_ASLEEP, VEHICLE_DATA_ALT
4042

4143
from tests.common import MockConfigEntry, async_fire_time_changed
@@ -497,3 +499,65 @@ async def test_bad_implementation(
497499
assert result["type"] is FlowResultType.FORM
498500
assert result["step_id"] == "reauth_confirm"
499501
assert not result["errors"]
502+
503+
504+
async def test_vehicle_without_location_scope(
505+
hass: HomeAssistant,
506+
expires_at: int,
507+
mock_vehicle_data: AsyncMock,
508+
) -> None:
509+
"""Test vehicle setup without VEHICLE_LOCATION scope excludes location endpoint."""
510+
511+
# Create config entry without VEHICLE_LOCATION scope
512+
config_entry = create_config_entry(
513+
expires_at,
514+
[
515+
Scope.OPENID,
516+
Scope.OFFLINE_ACCESS,
517+
Scope.VEHICLE_DEVICE_DATA,
518+
# Deliberately exclude Scope.VEHICLE_LOCATION
519+
],
520+
)
521+
522+
await setup_platform(hass, config_entry)
523+
assert config_entry.state is ConfigEntryState.LOADED
524+
525+
# Verify that vehicle_data was called without LOCATION_DATA endpoint
526+
mock_vehicle_data.assert_called()
527+
call_args = mock_vehicle_data.call_args
528+
endpoints = call_args.kwargs.get("endpoints", [])
529+
530+
# Should not include LOCATION_DATA endpoint
531+
assert VehicleDataEndpoint.LOCATION_DATA not in endpoints
532+
533+
# Should include other endpoints
534+
assert VehicleDataEndpoint.CHARGE_STATE in endpoints
535+
assert VehicleDataEndpoint.CLIMATE_STATE in endpoints
536+
assert VehicleDataEndpoint.DRIVE_STATE in endpoints
537+
assert VehicleDataEndpoint.VEHICLE_STATE in endpoints
538+
assert VehicleDataEndpoint.VEHICLE_CONFIG in endpoints
539+
540+
541+
async def test_vehicle_with_location_scope(
542+
hass: HomeAssistant,
543+
normal_config_entry: MockConfigEntry,
544+
mock_vehicle_data: AsyncMock,
545+
) -> None:
546+
"""Test vehicle setup with VEHICLE_LOCATION scope includes location endpoint."""
547+
await setup_platform(hass, normal_config_entry)
548+
assert normal_config_entry.state is ConfigEntryState.LOADED
549+
550+
# Verify that vehicle_data was called with LOCATION_DATA endpoint
551+
mock_vehicle_data.assert_called()
552+
call_args = mock_vehicle_data.call_args
553+
endpoints = call_args.kwargs.get("endpoints", [])
554+
555+
# Should include LOCATION_DATA endpoint when scope is present
556+
assert VehicleDataEndpoint.LOCATION_DATA in endpoints
557+
558+
# Should include all other endpoints
559+
assert VehicleDataEndpoint.CHARGE_STATE in endpoints
560+
assert VehicleDataEndpoint.CLIMATE_STATE in endpoints
561+
assert VehicleDataEndpoint.DRIVE_STATE in endpoints
562+
assert VehicleDataEndpoint.VEHICLE_STATE in endpoints
563+
assert VehicleDataEndpoint.VEHICLE_CONFIG in endpoints

0 commit comments

Comments
 (0)