Skip to content

Commit 64fd859

Browse files
committed
Partner login and fixed refresh hook types
1 parent 823cf13 commit 64fd859

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

tesla_fleet_api/tesla/fleet.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""Tesla Fleet API for Python."""
22

33
from json import dumps
4-
from typing import Any, Awaitable
4+
from typing import Any, Awaitable, Callable
55
import aiohttp
66

77
from tesla_fleet_api.tesla.tesla import Tesla
88
from tesla_fleet_api.exceptions import raise_for_status, InvalidRegion, LibraryError, ResponseError
9-
from tesla_fleet_api.const import SERVERS, Method, LOGGER
9+
from tesla_fleet_api.const import SERVERS, Method, LOGGER, Scope
1010
from tesla_fleet_api import __version__ as VERSION
1111

1212
# Based on https://developer.tesla.com/docs/fleet-api
@@ -18,7 +18,7 @@ class TeslaFleetApi(Tesla):
1818
server: str | None = None
1919
session: aiohttp.ClientSession
2020
headers: dict[str, str]
21-
refresh_hook: Awaitable | None = None
21+
refresh_hook: Callable[[], Awaitable[str | None]] | None = None
2222

2323
def __init__(
2424
self,
@@ -31,7 +31,7 @@ def __init__(
3131
partner_scope: bool = True,
3232
user_scope: bool = True,
3333
vehicle_scope: bool = True,
34-
refresh_hook: Awaitable | None = None,
34+
refresh_hook: Callable[[], Awaitable[str | None]] | None = None,
3535
):
3636
"""Initialize the Tesla Fleet API."""
3737

@@ -149,3 +149,46 @@ async def products(self) -> dict[str, Any]:
149149
Method.GET,
150150
"api/1/products",
151151
)
152+
153+
async def partner_login(
154+
self,
155+
client_id: str,
156+
client_secret: str,
157+
scopes: list[Scope] = [Scope.VEHICLE_DEVICE_DATA],
158+
) -> dict[str, Any]:
159+
"""Generate a partner token using client credentials authentication.
160+
161+
Args:
162+
client_id: Partner application client ID
163+
client_secret: Partner application client secret
164+
scopes: Optional list of scopes to request
165+
166+
Returns:
167+
Dictionary containing access token and token metadata
168+
"""
169+
170+
# Throw if there is no server set
171+
if not self.server:
172+
raise ValueError("Server was not set at init. Call find_server() first.")
173+
174+
data = {
175+
"grant_type": "client_credentials",
176+
"client_id": client_id,
177+
"client_secret": client_secret,
178+
"audience": self.server,
179+
"scope": " ".join(scopes),
180+
}
181+
182+
async with self.session.post(
183+
"https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token",
184+
headers={"Content-Type": "application/x-www-form-urlencoded"},
185+
data=data,
186+
) as resp:
187+
if resp.ok:
188+
token_data = await resp.json()
189+
# Set the access token for subsequent API calls
190+
self.access_token = token_data["access_token"]
191+
return token_data
192+
else:
193+
error_data = await resp.json()
194+
raise ValueError(f"Partner login failed: {error_data}")

0 commit comments

Comments
 (0)