tesla-fleet-api 0.0.1__py3-none-any.whl → 0.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,17 @@
1
1
  import aiohttp
2
- from .exceptions import raise_for_status, TeslaFleetError
2
+ from .exceptions import raise_for_status, InvalidRegion, LibraryError
3
3
  from typing import Any
4
- from enum import StrEnum, IntEnum
5
- from .const import SERVERS
4
+ from .const import (
5
+ SERVERS,
6
+ Methods,
7
+ Trunks,
8
+ ClimateKeeperMode,
9
+ CabinOverheatProtectionTemps,
10
+ VehicleDataEndpoints,
11
+ SunRoofCommands,
12
+ WindowCommands,
13
+ DeviceTypes,
14
+ )
6
15
 
7
16
 
8
17
  # Based on https://developer.tesla.com/docs/fleet-api
@@ -26,6 +35,7 @@ class TeslaFleetApi:
26
35
  """Initialize the Tesla Fleet API."""
27
36
 
28
37
  self.session = session
38
+ self.access_token = access_token
29
39
  self.use_command_protocol = use_command_protocol
30
40
 
31
41
  if region and not server and region not in SERVERS:
@@ -33,11 +43,6 @@ class TeslaFleetApi:
33
43
  self.server = server or SERVERS.get(region)
34
44
  self.raise_for_status = raise_for_status
35
45
 
36
- self.headers = {
37
- "Authorization": f"Bearer {access_token}",
38
- "Content-Type": "application/json",
39
- }
40
-
41
46
  self.user = self.User(self)
42
47
  self.charging = self.Charging(self)
43
48
  self.partner = self.Partner(self)
@@ -50,35 +55,40 @@ class TeslaFleetApi:
50
55
  try:
51
56
  await self.user.region()
52
57
  return
53
- except TeslaFleetError.Base:
54
- print(f"not {server}")
58
+ except InvalidRegion:
55
59
  continue
56
- raise TeslaFleetError.Base("Could not find a valid server.")
60
+ raise LibraryError("Could not find a valid Tesla API server.")
57
61
 
58
62
  async def _request(
59
63
  self,
60
- method: str,
64
+ method: Methods,
61
65
  path: str,
66
+ params: dict[str:Any] | None = None,
62
67
  data: dict[str:Any] | None = None,
63
68
  json: dict[str:Any] | None = None,
64
- params: dict[str:Any] | None = None,
65
69
  ):
66
- """Request data to the Tesla Fleet API with URL encoded data."""
70
+ """Send a request to the Tesla Fleet API."""
67
71
 
68
72
  if not self.server:
69
73
  raise ValueError("Server was not set at init. Call find_server() first.")
70
74
 
75
+ if method == Methods.GET and (data is not None or json is not None):
76
+ raise ValueError("GET requests cannot have data or json parameters.")
77
+
78
+ if params:
79
+ params = {k: v for k, v in params.items() if v is not None}
71
80
  if data:
72
81
  data = {k: v for k, v in data.items() if v is not None}
73
82
  if json:
74
83
  json = {k: v for k, v in json.items() if v is not None}
75
- if params:
76
- params = {k: v for k, v in params.items() if v is not None}
77
84
 
