Skip to content

Commit 144d1b4

Browse files
author
firstmate crewmate
committed
feat(vehicle): add format_usb and delete_dashcam_clips signed commands
Wraps the two remaining destructive VehicleAction fields with no confirmation guard, matching the existing erase_user_data() precedent: this library exposes the signed command as-is and leaves any confirmation UX to the caller.
1 parent 5563b13 commit 144d1b4

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

tesla_fleet_api/tesla/vehicle/commands.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@
180180
TeslaAuthResponseAction,
181181
SetupCloudProfileWithLocalProfileUuidAction,
182182
GetLocalProfilesForVaultUuidAction,
183+
DeleteDashcamClipsAction,
184+
FormatUSBAction,
183185
)
184186
from google.protobuf.timestamp_pb2 import Timestamp
185187
from tesla_protocol.command.vehicle_pb2 import (
@@ -2515,3 +2517,27 @@ async def get_local_profiles_for_vault_uuid(
25152517
),
25162518
mutating=False,
25172519
)
2520+
2521+
# No confirmation guard, matching the existing erase_user_data()
2522+
# precedent: this library exposes the signed command as-is and leaves
2523+
# any confirmation UX to the caller.
2524+
2525+
async def format_usb(self) -> dict[str, Any]:
2526+
"""Formats the USB drive connected to the vehicle, erasing all files on it. Irreversible."""
2527+
return await self._sendInfotainment(
2528+
Action(
2529+
vehicleAction=VehicleAction(
2530+
formatUsbAction=FormatUSBAction(format_usb=True)
2531+
)
2532+
)
2533+
)
2534+
2535+
async def delete_dashcam_clips(self) -> dict[str, Any]:
2536+
"""Deletes all dashcam clips stored on the vehicle. Irreversible."""
2537+
return await self._sendInfotainment(
2538+
Action(
2539+
vehicleAction=VehicleAction(
2540+
deleteDashcamClipsAction=DeleteDashcamClipsAction(delete_clips=True)
2541+
)
2542+
)
2543+
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Destructive data-clearing commands over the mocked BLE transport.
2+
3+
``format_usb``/``delete_dashcam_clips`` are unguarded no-confirmation
4+
wrappers, matching the existing ``erase_user_data()`` precedent
5+
(``tests/test_ble_mocked_commands.py`` has no dedicated test for that one
6+
either - it is exercised indirectly via the cross-transport suite).
7+
"""
8+
9+
from tesla_protocol.command.car_server_pb2 import Action
10+
from tesla_protocol.command.universal_message_pb2 import Domain
11+
12+
from ble_mocked_transport import (
13+
MockedBleTransportTestCase,
14+
decrypt_sent_command,
15+
infotainment_action_ok_reply,
16+
)
17+
18+
19+
def _decode_vehicle_action(vehicle, sent_msg):
20+
plaintext = decrypt_sent_command(vehicle, sent_msg)
21+
action = Action.FromString(plaintext)
22+
assert sent_msg.to_destination.domain == Domain.DOMAIN_INFOTAINMENT
23+
return action.vehicleAction
24+
25+
26+
class FormatUsbTests(MockedBleTransportTestCase):
27+
async def test_sends_format_usb_true(self) -> None:
28+
vehicle, send = self.make_vehicle()
29+
send.return_value = infotainment_action_ok_reply()
30+
31+
result = await vehicle.format_usb()
32+
33+
self.assertEqual(result, {"response": {"result": True, "reason": ""}})
34+
vehicle_action = _decode_vehicle_action(vehicle, send.await_args.args[0])
35+
self.assertTrue(vehicle_action.formatUsbAction.format_usb)
36+
37+
38+
class DeleteDashcamClipsTests(MockedBleTransportTestCase):
39+
async def test_sends_delete_clips_true(self) -> None:
40+
vehicle, send = self.make_vehicle()
41+
send.return_value = infotainment_action_ok_reply()
42+
43+
result = await vehicle.delete_dashcam_clips()
44+
45+
self.assertEqual(result, {"response": {"result": True, "reason": ""}})
46+
vehicle_action = _decode_vehicle_action(vehicle, send.await_args.args[0])
47+
self.assertTrue(vehicle_action.deleteDashcamClipsAction.delete_clips)

0 commit comments

Comments
 (0)