feat(vehicle): add low power mode and keep accessory power signed commands - #42
Merged
Conversation
…mands (fixes #31) Add public set_low_power_mode() and set_keep_accessory_power_mode() toggles to the signed vehicle command class (Commands), so callers no longer need to reach a private method with hand-built protobuf bytes. These commands are only available via the Tesla Vehicle Command Protocol (signed protobuf), not the REST API. The vendored car_server.proto lacked the SetLowPowerModeAction (VehicleAction field 130) and SetKeepAccessoryPowerModeAction (field 138) messages, so the .proto was updated from upstream and the gencode regenerated with protoc v32.0 (stamped 6.32.0 for Home Assistant compatibility). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Implement issue #31: add public low-power-mode and keep-accessory-power-on signed vehicle commands to tesla_fleet_api. Previously users had to reach a private _command() method with hand-built protobuf bytes (see jeffborg/tesla-fleet-extra). I added two public toggles, set_low_power_mode(on: bool) and set_keep_accessory_power_mode(on: bool), on the Commands class (the signed/BLE vehicle command layer). These are signed-only commands (Tesla Vehicle Command Protocol), NOT available via REST, so they were deliberately added only to Commands and not to VehicleFleet/Teslemetry/Tessie REST classes. The vendored car_server.proto lacked the required message types, so I surgically added SetLowPowerModeAction (VehicleAction oneof field 130, bool low_power_mode=1) and SetKeepAccessoryPowerModeAction (field 138, bool keep_accessory_power_mode=1) matching upstream teslamotors/vehicle-command exactly, then regenerated the gencode with protoc v32.0 so it stays stamped protobuf 6.32.0 for Home Assistant compatibility (per the repo's documented pin). The large line-count diff in car_server_pb2.py is expected regen noise: one updated serialized-descriptor line plus shifted _serialized_start/end offsets. Added tests/test_power_mode_commands.py with 4 tests covering on/off for both commands, including wire-format byte assertions that pin compatibility with the raw protobuf encoding downstream users relied on. Full pytest, pyright strict, and ruff all pass.
What Changed
set_low_power_mode(on: bool)andset_keep_accessory_power_mode(on: bool), to theCommandsclass (the signed/BLE command layer); they are intentionally not exposed on the REST-basedVehicleFleet/Teslemetry/Tessie classes since Tesla only supports them via the Vehicle Command Protocol.SetLowPowerModeAction(VehicleAction oneof field 130) andSetKeepAccessoryPowerModeAction(field 138) messages intocar_server.protomatching upstreamteslamotors/vehicle-command, and regenerated the gencode with protoc v32.0 to keep it stamped at protobuf 6.32.0 for Home Assistant compatibility (the largecar_server_pb2.pydiff is regen noise from the updated descriptor and shifted offsets).tests/test_power_mode_commands.pywith on/off coverage plus wire-format byte assertions for both commands, and documented the two commands indocs/fleet_api_signed_commands.md.Risk Assessment
✅ Low: Small, well-bounded additive change: two new signed-only commands with field numbers and message definitions verified against upstream teslamotors/vehicle-command, correct wire-format tests, and consistent protobuf regeneration following the existing established pattern.
Testing
Ran the new targeted tests (4 passed) and the full suite (45 passed, 8 subtests) to confirm the protobuf regeneration didn't regress other command paths, then produced product-level evidence by exercising both new public methods end-to-end through the signed Commands infotainment path and capturing the actual protobuf Action bytes placed on the wire. The demo shows the oneof fields resolve to numbers 130/138 (matching upstream teslamotors/vehicle-command) and that the emitted bytes are byte-for-byte identical to the raw protobuf encoding downstream users previously hand-built — directly demonstrating issue #31 is satisfied. No UI surface is involved (this is a Python library command API), so a CLI transcript is the appropriate end-user artifact. Transient build artifact (egg-info SOURCES.txt) was reverted, leaving the working tree clean.
Evidence: Power-mode signed command end-to-end demo (wire bytes + field numbers)
await vehicle.set_low_power_mode(True) -> oneof set: vehicleAction.setLowPowerModeAction (field 130) -> raw signed-command wire bytes: 12 05 92 08 02 08 01 await vehicle.set_keep_accessory_power_mode(True) -> oneof set: vehicleAction.setKeepAccessoryPowerModeAction (field 138) -> raw signed-command wire bytes: 12 05 d2 08 02 08 01 Wire-format compatibility vs raw protobuf (pre-#31 hand-encoded bytes): low_power_mode=true -> 12 05 92 08 02 08 01 -> OK keep_accessory_power_mode=true -> 12 05 d2 08 02 08 01 -> OKPipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
uv run pytest tests/test_power_mode_commands.py -v— 4 tests (on/off for both commands + wire-byte assertions) passuv run pytest tests -q— full suite, 45 passed + 8 subtests, confirms car_server_pb2 regen broke nothingEnd-to-end demo drivingset_low_power_mode(True/False)andset_keep_accessory_power_mode(True/False)through the signed Commands path with a captured_sendInfotainment, printing oneof field numbers (130/138) and raw protobuf Action bytesWire-format equality check:low_power_mode=true->12 05 92 08 02 08 01,keep_accessory_power_mode=true->12 05 d2 08 02 08 01, both OK vs the pre-#31 hand-encoded bytes✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.