78
85
  async with self.session.request(
79
86
  method,
80
87
  f"{self.server}/{path}",
81
- headers=self.headers,
88
+ headers={
89
+ "Authorization": f"Bearer {self.access_token}",
90
+ "Content-Type": "application/json",
91
+ },
82
92
  data=data,
83
93
  json=json,
84
94
  params=params,
@@ -87,70 +97,10 @@ class TeslaFleetApi:
87
97
  await raise_for_status(resp)
88
98
  return await resp.json()
89
99
 
90
- async def _get(self, path, params: dict[str:Any] | None = None):
91
- """Get data from the Tesla Fleet API."""
92
-
93
- if not self.server:
94
- raise ValueError("Server was not set at init. Call find_server() first.")
95
-
96
- if params:
97
- params = {k: v for k, v in params.items() if v is not None}
98
-
99
- async with self.session.get(
100
- f"{self.server}/{path}",
101
- params=params,
102
- headers=self.headers,
103
- ) as resp:
104
- if self.raise_for_status:
105
- await raise_for_status(resp)
106
- return await resp.json()
107
-
108
- async def _post(
109
- self,
110
- path,
111
- data: dict[str:Any] | None = None,
112
- json: dict[str:Any] | None = None,
113
- params: dict[str:Any] | None = None,
114
- ):
115
- """Post data to the Tesla Fleet API with URL encoded data."""
116
-
117
- if not self.server:
118
- raise ValueError("Server was not set at init. Call find_server() first.")
119
-
120
- if params:
121
- params = {k: v for k, v in params.items() if v is not None}
122
-
123
- async with self.session.post(
124
- f"{self.server}/{path}",
125
- headers=self.headers,
126
- data=data,
127
- json=json,
128
- params=params,
129
- ) as resp:
130
- if self.raise_for_status:
131
- await raise_for_status(resp)
132
- return await resp.json()
133
-
134
- async def _delete(self, path, params: dict[str:Any] | None = None):
135
- """Delete data from the Tesla Fleet API."""
136
-
137
- if not self.server:
138
- raise ValueError("Server was not set at init. Call find_server() first.")
139
-
140
- if params:
141
- params = {k: v for k, v in params.items() if v is not None}
142
-
143
- async with self.session.delete(
144
- f"{self.server}/{path}",
145
- headers=self.headers,
146
- params=params,
147
- ) as resp:
148
- if self.raise_for_status:
149
- await raise_for_status(resp)
150
- return await resp.json()
151
-
152
100
  async def status(self):
153
101
  """This endpoint returns the string "ok" if the API is operating normally. No HTTP headers are required."""
102
+ if not self.server:
103
+ raise ValueError("Server was not set at init. Call find_server() first.")
154
104
  async with self.session.get(f"{self.server}/status") as resp:
155
105
  return await resp.text()
156
106
 
@@ -158,8 +108,7 @@ class TeslaFleetApi:
158
108
  """Class describing the Tesla Fleet API charging endpoints."""
159
109
 
160
110
  def __init__(self, parent):
161
- self._get = parent._get
162
- self._post = parent._post
111
+ self._request = parent._request
163
112
 
164
113
  async def history(
165
114
  self,
@@ -172,7 +121,8 @@ class TeslaFleetApi:
172
121
  sortOrder: str | None = None,
173
122
  ) -> dict[str, Any]:
174
123
  """Returns the paginated charging history."""
175
- return await self._get(
124
+ return await self._request(
125
+ Methods.GET,
176
126
  "api/1/dx/charging/history",
177
127
  {
178
128
  vin: vin,
@@ -194,7 +144,8 @@ class TeslaFleetApi:
194
144
  offset: int | None = None,
195
145
  ) -> dict[str, Any]:
196
146
  """Returns the charging session information including pricing and energy data. This endpoint is only available for business accounts that own a fleet of vehicles."""
197
- return await self._get(
147
+ return await self._request(
148
+ Methods.GET,
198
149
  "api/1/dx/charging/sessions",
199
150
  {
200
151
  vin: vin,
@@ -209,67 +160,62 @@ class TeslaFleetApi:
209
160
  """Class describing the Tesla Fleet API partner endpoints"""
210
161
 
211
162
  def __init__(self, parent):
212
- self._get = parent._get
213
- self._post = parent._post
163
+ self._request = parent._request
214
164
 
215
165
  async def public_key(self, domain: str | None = None) -> dict[str, Any]:
216
166
  """Returns the public key associated with a domain. It can be used to ensure the registration was successful."""
217
- return await self._get(
218
- "api/1/partner_accounts/public_key", data={domain: domain}
167
+ return await self._request(
168
+ Methods.GET, "api/1/partner_accounts/public_key", data={domain: domain}
219
169
  )
220
170
 
221
171
  async def register(self, domain: str) -> dict[str, Any]:
222
172
  """Registers an existing account before it can be used for general API access. Each application from developer.tesla.com must complete this step."""
223
- return await self._post("api/1/partner_accounts", data={domain: domain})
173
+ return await self._request(
174
+ Methods.POST, "api/1/partner_accounts", data={domain: domain}
175
+ )
224
176
 
225
177
  class User:
226
178
  """Class describing the Tesla Fleet API user endpoints"""
227
179
 
228
180
  def __init__(self, parent):
229
- self._get = parent._get
181
+ self._request = parent._request
230
182
 
231
183
  async def backup_key(self) -> dict[str, Any]:
232
184
  """Returns the public key associated with the user."""
233
- return await self._get("api/1/users/backup_key")
185
+ return await self._request(Methods.GET, "api/1/users/backup_key")
234
186
 
235
187
  async def feature_config(self) -> dict[str, Any]:
236
188
  """Returns any custom feature flag applied to a user."""
237
- return await self._get("api/1/users/feature_config")
189
+ return await self._request(Methods.GET, "api/1/users/feature_config")
238
190
 
239
191
  async def me(self) -> dict[str, Any]:
240
192
  """Returns a summary of a user's account."""
241
- return await self._get("api/1/users/me")
193
+ return await self._request(Methods.GET, "api/1/users/me")
242
194
 
243
195
  async def orders(self) -> dict[str, Any]:
244
196
  """Returns the active orders for a user."""
245
- return await self._get("api/1/users/orders")
197
+ return await self._request(Methods.GET, "api/1/users/orders")
246
198
 
247
199
  async def region(self) -> dict[str, Any]:
248
200
  """Returns a user's region and appropriate fleet-api base URL. Accepts no parameters, response is based on the authentication token subject."""
249
- return await self._get("api/1/users/region")
201
+ return await self._request(Methods.GET, "api/1/users/region")
250
202
 
251
203
  class Vehicle:
252
204
  """Class describing the Tesla Fleet API vehicle endpoints and commands."""
253
205
 
254
206
  def __init__(self, parent):
255
- self._get = parent._get
256
- self._post = parent._post
257
- self._delete = parent._delete
207
+ self._parent = parent
208
+ self._request = parent._request
258
209
  self.use_command_protocol = parent.use_command_protocol
259
210
 
260
- class Trunk(StrEnum):
261
- """Trunk options"""
262
-
263
- FRONT: "front"
264
- REAR: "rear"
265
-
266
211
  async def actuate_trunk(
267
- self, vehicle_tag: str | int, which_trunk: Trunk | str
212
+ self, vehicle_tag: str | int, which_trunk: Trunks | str
268
213
  ) -> dict[str, Any]:
269
214
  """Controls the front or rear trunk."""
270
215
  if self.use_command_protocol:
271
216
  raise NotImplementedError("Command Protocol not implemented")
272
- return await self._post(
217
+ return await self._request(
218
+ Methods.POST,
273
219
  f"api/1/vehicles/{vehicle_tag}/command/actuate_trunk",
274
220
  json={which_trunk: which_trunk},
275
221
  )
@@ -282,7 +228,8 @@ class TeslaFleetApi:
282
228
  raise NotImplementedError("Command Protocol not implemented")
283
229
  if volume < 0.0 or volume > 11.0:
284
230
  raise ValueError("Volume must a number from 0.0 to 11.0")
285
- return await self._post(
231
+ return await self._request(
232
+ Methods.POST,
286
233
  f"api/1/vehicles/{vehicle_tag}/command/adjust_volume",
287
234
  json={volume: volume},
288
235
  )
@@ -293,8 +240,9 @@ class TeslaFleetApi:
293
240
  """Starts climate preconditioning."""
294
241
  if self.use_command_protocol:
295
242
  raise NotImplementedError("Command Protocol not implemented")
296
- return await self._post(
297
- f"api/1/vehicles/{vehicle_tag}/command/auto_conditioning_start"
243
+ return await self._request(
244
+ Methods.POST,
245
+ f"api/1/vehicles/{vehicle_tag}/command/auto_conditioning_start",
298
246
  )
299
247
 
300
248
  async def auto_conditioning_stop(
@@ -303,8 +251,9 @@ class TeslaFleetApi:
303
251
  """Stops climate preconditioning."""
304
252
  if self.use_command_protocol:
305
253
  raise NotImplementedError("Command Protocol not implemented")
306
- return await self._post(
307
- f"api/1/vehicles/{vehicle_tag}/command/auto_conditioning_stop"
254
+ return await self._request(
255
+ Methods.POST,
256
+ f"api/1/vehicles/{vehicle_tag}/command/auto_conditioning_stop",
308
257
  )
309
258
 
310
259
  async def cancel_software_update(
@@ -313,16 +262,17 @@ class TeslaFleetApi:
313
262
  """Cancels the countdown to install the vehicle software update."""
314
263
  if self.use_command_protocol:
315
264
  raise NotImplementedError("Command Protocol not implemented")
316
- return await self._post(
317
- f"api/1/vehicles/{vehicle_tag}/command/cancel_software_update"
265
+ return await self._request(
266
+ Methods.POST,
267
+ f"api/1/vehicles/{vehicle_tag}/command/cancel_software_update",
318
268
  )
319
269
 
320
270
  async def charge_max_range(self, vehicle_tag: str | int) -> dict[str, Any]:
321
271
  """Charges in max range mode -- we recommend limiting the use of this mode to long trips."""
322
272
  if self.use_command_protocol:
323
273
  raise NotImplementedError("Command Protocol not implemented")
324
- return await self._post(
325
- f"api/1/vehicles/{vehicle_tag}/command/charge_max_range"
274
+ return await self._request(
275
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/charge_max_range"
326
276
  )
327
277
 
328
278
  async def charge_port_door_close(
@@ -331,70 +281,79 @@ class TeslaFleetApi:
331
281
  """Closes the charge port door."""
332
282
  if self.use_command_protocol:
333
283
  raise NotImplementedError("Command Protocol not implemented")
334
- return await self._post(
335
- f"api/1/vehicles/{vehicle_tag}/command/charge_port_door_close"
284
+ return await self._request(
285
+ Methods.POST,
286
+ f"api/1/vehicles/{vehicle_tag}/command/charge_port_door_close",
336
287
  )
337
288
 
338
289
  async def charge_port_door_open(self, vehicle_tag: str | int) -> dict[str, Any]:
339
290
  """Opens the charge port door."""
340
291
  if self.use_command_protocol:
341
292
  raise NotImplementedError("Command Protocol not implemented")
342
- return await self._post(
343
- f"api/1/vehicles/{vehicle_tag}/command/charge_port_door_open"
293
+ return await self._request(
294
+ Methods.POST,
295
+ f"api/1/vehicles/{vehicle_tag}/command/charge_port_door_open",
344
296
  )
345
297
 
346
298
  async def charge_standard(self, vehicle_tag: str | int) -> dict[str, Any]:
347
299
  """Charges in Standard mode."""
348
300
  if self.use_command_protocol:
349
301
  raise NotImplementedError("Command Protocol not implemented")
350
- return await self._post(
351
- f"api/1/vehicles/{vehicle_tag}/command/charge_standard"
302
+ return await self._request(
303
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/charge_standard"
352
304
  )
353
305
 
354
306
  async def charge_start(self, vehicle_tag: str | int) -> dict[str, Any]:
355
307
  """Starts charging the vehicle."""
356
308
  if self.use_command_protocol:
357
309
  raise NotImplementedError("Command Protocol not implemented")
358
- return await self._post(
359
- f"api/1/vehicles/{vehicle_tag}/command/charge_start"
310
+ return await self._request(
311
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/charge_start"
360
312
  )
361
313
 
362
314
  async def charge_stop(self, vehicle_tag: str | int) -> dict[str, Any]:
363
315
  """Stops charging the vehicle."""
364
316
  if self.use_command_protocol:
365
317
  raise NotImplementedError("Command Protocol not implemented")
366
- return await self._post(f"api/1/vehicles/{vehicle_tag}/command/charge_stop")
318
+ return await self._request(
319
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/charge_stop"
320
+ )
367
321
 
368
322
  async def clear_pin_to_drive_admin(self, vehicle_tag: str | int):
369
323
  """Deactivates PIN to Drive and resets the associated PIN for vehicles running firmware versions 2023.44+. This command is only accessible to fleet managers or owners."""
370
- return await self._post(
371
- f"api/1/vehicles/{vehicle_tag}/command/clear_pin_to_drive_admin"
324
+ return await self._request(
325
+ Methods.POST,
326
+ f"api/1/vehicles/{vehicle_tag}/command/clear_pin_to_drive_admin",
372
327
  )
373
328
 
374
329
  async def door_lock(self, vehicle_tag: str | int) -> dict[str, Any]:
375
330
  """Locks the vehicle."""
376
331
  if self.use_command_protocol:
377
332
  raise NotImplementedError("Command Protocol not implemented")
378
- return await self._post(f"api/1/vehicles/{vehicle_tag}/command/door_lock")
333
+ return await self._request(
334
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/door_lock"
335
+ )
379
336
 
380
337
  async def door_unlock(self, vehicle_tag: str | int) -> dict[str, Any]:
381
338
  """Unlocks the vehicle."""
382
339
  if self.use_command_protocol:
383
340
  raise NotImplementedError("Command Protocol not implemented")
384
- return await self._post(f"api/1/vehicles/{vehicle_tag}/command/door_unlock")
341
+ return await self._request(
342
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/door_unlock"
343
+ )
385
344
 
386
345
  async def erase_user_data(self, vehicle_tag: str | int) -> dict[str, Any]:
387
346
  """Erases user's data from the user interface. Requires the vehicle to be in park."""
388
- return await self._post(
389
- f"api/1/vehicles/{vehicle_tag}/command/erase_user_data"
347
+ return await self._request(
348
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/erase_user_data"
390
349
  )
391
350
 
392
351
  async def flash_lights(self, vehicle_tag: str | int) -> dict[str, Any]:
393
352
  """Briefly flashes the vehicle headlights. Requires the vehicle to be in park."""
394
353
  if self.use_command_protocol:
395
354
  raise NotImplementedError("Command Protocol not implemented")
396
- return await self._post(
397
- f"api/1/vehicles/{vehicle_tag}/command/flash_lights"
355
+ return await self._request(
356
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/flash_lights"
398
357
  )
399
358
 
400
359
  async def guest_mode(
@@ -403,7 +362,8 @@ class TeslaFleetApi:
403
362
  """Restricts certain vehicle UI functionality from guest users"""
404
363
  if self.use_command_protocol:
405
364
  raise NotImplementedError("Command Protocol not implemented")
406
- return await self._post(
365
+ return await self._request(
366
+ Methods.POST,
407
367
  f"api/1/vehicles/{vehicle_tag}/command/guest_mode",
408
368
  json={enable: enable},
409
369
  )
@@ -412,42 +372,45 @@ class TeslaFleetApi:
412
372
  """Honks the vehicle horn. Requires the vehicle to be in park."""
413
373
  if self.use_command_protocol:
414
374
  raise NotImplementedError("Command Protocol not implemented")
415
- return await self._post(f"api/1/vehicles/{vehicle_tag}/command/honk_horn")
375
+ return await self._request(
376
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/honk_horn"
377
+ )
416
378
 
417
379
  async def media_next_fav(self, vehicle_tag: str | int) -> dict[str, Any]:
418
380
  """Advances media player to next favorite track."""
419
- return await self._post(
420
- f"api/1/vehicles/{vehicle_tag}/command/media_next_fav"
381
+ return await self._request(
382
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/media_next_fav"
421
383
  )
422
384
 
423
385
  async def media_next_track(self, vehicle_tag: str | int) -> dict[str, Any]:
424
386
  """Advances media player to next track."""
425
- return await self._post(
426
- f"api/1/vehicles/{vehicle_tag}/command/media_next_track"
387
+ return await self._request(
388
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/media_next_track"
427
389
  )
428
390
 
429
391
  async def media_prev_fav(self, vehicle_tag: str | int) -> dict[str, Any]:
430
392
  """Advances media player to previous favorite track."""
431
- return await self._post(
432
- f"api/1/vehicles/{vehicle_tag}/command/media_prev_fav"
393
+ return await self._request(
394
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/media_prev_fav"
433
395
  )
434
396
 
435
397
  async def media_prev_track(self, vehicle_tag: str | int) -> dict[str, Any]:
436
398
  """Advances media player to previous track."""
437
- return await self._post(
438
- f"api/1/vehicles/{vehicle_tag}/command/media_prev_track"
399
+ return await self._request(
400
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/media_prev_track"
439
401
  )
440
402
 
441
403
  async def media_toggle_playback(self, vehicle_tag: str | int) -> dict[str, Any]:
442
404
  """Toggles current play/pause state."""
443
- return await self._post(
444
- f"api/1/vehicles/{vehicle_tag}/command/media_toggle_playback"
405
+ return await self._request(
406
+ Methods.POST,
407
+ f"api/1/vehicles/{vehicle_tag}/command/media_toggle_playback",
445
408
  )
446
409
 
447
410
  async def media_volume_down(self, vehicle_tag: str | int) -> dict[str, Any]:
448
411
  """Turns the volume down by one."""
449
- return await self._post(
450
- f"api/1/vehicles/{vehicle_tag}/command/media_volume_down"
412
+ return await self._request(
413
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/media_volume_down"
451
414
  )
452
415
 
453
416
  async def navigation_gps_request(
@@ -456,7 +419,8 @@ class TeslaFleetApi:
456
419
  """Start navigation to given coordinates. Order can be used to specify order of multiple stops."""
457
420
  if self.use_command_protocol:
458
421
  raise NotImplementedError("Command Protocol not implemented")
459
- return await self._post(
422
+ return await self._request(
423
+ Methods.POST,
460
424
  f"api/1/vehicles/{vehicle_tag}/command/navigation_gps_request",
461
425
  json={lat: lat, lon: lon, order: order},
462
426
  )
@@ -465,7 +429,8 @@ class TeslaFleetApi:
465
429
  self, vehicle_tag: str | int, type: str, locale: str, timestamp_ms: str
466
430
  ) -> dict[str, Any]:
467
431
  """Sends a location to the in-vehicle navigation system."""
468
- return await self._post(
432
+ return await self._request(
433
+ Methods.POST,
469
434
  f"api/1/vehicles/{vehicle_tag}/command/navigation_request",
470
435
  json={type: type, locale: locale, timestamp_ms: timestamp_ms},
471
436
  )
@@ -474,7 +439,8 @@ class TeslaFleetApi:
474
439
  self, vehicle_tag: str | int, id: int, order: int
475
440
  ) -> dict[str, Any]:
476
441
  """Sends a location to the in-vehicle navigation system."""
477
- return await self._post(
442
+ return await self._request(
443
+ Methods.POST,
478
444
  f"api/1/vehicles/{vehicle_tag}/command/navigation_sc_request",
479
445
  json={type: type, id: id, order: order},
480
446
  )
@@ -485,7 +451,8 @@ class TeslaFleetApi:
485
451
  """Sets automatic seat heating and cooling."""
486
452
  if self.use_command_protocol:
487
453
  raise NotImplementedError("Command Protocol not implemented")
488
- return await self._post(
454
+ return await self._request(
455
+ Methods.POST,
489
456
  f"api/1/vehicles/{vehicle_tag}/command/remote_auto_seat_climate_request",
490
457
  json={
491
458
  auto_seat_position: auto_seat_position,
@@ -497,7 +464,8 @@ class TeslaFleetApi:
497
464
  self, vehicle_tag: str | int, on: bool
498
465
  ) -> dict[str, Any]:
499
466
  """Sets automatic steering wheel heating on/off."""
500
- return await self._post(
467
+ return await self._request(
468
+ Methods.POST,
501
469
  f"api/1/vehicles/{vehicle_tag}/command/remote_auto_steering_wheel_heat_climate_request",
502
470
  json={on: on},
503
471
  )
@@ -506,7 +474,8 @@ class TeslaFleetApi:
506
474
  self, vehicle_tag: str | int, sound: int
507
475
  ) -> dict[str, Any]:
508
476
  """Plays a sound through the vehicle external speaker."""
509
- return await self._post(
477
+ return await self._request(
478
+ Methods.POST,
510
479
  f"api/1/vehicles/{vehicle_tag}/command/remote_boombox",
511
480
  json={sound: sound},
512
481
  )
@@ -517,7 +486,8 @@ class TeslaFleetApi:
517
486
  """Sets seat cooling."""
518
487
  if self.use_command_protocol:
519
488
  raise NotImplementedError("Command Protocol not implemented")
520
- return await self._post(
489
+ return await self._request(
490
+ Methods.POST,
521
491
  f"api/1/vehicles/{vehicle_tag}/command/remote_seat_cooler_request",
522
492
  json={
523
493
  seat_position: seat_position,
@@ -531,16 +501,17 @@ class TeslaFleetApi:
531
501
  """Sets seat heating."""
532
502
  if self.use_command_protocol:
533
503
  raise NotImplementedError("Command Protocol not implemented")
534
- return await self._post(
535
- f"api/1/vehicles/{vehicle_tag}/command/remote_seat_heater_request"
504
+ return await self._request(
505
+ Methods.POST,
506
+ f"api/1/vehicles/{vehicle_tag}/command/remote_seat_heater_request",
536
507
  )
537
508
 
538
509
  async def remote_start_drive(self, vehicle_tag: str | int) -> dict[str, Any]:
539
510
  """Starts the vehicle remotely. Requires keyless driving to be enabled."""
540
511
  if self.use_command_protocol:
541
512
  raise NotImplementedError("Command Protocol not implemented")
542
- return await self._post(
543
- f"api/1/vehicles/{vehicle_tag}/command/remote_start_drive"
513
+ return await self._request(
514
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/remote_start_drive"
544
515
  )
545
516
 
546
517
  async def remote_steering_wheel_heat_level_request(
@@ -549,7 +520,8 @@ class TeslaFleetApi:
549
520
  """Sets steering wheel heat level."""
550
521
  if self.use_command_protocol:
551
522
  raise NotImplementedError("Command Protocol not implemented")
552
- return await self._post(
523
+ return await self._request(
524
+ Methods.POST,
553
525
  f"api/1/vehicles/{vehicle_tag}/command/remote_steering_wheel_heat_level_request",
554
526
  json={level: level},
555
527
  )
@@ -560,7 +532,8 @@ class TeslaFleetApi:
560
532
  """Sets steering wheel heating on/off. For vehicles that do not support auto steering wheel heat."""
561
533
  if self.use_command_protocol:
562
534
  raise NotImplementedError("Command Protocol not implemented")
563
- return await self._post(
535
+ return await self._request(
536
+ Methods.POST,
564
537
  f"api/1/vehicles/{vehicle_tag}/command/remote_steering_wheel_heater_request",
565
538
  json={on: on},
566
539
  )
@@ -571,16 +544,17 @@ class TeslaFleetApi:
571
544
  """Removes PIN to Drive. Requires the car to be in Pin to Drive mode and not in Valet mode. Note that this only works if PIN to Drive is not active. This command also requires the Tesla Vehicle Command Protocol - for more information, please see refer to the documentation here."""
572
545
  if self.use_command_protocol:
573
546
  raise NotImplementedError("Command Protocol not implemented")
574
- return await self._post(
575
- f"api/1/vehicles/{vehicle_tag}/command/reset_pin_to_drive_pin"
547
+ return await self._request(
548
+ Methods.POST,
549
+ f"api/1/vehicles/{vehicle_tag}/command/reset_pin_to_drive_pin",
576
550
  )
577
551
 
578
552
  async def reset_valet_pin(self, vehicle_tag: str | int) -> dict[str, Any]:
579
553
  """Removes PIN for Valet Mode."""
580
554
  if self.use_command_protocol:
581
555
  raise NotImplementedError("Command Protocol not implemented")
582
- return await self._post(
583
- f"api/1/vehicles/{vehicle_tag}/command/reset_valet_pin"
556
+ return await self._request(
557
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/command/reset_valet_pin"
584
558
  )
585
559
 
586
560
  async def schedule_software_update(
@@ -589,7 +563,8 @@ class TeslaFleetApi:
589
563
  """Schedules a vehicle software update (over the air "OTA") to be installed in the future."""
590
564
  if self.use_command_protocol:
591
565
  raise NotImplementedError("Command Protocol not implemented")
592
- return await self._post(
566
+ return await self._request(
567
+ Methods.POST,
593
568
  f"api/1/vehicles/{vehicle_tag}/command/schedule_software_update",
594
569
  json={offset_sec: offset_sec},
595
570
  )
@@ -600,7 +575,8 @@ class TeslaFleetApi:
600
575
  """Turns Bioweapon Defense Mode on and off."""
601
576
  if self.use_command_protocol:
602
577
  raise NotImplementedError("Command Protocol not implemented")
603
- return await self._post(
578
+ return await self._request(
579
+ Methods.POST,
604
580
  f"api/1/vehicles/{vehicle_tag}/command/set_bioweapon_mode",
605
581
  json={on: on, manual_override: manual_override},
606
582
  )
@@ -611,7 +587,8 @@ class TeslaFleetApi:
611
587
  """Sets the vehicle overheat protection."""
612
588
  if self.use_command_protocol:
613
589
  raise NotImplementedError("Command Protocol not implemented")
614
- return await self._post(
590
+ return await self._request(
591
+ Methods.POST,
615
592
  f"api/1/vehicles/{vehicle_tag}/command/set_cabin_overheat_protection",
616
593
  json={on: on, fan_only: fan_only},
617
594
  )
@@ -622,7 +599,8 @@ class TeslaFleetApi:
622
599
  """Sets the vehicle charge limit."""
623
600
  if self.use_command_protocol:
624
601
  raise NotImplementedError("Command Protocol not implemented")
625
- return await self._post(
602
+ return await self._request(
603
+ Methods.POST,
626
604
  f"api/1/vehicles/{vehicle_tag}/command/set_charge_limit",
627
605
  json={percent: percent},
628
606
  )
@@ -633,44 +611,32 @@ class TeslaFleetApi:
633
611
  """Sets the vehicle charging amps."""
634
612
  if self.use_command_protocol:
635
613
  raise NotImplementedError("Command Protocol not implemented")
636
- return await self._post(
614
+ return await self._request(
615
+ Methods.POST,
637
616
  f"api/1/vehicles/{vehicle_tag}/command/set_charging_amps",
638
617
  json={charging_amps: charging_amps},
639
618
  )
640
619
 
641
- class ClimateKeeperMode(IntEnum):
642
- """Climate Keeper Mode options"""
643
-
644
- OFF = 0
645
- KEEP_MODE = 1
646
- DOG_MODE = 2
647
- CAMP_MODE = 3
648
-
649
620
  async def set_climate_keeper_mode(
650
621
  self, vehicle_tag: str | int, climate_keeper_mode: ClimateKeeperMode | int
651
622
  ) -> dict[str, Any]:
652
623
  """Enables climate keeper mode."""
653
624
  if self.use_command_protocol:
654
625
  raise NotImplementedError("Command Protocol not implemented")
655
- return await self._post(
626
+ return await self._request(
627
+ Methods.POST,
656
628
  f"api/1/vehicles/{vehicle_tag}/command/set_climate_keeper_mode",
657
629
  json={climate_keeper_mode: climate_keeper_mode},
658
630
  )
659
631
 
660
- class CopTemp(IntEnum):
661
- """COP Temp options"""
662
-
663
- LOW = 0 # 30C 90F
664
- MEDIUM = 1 # 35C 95F
665
- HIGH = 2 # 40C 100F
666
-
667
632
  async def set_cop_temp(
668
- self, vehicle_tag: str | int, cop_temp: CopTemp | int
633
+ self, vehicle_tag: str | int, cop_temp: CabinOverheatProtectionTemps | int
669
634
  ) -> dict[str, Any]:
670
635
  """Adjusts the Cabin Overheat Protection temperature (COP)."""
671
636
  if self.use_command_protocol:
672
637
  raise NotImplementedError("Command Protocol not implemented")
673
- return await self._post(
638
+ return await self._request(
639
+ Methods.POST,
674
640
  f"api/1/vehicles/{vehicle_tag}/command/set_cop_temp",
675
641
  json={cop_temp: cop_temp},
676
642
  )
@@ -681,7 +647,8 @@ class TeslaFleetApi:
681
647
  """Sets a four-digit passcode for PIN to Drive. This PIN must then be entered before the vehicle can be driven."""
682
648
  if self.use_command_protocol:
683
649
  raise NotImplementedError("Command Protocol not implemented")
684
- return await self._post(
650
+ return await self._request(
651
+ Methods.POST,
685
652
  f"api/1/vehicles/{vehicle_tag}/command/set_pin_to_drive",
686
653
  json={on: on, password: str(password)},
687
654
  )
@@ -692,7 +659,8 @@ class TeslaFleetApi:
692
659
  """Sets an override for preconditioning — it should default to empty if no override is used."""
693
660
  if self.use_command_protocol:
694
661
  raise NotImplementedError("Command Protocol not implemented")
695
- return await self._post(
662
+ return await self._request(
663
+ Methods.POST,
696
664
  f"api/1/vehicles/{vehicle_tag}/command/set_preconditioning_max",
697
665
  json={on: on, manual_override: manual_override},
698
666
  )
@@ -703,7 +671,8 @@ class TeslaFleetApi:
703
671
  """Sets a time at which charging should be completed. The time parameter is minutes after midnight (e.g: time=120 schedules charging for 2:00am vehicle local time)."""
704
672
  if self.use_command_protocol:
705
673
  raise NotImplementedError("Command Protocol not implemented")
706
- return await self._post(
674
+ return await self._request(
675
+ Methods.POST,
707
676
  f"api/1/vehicles/{vehicle_tag}/command/set_scheduled_charging",
708
677
  json={enable: enable, time: time},
709
678
  )
@@ -714,7 +683,8 @@ class TeslaFleetApi:
714
683
  """Sets a time at which departure should be completed. The time parameter is minutes after midnight (e.g: time=120 schedules departure for 2:00am vehicle local time)."""
715
684
  if self.use_command_protocol:
716
685
  raise NotImplementedError("Command Protocol not implemented")
717
- return await self._post(
686
+ return await self._request(
687
+ Methods.POST,
718
688
  f"api/1/vehicles/{vehicle_tag}/command/set_scheduled_departure",
719
689
  json={enable: enable, time: time},
720
690
  )
@@ -725,8 +695,10 @@ class TeslaFleetApi:
725
695
  """Enables and disables Sentry Mode. Sentry Mode allows customers to watch the vehicle cameras live from the mobile app, as well as record sentry events."""
726
696
  if self.use_command_protocol:
727
697
  raise NotImplementedError("Command Protocol not implemented")
728
- return await self._post(
729
- f"api/1/vehicles/{vehicle_tag}/command/set_sentry_mode", json={on: on}
698
+ return await self._request(
699
+ Methods.POST,
700
+ f"api/1/vehicles/{vehicle_tag}/command/set_sentry_mode",
701
+ json={on: on},
730
702
  )
731
703
 
732
704
  async def set_temps(
@@ -735,7 +707,8 @@ class TeslaFleetApi:
735
707
  """Sets the driver and/or passenger-side cabin temperature (and other zones if sync is enabled)."""
736
708
  if self.use_command_protocol:
737
709
  raise NotImplementedError("Command Protocol not implemented")
738
- return await self._post(
710
+ return await self._request(
711
+ Methods.POST,
739
712
  f"api/1/vehicles/{vehicle_tag}/command/set_temps",
740
713
  json={driver_temp: driver_temp, passenger_temp: passenger_temp},
741
714
  )
@@ -746,7 +719,8 @@ class TeslaFleetApi:
746
719
  """Turns on Valet Mode and sets a four-digit passcode that must then be entered to disable Valet Mode."""
747
720
  if self.use_command_protocol:
748
721
  raise NotImplementedError("Command Protocol not implemented")
749
- return await self._post(
722
+ return await self._request(
723
+ Methods.POST,
750
724
  f"api/1/vehicles/{vehicle_tag}/command/set_valet_mode",
751
725
  json={on: on, password: str(password)},
752
726
  )
@@ -757,7 +731,8 @@ class TeslaFleetApi:
757
731
  """Changes the name of a vehicle. This command also requires the Tesla Vehicle Command Protocol - for more information, please see refer to the documentation here."""
758
732
  if self.use_command_protocol:
759
733
  raise NotImplementedError("Command Protocol not implemented")
760
- return await self._post(
734
+ return await self._request(
735
+ Methods.POST,
761
736
  f"api/1/vehicles/{vehicle_tag}/command/set_vehicle_name",
762
737
  json={vehicle_name: vehicle_name},
763
738
  )
@@ -768,7 +743,8 @@ class TeslaFleetApi:
768
743
  """Activates Speed Limit Mode with a four-digit PIN."""
769
744
  if self.use_command_protocol:
770
745
  raise NotImplementedError("Command Protocol not implemented")
771
- return await self._post(
746
+ return await self._request(
747
+ Methods.POST,
772
748
  f"api/1/vehicles/{vehicle_tag}/command/speed_limit_activate",
773
749
  json={pin: str(pin)},
774
750
  )
@@ -779,7 +755,8 @@ class TeslaFleetApi:
779
755
  """Deactivates Speed Limit Mode and resets the associated PIN."""
780
756
  if self.use_command_protocol:
781
757
  raise NotImplementedError("Command Protocol not implemented")
782
- return await self._post(
758
+ return await self._request(
759
+ Methods.POST,
783
760
  f"api/1/vehicles/{vehicle_tag}/command/speed_limit_clear_pin",
784
761
  json={pin: str(pin)},
785
762
  )
@@ -788,8 +765,9 @@ class TeslaFleetApi:
788
765
  self, vehicle_tag: str | int
789
766
  ) -> dict[str, Any]:
790
767
  """Deactivates Speed Limit Mode and resets the associated PIN for vehicles running firmware versions 2023.38+. This command is only accessible to fleet managers or owners."""
791
- return await self._post(
792
- f"api/1/vehicles/{vehicle_tag}/command/speed_limit_clear_pin_admin"
768
+ return await self._request(
769
+ Methods.POST,
770
+ f"api/1/vehicles/{vehicle_tag}/command/speed_limit_clear_pin_admin",
793
771
  )
794
772
 
795
773
  async def speed_limit_deactivate(
@@ -798,7 +776,8 @@ class TeslaFleetApi:
798
776
  """Deactivates Speed Limit Mode."""
799
777
  if self.use_command_protocol:
800
778
  raise NotImplementedError("Command Protocol not implemented")
801
- return await self._post(
779
+ return await self._request(
780
+ Methods.POST,
802
781
  f"api/1/vehicles/{vehicle_tag}/command/speed_limit_deactivate",
803
782
  json={pin: str(pin)},
804
783
  )
@@ -809,23 +788,18 @@ class TeslaFleetApi:
809
788
  """Sets the maximum speed allowed when Speed Limit Mode is active."""
810
789
  if self.use_command_protocol:
811
790
  raise NotImplementedError("Command Protocol not implemented")
812
- return await self._post(
791
+ return await self._request(
792
+ Methods.POST,
813
793
  f"api/1/vehicles/{vehicle_tag}/command/speed_limit_set_limit",
814
794
  json={limit_mph: limit_mph},
815
795
  )
816
796
 
817
- class SunRoof(StrEnum):
818
- """Sunroof options"""
819
-
820
- STOP = "stop"
821
- CLOSE = "close"
822
- VENT = "vent"
823
-
824
797
  async def sun_roof_control(
825
- self, vehicle_tag: str | int, state: str | SunRoof
798
+ self, vehicle_tag: str | int, state: str | SunRoofCommands
826
799
  ) -> dict[str, Any]:
827
800
  """Controls the panoramic sunroof on the Model S."""
828
- return await self._post(
801
+ return await self._request(
802
+ Methods.POST,
829
803
  f"api/1/vehicles/{vehicle_tag}/command/sun_roof_control",
830
804
  {state: state},
831
805
  )
@@ -834,8 +808,10 @@ class TeslaFleetApi:
834
808
  self, vehicle_tag: str | int, note: str
835
809
  ) -> dict[str, Any]:
836
810
  """Records a drive note. The note parameter is truncated to 80 characters in length."""
837
- return await self._post(
838
- f"api/1/vehicles/{vehicle_tag}/command/take_drivenote", {note: note}
811
+ return await self._request(
812
+ Methods.POST,
813
+ f"api/1/vehicles/{vehicle_tag}/command/take_drivenote",
814
+ {note: note},
839
815
  )
840
816
 
841
817
  async def trigger_homelink(
@@ -844,7 +820,8 @@ class TeslaFleetApi:
844
820
  """Turns on HomeLink (used to open and close garage doors)."""
845
821
  if self.use_command_protocol:
846
822
  raise NotImplementedError("Command Protocol not implemented")
847
- return await self._post(
823
+ return await self._request(
824
+ Methods.POST,
848
825
  f"api/1/vehicles/{vehicle_tag}/command/trigger_homelink",
849
826
  {lat: lat, lon: lon, token: token},
850
827
  )
@@ -853,51 +830,55 @@ class TeslaFleetApi:
853
830
  self, vehicle_tag: str | int, calendar_data: str
854
831
  ) -> dict[str, Any]:
855
832
  """Upcoming calendar entries stored on the vehicle."""
856
- return await self._post(
833
+ return await self._request(
834
+ Methods.POST,
857
835
  f"api/1/vehicles/{vehicle_tag}/command/upcoming_calendar_entries",
858
836
  {calendar_data: calendar_data},
859
837
  )
860
838
 
861
- class WindowControl(StrEnum):
862
- """Window Control options"""
863
-
864
- VENT = "vent"
865
- CLOSE = "close"
866
-
867
839
  async def window_control(
868
840
  self,
869
841
  vehicle_tag: str | int,
870
842
  lat: float,
871
843
  lon: float,
872
- command: str | WindowControl,
844
+ command: str | WindowCommands,
873
845
  ) -> dict[str, Any]:
874
846
  """Control the windows of a parked vehicle. Supported commands: vent and close. When closing, specify lat and lon of user to ensure they are within range of vehicle (unless this is an M3 platform vehicle)."""
875
- return await self._post(
847
+ return await self._request(
848
+ Methods.POST,
876
849
  f"api/1/vehicles/{vehicle_tag}/command/window_control",
877
850
  {lat: lat, lon: lon, command: command},
878
851
  )
879
852
 
880
853
  async def drivers(self, vehicle_tag: str | int) -> dict[str, Any]:
881
854
  """Returns all allowed drivers for a vehicle. This endpoint is only available for the vehicle owner."""
882
- return await self._get(f"api/1/vehicles/{vehicle_tag}/drivers")
855
+ return await self._request(
856
+ Methods.GET, f"api/1/vehicles/{vehicle_tag}/drivers"
857
+ )
883
858
 
884
859
  async def drivers_remove(
885
860
  self, vehicle_tag: str | int, share_user_id: str | int | None = None
886
861
  ) -> dict[str, Any]:
887
862
  """Removes driver access from a vehicle. Share users can only remove their own access. Owners can remove share access or their own."""
888
- return await self._delete(
889
- f"api/1/vehicles/{vehicle_tag}/drivers", {share_user_id: share_user_id}
863
+ return await self._request(
864
+ Methods.DELETE,
865
+ f"api/1/vehicles/{vehicle_tag}/drivers",
866
+ {share_user_id: share_user_id},
890
867
  )
891
868
 
892
869
  async def list(
893
870
  self, page: int | None = None, per_page: int | None = None
894
871
  ) -> dict[str, Any]:
895
872
  """Returns vehicles belonging to the account."""
896
- return await self._get("api/1/vehicles", {page: page, per_page: per_page})
873
+ return await self._request(
874
+ Methods.GET, "api/1/vehicles", {page: page, per_page: per_page}
875
+ )
897
876
 
898
877
  async def mobile_enabled(self, vehicle_tag: str | int) -> dict[str, Any]:
899
878
  """Returns whether or not mobile access is enabled for the vehicle."""
900
- return await self._get(f"api/1/vehicles/{vehicle_tag}/mobile_enabled")
879
+ return await self._request(
880
+ Methods.GET, f"api/1/vehicles/{vehicle_tag}/mobile_enabled"
881
+ )
901
882
 
902
883
  async def nearby_charging_sites(
903
884
  self,
@@ -907,18 +888,23 @@ class TeslaFleetApi:
907
888
  detail: bool | None = None,
908
889
  ) -> dict[str, Any]:
909
890
  """Returns the charging sites near the current location of the vehicle."""
910
- return await self._get(
891
+ return await self._request(
892
+ Methods.GET,
911
893
  f"api/1/vehicles/{vehicle_tag}/nearby_charging_sites",
912
894
  {count: count, radius: radius, detail: detail},
913
895
  )
914
896
 
915
897
  async def options(self, vin: str) -> dict[str, Any]:
916
898
  """Returns vehicle option details."""
917
- return await self._get("api/1/dx/vehicles/options", {vin: vin})
899
+ return await self._request(
900
+ Methods.GET, "api/1/dx/vehicles/options", {vin: vin}
901
+ )
918
902
 
919
903
  async def recent_alerts(self, vehicle_tag: str | int) -> dict[str, Any]:
920
904
  """List of recent alerts"""
921
- return await self._get(f"api/1/vehicles/{vehicle_tag}/recent_alerts")
905
+ return await self._request(
906
+ Methods.GET, f"api/1/vehicles/{vehicle_tag}/recent_alerts"
907
+ )
922
908
 
923
909
  async def release_notes(
924
910
  self,
@@ -927,40 +913,50 @@ class TeslaFleetApi:
927
913
  language: int | None = None,
928
914
  ) -> dict[str, Any]:
929
915
  """Returns firmware release notes."""
930
- return await self._get(
916
+ return await self._request(
917
+ Methods.GET,
931
918
  f"api/1/vehicles/{vehicle_tag}/release_notes",
932
919
  {staged: staged, language: language},
933
920
  )
934
921
 
935
922
  async def service_data(self, vehicle_tag: str | int) -> dict[str, Any]:
936
923
  """Returns service data."""
937
- return await self._get(f"api/1/vehicles/{vehicle_tag}/service_data")
924
+ return await self._request(
925
+ Methods.GET, f"api/1/vehicles/{vehicle_tag}/service_data"
926
+ )
938
927
 
939
928
  async def share_invites(self, vehicle_tag: str | int) -> dict[str, Any]:
940
929
  """Returns the share invites for a vehicle."""
941
- return await self._get(f"api/1/vehicles/{vehicle_tag}/invitations")
930
+ return await self._request(
931
+ Methods.GET, f"api/1/vehicles/{vehicle_tag}/invitations"
932
+ )
942
933
 
943
934
  async def share_invites_create(self, vehicle_tag: str | int) -> dict[str, Any]:
944
935
  """Creates a share invite for a vehicle."""
945
- return await self._post(f"api/1/vehicles/{vehicle_tag}/invitations")
936
+ return await self._request(
937
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/invitations"
938
+ )
946
939
 
947
940
  async def share_invites_redeem(self, code: str) -> dict[str, Any]:
948
941
  """Redeems a share invite."""
949
- return await self._post("api/1/invitations/redeem", {code: code})
942
+ return await self._request(
943
+ Methods.POST, "api/1/invitations/redeem", {code: code}
944
+ )
950
945
 
951
946
  async def share_invites_revoke(
952
947
  self, vehicle_tag: str | int, id: str
953
948
  ) -> dict[str, Any]:
954
949
  """Revokes a share invite."""
955
- return await self._post(
956
- f"api/1/vehicles/{vehicle_tag}/invitations/{id}/revoke"
950
+ return await self._request(
951
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/invitations/{id}/revoke"
957
952
  )
958
953
 
959
954
  async def signed_command(
960
955
  self, vehicle_tag: str | int, routable_message: str
961
956
  ) -> dict[str, Any]:
962
957
  """Signed Commands is a generic endpoint replacing legacy commands."""
963
- return await self._post(
958
+ return await self._request(
959
+ Methods.POST,
964
960
  f"api/1/vehicles/{vehicle_tag}/signed_command",
965
961
  {routable_message: routable_message},
966
962
  )
@@ -969,7 +965,8 @@ class TeslaFleetApi:
969
965
  self, device_token: str, device_type: str
970
966
  ) -> dict[str, Any]:
971
967
  """Returns the list of vehicles for which this mobile device currently subscribes to push notifications."""
972
- return await self._get(
968
+ return await self._request(
969
+ Methods.GET,
973
970
  "api/1/subscriptions",
974
971
  query={device_token: device_token, device_type: device_type},
975
972
  )
@@ -978,69 +975,516 @@ class TeslaFleetApi:
978
975
  self, device_token: str, device_type: str
979
976
  ) -> dict[str, Any]:
980
977
  """Allows a mobile device to specify which vehicles to receive push notifications from."""
981
- return await self._post(
978
+ return await self._request(
979
+ Methods.POST,
982
980
  "api/1/subscriptions",
983
981
  query={device_token: device_token, device_type: device_type},
984
982
  )
985
983
 
986
984
  async def vehicle(self, vehicle_tag: str | int) -> dict[str, Any]:
987
985
  """Returns information about a vehicle."""
988
- return await self._get(f"api/1/vehicles/{vehicle_tag}")
989
-
990
- class Endpoints(StrEnum):
991
- """Endpoints options"""
992
-
993
- CHARGE_STATE = "charge_state"
994
- CLIMATE_STATE = "climate_state"
995
- CLOSURES_STATE = "closures_state"
996
- DRIVE_STATE = "drive_state"
997
- GUI_SETTINGS = "gui_settings"
998
- LOCATION_DATA = "location_data"
999
- VEHICLE_CONFIG = "vehicle_config"
1000
- VEHICLE_STATE = "vehicle_state"
1001
- VEHICLE_DATA_COMBO = "vehicle_data_combo"
986
+ return await self._request(Methods.GET, f"api/1/vehicles/{vehicle_tag}")
1002
987
 
1003
988
  async def vehicle_data(
1004
989
  self,
1005
990
  vehicle_tag: str | int,
1006
- endpoints: Endpoints | str | None = None,
991
+ endpoints: VehicleDataEndpoints | str | None = None,
1007
992
  ) -> dict[str, Any]:
1008
993
  """Makes a live call to the vehicle. This may return cached data if the vehicle is offline. For vehicles running firmware versions 2023.38+, location_data is required to fetch vehicle location. This will result in a location sharing icon to show on the vehicle UI."""
1009
- return await self._get(
1010
- f"api/1/vehicles/{vehicle_tag}/vehicle_data", {endpoints: endpoints}
994
+ return await self._request(
995
+ Methods.GET,
996
+ f"api/1/vehicles/{vehicle_tag}/vehicle_data",
997
+ {endpoints: endpoints},
1011
998
  )
1012
999
 
1013
- class DeviceType(StrEnum):
1014
- """Device Type options"""
1015
-
1016
- ANDROID = "android"
1017
- IOS_DEVELOPMENT = "ios-development"
1018
- IOS_ENTERPRISE = "ios-enterprise"
1019
- IOS_BETA = "ios-beta"
1020
- IOS_PRODUCTION = "ios-production"
1021
-
1022
1000
  async def vehicle_subscriptions(
1023
- self, device_token: str, device_type: DeviceType | str
1001
+ self, device_token: str, device_type: DeviceTypes | str
1024
1002
  ) -> dict[str, Any]:
1025
1003
  """Returns the list of vehicles for which this mobile device currently subscribes to push notifications."""
1026
- return await self._get(
1004
+ return await self._request(
1005
+ Methods.GET,
1027
1006
  "api/1/vehicle_subscriptions",
1028
1007
  {device_token: device_token, device_type: device_type},
1029
1008
  )
1030
1009
 
1031
1010
  async def vehicle_subscriptions_set(
1032
- self, device_token: str, device_type: DeviceType | str
1011
+ self, device_token: str, device_type: DeviceTypes | str
1033
1012
  ) -> dict[str, Any]:
1034
1013
  """Allows a mobile device to specify which vehicles to receive push notifications from."""
1035
- return await self._post(
1014
+ return await self._request(
1015
+ Methods.POST,
1036
1016
  "api/1/vehicle_subscriptions",
1037
1017
  params={device_token: device_token, device_type: device_type},
1038
1018
  )
1039
1019
 
1040
1020
  async def wake_up(self, vehicle_tag: str | int) -> dict[str, Any]:
1041
1021
  """Wakes the vehicle from sleep, which is a state to minimize idle energy consumption."""
1042
- return await self._post(f"api/1/vehicles/{vehicle_tag}/wake_up")
1022
+ return await self._request(
1023
+ Methods.POST, f"api/1/vehicles/{vehicle_tag}/wake_up"
1024
+ )
1043
1025
 
1044
1026
  async def warranty_details(self, vin: str | None) -> dict[str, Any]:
1045
1027
  """Returns warranty details."""
1046
- return await self._get("api/1/dx/warranty/details", {vin: vin})
1028
+ return await self._request(
1029
+ Methods.GET, "api/1/dx/warranty/details", {vin: vin}
1030
+ )
1031
+
1032
+ async def fleet_telemetry_config(
1033
+ self, config: dict[str, Any]
1034
+ ) -> dict[str, Any]:
1035
+ """Configures fleet telemetry."""
1036
+ return await self._request(
1037
+ Methods.POST, "api/1/vehicles/fleet_telemetry_config", json=config
1038
+ )
1039
+
1040
+ class Specific:
1041
+ """Class describing the Tesla Fleet API vehicle endpoints and commands for a specific vehicle."""
1042
+
1043
+ def __init__(self, parent, vin: str | None = None):
1044
+ self.parent = parent
1045
+ self.vin = vin
1046
+
1047
+ async def actuate_trunk(self, which_trunk: Trunks | str) -> dict[str, Any]:
1048
+ """Controls the front or rear trunk."""
1049
+ return await self.parent.actuate_trunk(self.vin, which_trunk)
1050
+
1051
+ async def adjust_volume(self, volume: float) -> dict[str, Any]:
1052
+ """Adjusts vehicle media playback volume."""
1053
+ return await self.parent.adjust_volume(self.vin, volume)
1054
+
1055
+ async def auto_conditioning_start(self) -> dict[str, Any]:
1056
+ """Starts climate preconditioning."""
1057
+ return await self.parent.auto_conditioning_start(self.vin)
1058
+
1059
+ async def auto_conditioning_stop(self) -> dict[str, Any]:
1060
+ """Stops climate preconditioning."""
1061
+ return await self.parent.auto_conditioning_stop(self.vin)
1062
+
1063
+ async def cancel_software_update(self) -> dict[str, Any]:
1064
+ """Cancels the countdown to install the vehicle software update."""
1065
+ return await self.parent.cancel_software_update(self.vin)
1066
+
1067
+ async def charge_max_range(self) -> dict[str, Any]:
1068
+ """Charges in max range mode -- we recommend limiting the use of this mode to long trips."""
1069
+ return await self.parent.charge_max_range(self.vin)
1070
+
1071
+ async def charge_port_door_close(self) -> dict[str, Any]:
1072
+ """Closes the charge port door."""
1073
+ return await self.parent.charge_port_door_close(self.vin)
1074
+
1075
+ async def charge_port_door_open(self) -> dict[str, Any]:
1076
+ """Opens the charge port door."""
1077
+ return await self.parent.charge_port_door_open(self.vin)
1078
+
1079
+ async def charge_standard(self) -> dict[str, Any]:
1080
+ """Charges in Standard mode."""
1081
+ return await self.parent.charge_standard(self.vin)
1082
+
1083
+ async def charge_start(self) -> dict[str, Any]:
1084
+ """Starts charging the vehicle."""
1085
+ return await self.parent.charge_start(self.vin)
1086
+
1087
+ async def charge_stop(self) -> dict[str, Any]:
1088
+ """Stops charging the vehicle."""
1089
+ return await self.parent.charge_stop(self.vin)
1090
+
1091
+ async def clear_pin_to_drive_admin(self):
1092
+ """Deactivates PIN to Drive and resets the associated PIN for vehicles running firmware versions 2023.44+. This command is only accessible to fleet managers or owners."""
1093
+ return await self.parent.clear_pin_to_drive_admin(self.vin)
1094
+
1095
+ async def door_lock(self) -> dict[str, Any]:
1096
+ """Locks the vehicle."""
1097
+ return await self.parent.door_lock(self.vin)
1098
+
1099
+ async def door_unlock(self) -> dict[str, Any]:
1100
+ """Unlocks the vehicle."""
1101
+ return await self.parent.door_unlock(self.vin)
1102
+
1103
+ async def erase_user_data(self) -> dict[str, Any]:
1104
+ """Erases user's data from the user interface. Requires the vehicle to be in park."""
1105
+ return await self.parent.erase_user_data(self.vin)
1106
+
1107
+ async def flash_lights(self) -> dict[str, Any]:
1108
+ """Briefly flashes the vehicle headlights. Requires the vehicle to be in park."""
1109
+ return await self.parent.flash_lights(self.vin)
1110
+
1111
+ async def guest_mode(self, enable: bool) -> dict[str, Any]:
1112
+ """Restricts certain vehicle UI functionality from guest users"""
1113
+ return await self.parent.guest_mode(self.vin, enable)
1114
+
1115
+ async def honk_horn(self) -> dict[str, Any]:
1116
+ """Honks the vehicle horn. Requires the vehicle to be in park."""
1117
+ return await self.parent.honk_horn(self.vin)
1118
+
1119
+ async def media_next_fav(self) -> dict[str, Any]:
1120
+ """Advances media player to next favorite track."""
1121
+ return await self.parent.media_next_fav(self.vin)
1122
+
1123
+ async def media_next_track(self) -> dict[str, Any]:
1124
+ """Advances media player to next track."""
1125
+ return await self.parent.media_next_track(self.vin)
1126
+
1127
+ async def media_prev_fav(self) -> dict[str, Any]:
1128
+ """Advances media player to previous favorite track."""
1129
+ return await self.parent.media_prev_fav(self.vin)
1130
+
1131
+ async def media_prev_track(self) -> dict[str, Any]:
1132
+ """Advances media player to previous track."""
1133
+ return await self.parent.media_prev_track(self.vin)
1134
+
1135
+ async def media_toggle_playback(self) -> dict[str, Any]:
1136
+ """Toggles current play/pause state."""
1137
+ return await self.parent.media_toggle_playback(self.vin)
1138
+
1139
+ async def media_volume_down(self) -> dict[str, Any]:
1140
+ """Turns the volume down by one."""
1141
+ return await self.parent.media_volume_down(self.vin)
1142
+
1143
+ async def navigation_gps_request(
1144
+ self, lat: float, lon: float, order: int
1145
+ ) -> dict[str, Any]:
1146
+ """Start navigation to given coordinates. Order can be used to specify order of multiple stops."""
1147
+ self.parent.navigation_gps_request(self.vin, lat, lon, order)
1148
+
1149
+ async def navigation_request(
1150
+ self, type: str, locale: str, timestamp_ms: str
1151
+ ) -> dict[str, Any]:
1152
+ """Sends a location to the in-vehicle navigation system."""
1153
+ return await self.parent.navigation_request(
1154
+ self.vin, type, locale, timestamp_ms
1155
+ )
1156
+
1157
+ async def navigation_sc_request(
1158
+ self, id: int, order: int
1159
+ ) -> dict[str, Any]:
1160
+ """Sends a location to the in-vehicle navigation system."""
1161
+ return await self.parent.navigation_sc_request(self.vin, id, order)
1162
+
1163
+ async def remote_auto_seat_climate_request(
1164
+ self, auto_seat_position: int, auto_climate_on: bool
1165
+ ) -> dict[str, Any]:
1166
+ """Sets automatic seat heating and cooling."""
1167
+ return await self.parent.remote_auto_seat_climate_request(
1168
+ self.vin, auto_seat_position, auto_climate_on
1169
+ )
1170
+
1171
+ async def remote_auto_steering_wheel_heat_climate_request(
1172
+ self, on: bool
1173
+ ) -> dict[str, Any]:
1174
+ """Sets automatic steering wheel heating on/off."""
1175
+ return (
1176
+ await self.parent.remote_auto_steering_wheel_heat_climate_request(
1177
+ self.vin, on
1178
+ )
1179
+ )
1180
+
1181
+ async def remote_boombox(self, sound: int) -> dict[str, Any]:
1182
+ """Plays a sound through the vehicle external speaker."""
1183
+ return await self.parent.remote_boombox(self.vin, sound)
1184
+
1185
+ async def remote_seat_cooler_request(
1186
+ self, seat_position: int, seat_cooler_level: int
1187
+ ) -> dict[str, Any]:
1188
+ """Sets seat cooling."""
1189
+ return await self.parent.remote_seat_cooler_request(
1190
+ self.vin, seat_position, seat_cooler_level
1191
+ )
1192
+
1193
+ async def remote_seat_heater_request(self) -> dict[str, Any]:
1194
+ """Sets seat heating."""
1195
+ return await self.parent.remote_seat_heater_request(self.vin)
1196
+
1197
+ async def remote_start_drive(self) -> dict[str, Any]:
1198
+ """Starts the vehicle remotely. Requires keyless driving to be enabled."""
1199
+ return await self.parent.remote_start_drive(self.vin)
1200
+
1201
+ async def remote_steering_wheel_heat_level_request(
1202
+ self, level: int
1203
+ ) -> dict[str, Any]:
1204
+ """Sets steering wheel heat level."""
1205
+ return await self.parent.remote_steering_wheel_heat_level_request(
1206
+ self.vin, level
1207
+ )
1208
+
1209
+ async def remote_steering_wheel_heater_request(
1210
+ self, on: bool
1211
+ ) -> dict[str, Any]:
1212
+ """Sets steering wheel heating on/off. For vehicles that do not support auto steering wheel heat."""
1213
+ return await self.parent.remote_steering_wheel_heater_request(
1214
+ self.vin, on
1215
+ )
1216
+
1217
+ async def reset_pin_to_drive_pin(self) -> dict[str, Any]:
1218
+ """Removes PIN to Drive. Requires the car to be in Pin to Drive mode and not in Valet mode. Note that this only works if PIN to Drive is not active. This command also requires the Tesla Vehicle Command Protocol - for more information, please see refer to the documentation here."""
1219
+ return await self.parent.reset_pin_to_drive_pin(self.vin)
1220
+
1221
+ async def reset_valet_pin(self) -> dict[str, Any]:
1222
+ """Removes PIN for Valet Mode."""
1223
+ return await self.parent.reset_valet_pin(self.vin)
1224
+
1225
+ async def schedule_software_update(self, offset_sec: int) -> dict[str, Any]:
1226
+ """Schedules a vehicle software update (over the air "OTA") to be installed in the future."""
1227
+ return await self.parent.schedule_software_update(self.vin, offset_sec)
1228
+
1229
+ async def set_bioweapon_mode(
1230
+ self, on: bool, manual_override: bool
1231
+ ) -> dict[str, Any]:
1232
+ """Turns Bioweapon Defense Mode on and off."""
1233
+ return await self.parent.set_bioweapon_mode(
1234
+ self.vin, on, manual_override
1235
+ )
1236
+
1237
+ async def set_cabin_overheat_protection(
1238
+ self, on: bool, fan_only: bool
1239
+ ) -> dict[str, Any]:
1240
+ """Sets the vehicle overheat protection."""
1241
+ return await self.parent.set_cabin_overheat_protection(
1242
+ self.vin, on, fan_only
1243
+ )
1244
+
1245
+ async def set_charge_limit(self, percent: int) -> dict[str, Any]:
1246
+ """Sets the vehicle charge limit."""
1247
+ return await self.parent.set_charge_limit(self.vin, percent)
1248
+
1249
+ async def set_charging_amps(self, charging_amps: int) -> dict[str, Any]:
1250
+ """Sets the vehicle charging amps."""
1251
+ return await self.parent.set_charging_amps(self.vin, charging_amps)
1252
+
1253
+ async def set_climate_keeper_mode(
1254
+ self, climate_keeper_mode: ClimateKeeperMode | int
1255
+ ) -> dict[str, Any]:
1256
+ """Enables climate keeper mode."""
1257
+ return await self.parent.set_climate_keeper_mode(
1258
+ self.vin, climate_keeper_mode
1259
+ )
1260
+
1261
+ async def set_cop_temp(
1262
+ self, cop_temp: CabinOverheatProtectionTemps | int
1263
+ ) -> dict[str, Any]:
1264
+ """Adjusts the Cabin Overheat Protection temperature (COP)."""
1265
+ return await self.parent.set_cop_temp(self.vin, cop_temp)
1266
+
1267
+ async def set_pin_to_drive(
1268
+ self, on: bool, password: str | int
1269
+ ) -> dict[str, Any]:
1270
+ """Sets a four-digit passcode for PIN to Drive. This PIN must then be entered before the vehicle can be driven."""
1271
+ return await self.parent.set_pin_to_drive(self.vin, on, password)
1272
+
1273
+ async def set_preconditioning_max(
1274
+ self, on: bool, manual_override: bool
1275
+ ) -> dict[str, Any]:
1276
+ """Sets an override for preconditioning — it should default to empty if no override is used."""
1277
+ return await self.parent.set_preconditioning_max(
1278
+ self.vin, on, manual_override
1279
+ )
1280
+
1281
+ async def set_scheduled_charging(
1282
+ self, enable: bool, time: int
1283
+ ) -> dict[str, Any]:
1284
+ """Sets a time at which charging should be completed. The time parameter is minutes after midnight (e.g: time=120 schedules charging for 2:00am vehicle local time)."""
1285
+ return await self.parent.set_scheduled_charging(self.vin, enable, time)
1286
+
1287
+ async def set_scheduled_departure(
1288
+ self, enable: bool, time: int
1289
+ ) -> dict[str, Any]:
1290
+ """Sets a time at which departure should be completed. The time parameter is minutes after midnight (e.g: time=120 schedules departure for 2:00am vehicle local time)."""
1291
+ return await self.parent.set_scheduled_departure(self.vin, enable, time)
1292
+
1293
+ async def set_sentry_mode(self, on: bool) -> dict[str, Any]:
1294
+ """Enables and disables Sentry Mode. Sentry Mode allows customers to watch the vehicle cameras live from the mobile app, as well as record sentry events."""
1295
+ return await self.parent.set_sentry_mode(self.vin, on)
1296
+
1297
+ async def set_temps(
1298
+ self, driver_temp: int, passenger_temp: int
1299
+ ) -> dict[str, Any]:
1300
+ """Sets the driver and/or passenger-side cabin temperature (and other zones if sync is enabled)."""
1301
+ return await self.parent.set_temps(
1302
+ self.vin, driver_temp, passenger_temp
1303
+ )
1304
+
1305
+ async def set_valet_mode(
1306
+ self, on: bool, password: str | int
1307
+ ) -> dict[str, Any]:
1308
+ """Turns on Valet Mode and sets a four-digit passcode that must then be entered to disable Valet Mode."""
1309
+ return await self.parent.set_valet_mode(self.vin, on, password)
1310
+
1311
+ async def set_vehicle_name(self, vehicle_name: str) -> dict[str, Any]:
1312
+ """Changes the name of a vehicle. This command also requires the Tesla Vehicle Command Protocol - for more information, please see refer to the documentation here."""
1313
+ return await self.parent.set_vehicle_name(self.vin, vehicle_name)
1314
+
1315
+ async def speed_limit_activate(self, pin: str | int) -> dict[str, Any]:
1316
+ """Activates Speed Limit Mode with a four-digit PIN."""
1317
+ return await self.parent.speed_limit_activate(self.vin, pin)
1318
+
1319
+ async def speed_limit_clear_pin(self, pin: str | int) -> dict[str, Any]:
1320
+ """Deactivates Speed Limit Mode and resets the associated PIN."""
1321
+ return await self.parent.speed_limit_clear_pin(self.vin, pin)
1322
+
1323
+ async def speed_limit_clear_pin_admin(self) -> dict[str, Any]:
1324
+ """Deactivates Speed Limit Mode and resets the associated PIN for vehicles running firmware versions 2023.38+. This command is only accessible to fleet managers or owners."""
1325
+ return await self.parent.speed_limit_clear_pin_admin(self.vin)
1326
+
1327
+ async def speed_limit_deactivate(self, pin: str | int) -> dict[str, Any]:
1328
+ """Deactivates Speed Limit Mode."""
1329
+ return await self.parent.speed_limit_deactivate(self.vin, pin)
1330
+
1331
+ async def speed_limit_set_limit(self, limit_mph: int) -> dict[str, Any]:
1332
+ """Sets the maximum speed allowed when Speed Limit Mode is active."""
1333
+ return await self.parent.speed_limit_set_limit(self.vin, limit_mph)
1334
+
1335
+ async def sun_roof_control(
1336
+ self, state: str | SunRoofCommands
1337
+ ) -> dict[str, Any]:
1338
+ """Controls the panoramic sunroof on the Model S."""
1339
+ return await self.parent.sun_roof_control(self.vin, state)
1340
+
1341
+ async def take_drivenote(self, note: str) -> dict[str, Any]:
1342
+ """Records a drive note. The note parameter is truncated to 80 characters in length."""
1343
+ return await self.parent.take_drivenote(self.vin, note)
1344
+
1345
+ async def trigger_homelink(
1346
+ self, lat: float, lon: float, token: str
1347
+ ) -> dict[str, Any]:
1348
+ """Turns on HomeLink (used to open and close garage doors)."""
1349
+ return await self.parent.trigger_homelink(self.vin, lat, lon, token)
1350
+
1351
+ async def upcoming_calendar_entries(
1352
+ self, calendar_data: str
1353
+ ) -> dict[str, Any]:
1354
+ """Upcoming calendar entries stored on the vehicle."""
1355
+ return await self.parent.upcoming_calendar_entries(
1356
+ self.vin, calendar_data
1357
+ )
1358
+
1359
+ async def window_control(
1360
+ self,
1361
+ vehicle_tag: str | int,
1362
+ lat: float,
1363
+ lon: float,
1364
+ command: str | WindowCommands,
1365
+ ) -> dict[str, Any]:
1366
+ """Control the windows of a parked vehicle. Supported commands: vent and close. When closing, specify lat and lon of user to ensure they are within range of vehicle (unless this is an M3 platform vehicle)."""
1367
+ return await self.parent.window_control(self.vin, lat, lon, command)
1368
+
1369
+ async def drivers(self) -> dict[str, Any]:
1370
+ """Returns all allowed drivers for a vehicle. This endpoint is only available for the vehicle owner."""
1371
+ return await self.parent.drivers(self.vin)
1372
+
1373
+ async def drivers_remove(
1374
+ self, share_user_id: str | int | None = None
1375
+ ) -> dict[str, Any]:
1376
+ """Removes driver access from a vehicle. Share users can only remove their own access. Owners can remove share access or their own."""
1377
+ return await self.parent.drivers_remove(self.vin, share_user_id)
1378
+
1379
+ async def mobile_enabled(self) -> dict[str, Any]:
1380
+ """Returns whether or not mobile access is enabled for the vehicle."""
1381
+ return await self.parent.mobile_enabled(self.vin)
1382
+
1383
+ async def nearby_charging_sites(
1384
+ self,
1385
+ vehicle_tag: str | int,
1386
+ count: int | None = None,
1387
+ radius: int | None = None,
1388
+ detail: bool | None = None,
1389
+ ) -> dict[str, Any]:
1390
+ """Returns the charging sites near the current location of the vehicle."""
1391
+ return await self.parent.nearby_charging_sites(
1392
+ self.vin, count, radius, detail
1393
+ )
1394
+
1395
+ async def options(self, vin: str) -> dict[str, Any]:
1396
+ """Returns vehicle option details."""
1397
+ return await self.parent.options(self.vin)
1398
+
1399
+ async def recent_alerts(self) -> dict[str, Any]:
1400
+ """List of recent alerts"""
1401
+ return await self.parent.recent_alerts(self.vin)
1402
+
1403
+ async def release_notes(
1404
+ self,
1405
+ vehicle_tag: str | int,
1406
+ staged: bool | None = None,
1407
+ language: int | None = None,
1408
+ ) -> dict[str, Any]:
1409
+ """Returns firmware release notes."""
1410
+ return await self.parent.release_notes(self.vin, staged, language)
1411
+
1412
+ async def service_data(self) -> dict[str, Any]:
1413
+ """Returns service data."""
1414
+ return await self.parent.service_data(self.vin)
1415
+
1416
+ async def share_invites(self) -> dict[str, Any]:
1417
+ """Returns the share invites for a vehicle."""
1418
+ return await self.parent.share_invites(self.vin)
1419
+
1420
+ async def share_invites_create(self) -> dict[str, Any]:
1421
+ """Creates a share invite for a vehicle."""
1422
+ return await self.parent.share_invites_create(self.vin)
1423
+
1424
+ async def share_invites_redeem(self, code: str) -> dict[str, Any]:
1425
+ """Redeems a share invite."""
1426
+ return await self.parent.share_invites_redeem(code)
1427
+
1428
+ async def share_invites_revoke(self, id: str) -> dict[str, Any]:
1429
+ """Revokes a share invite."""
1430
+ return await self.parent.share_invites_revoke(self.vin, id)
1431
+
1432
+ async def signed_command(self, routable_message: str) -> dict[str, Any]:
1433
+ """Signed Commands is a generic endpoint replacing legacy commands."""
1434
+ return await self.parent.signed_command(self.vin, routable_message)
1435
+
1436
+ async def subscriptions(
1437
+ self, device_token: str, device_type: str
1438
+ ) -> dict[str, Any]:
1439
+ """Returns the list of vehicles for which this mobile device currently subscribes to push notifications."""
1440
+ return await self.parent.subscriptions(
1441
+ self.vin, device_token, device_type
1442
+ )
1443
+
1444
+ async def subscriptions_set(
1445
+ self, device_token: str, device_type: str
1446
+ ) -> dict[str, Any]:
1447
+ """Allows a mobile device to specify which vehicles to receive push notifications from."""
1448
+ return await self.parent.subscriptions_set(
1449
+ self.vin, device_token, device_type
1450
+ )
1451
+
1452
+ async def vehicle(self) -> dict[str, Any]:
1453
+ """Returns information about a vehicle."""
1454
+ return await self.parent.vehicle(self.vin)
1455
+
1456
+ async def vehicle_data(
1457
+ self,
1458
+ endpoints: VehicleDataEndpoints | str | None = None,
1459
+ ) -> dict[str, Any]:
1460
+ """Makes a live call to the vehicle. This may return cached data if the vehicle is offline. For vehicles running firmware versions 2023.38+, location_data is required to fetch vehicle location. This will result in a location sharing icon to show on the vehicle UI."""
1461
+ return await self.parent.vehicle_data(self.vin, endpoints)
1462
+
1463
+ async def vehicle_subscriptions(
1464
+ self, device_token: str, device_type: DeviceTypes | str
1465
+ ) -> dict[str, Any]:
1466
+ """Returns the list of vehicles for which this mobile device currently subscribes to push notifications."""
1467
+ return await self.parent.vehicle_subscriptions(
1468
+ self.vin, device_token, device_type
1469
+ )
1470
+
1471
+ async def vehicle_subscriptions_set(
1472
+ self, device_token: str, device_type: DeviceTypes | str
1473
+ ) -> dict[str, Any]:
1474
+ """Allows a mobile device to specify which vehicles to receive push notifications from."""
1475
+ return await self.parent.vehicle_subscriptions_set(
1476
+ self.vin, device_token, device_type
1477
+ )
1478
+
1479
+ async def wake_up(self) -> dict[str, Any]:
1480
+ """Wakes the vehicle from sleep, which is a state to minimize idle energy consumption."""
1481
+ return await self.parent.wake_up(self.vin)
1482
+
1483
+ async def warranty_details(self) -> dict[str, Any]:
1484
+ """Returns warranty details."""
1485
+ return await self.parent.warranty_details(self.vin)
1486
+
1487
+ async def create(self) -> [Specific]:
1488
+ """Creates a class for each vehicle."""
1489
+ list = await self.list()
1490
+ return [self.Specific(self, x["vin"]) for x in list["response"]]