fix(vehicle): standardize auto seat climate on 1-indexed AutoSeat (fixes #11)#41
Merged
Conversation
The auto-seat-climate command is 1-indexed on Tesla's wire (FrontLeft=1, FrontRight=2), but the two backends disagreed with each other and with the 0-indexed `Seat` enum, so `Seat.FRONT_LEFT`=0 was rejected and `Seat.FRONT_RIGHT`=1 controlled the front-left seat. Both backends now standardize on the 1-indexed `AutoSeat` enum (FL=1, FR=2), matching the REST wire values and the proto `AutoSeatPosition_*` enum: - fleet.py: type hint `int | Seat` -> `int | AutoSeat` (behavior unchanged; the Fleet REST path already forwarded the value verbatim to the 1-indexed endpoint). - commands.py: the signed/protobuf path now maps the 1-indexed int directly onto the proto enum instead of indexing a 0-based tuple, so `AutoSeat.FRONT_RIGHT`=2 no longer raises IndexError. Type hint updated to `int | AutoSeat`. `AutoSeat` sits alongside `Seat` in const.py, so consumers can import it from the same module. BEHAVIOR CHANGE (signed path): the expected `auto_seat_position` index moves from 0-based to 1-based. A direct caller of the signed `remote_auto_seat_climate_request` must now pass 1-indexed values. Regression tests cover both backends for front-left and front-right. The manual seat-heater/cooler paths and the 0-indexed `Seat` enum are unchanged. Downstream follow-up (out of scope here): the Home Assistant `tesla_fleet` integration must pass 1-indexed `AutoSeat` values to fully close the reported end-user symptom. 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
Fix issue #11: the auto-seat-climate command (remote_auto_seat_climate_request) is 1-indexed on Tesla's wire (AutoSeatPosition_FrontLeft=1, FrontRight=2), but the library's two backends disagreed with each other and with the 0-indexed Seat enum, so Seat.FRONT_LEFT=0 was rejected and Seat.FRONT_RIGHT=1 controlled the front-left seat. DECISION (made by the maintainer, do not re-litigate): standardize BOTH backends on the 1-indexed AutoSeat enum (FL=1, FR=2), which already matches the REST wire values and the proto AutoSeatPosition_* enum. Changes: (1) fleet.py REST path — change type hint 'int | Seat' to 'int | AutoSeat' and import AutoSeat; this is a correctness/clarity change with NO behavior change since the REST path already forwarded the value verbatim to the 1-indexed endpoint. (2) commands.py signed/protobuf path — map the 1-indexed int directly onto the proto enum (via typing.cast for pyright strict; protobuf accepts the raw int at runtime) INSTEAD of indexing the removed 0-based AutoSeatClimatePositions tuple, so AutoSeat.FRONT_RIGHT=2 no longer raises IndexError; type hint updated to 'int | AutoSeat'. This is a DELIBERATE behavior change on the signed path: its expected index moves 0->1, so a direct caller of the signed method must now pass 1-indexed values — this is intended and called out in the commit body. (3) AutoSeat already sits alongside Seat in const.py so it is importable from the same module. (4) Added regression tests (tests/test_auto_seat_climate.py) asserting the Fleet JSON body carries auto_seat_position=1/2 and the signed builder emits AutoSeatPosition_FrontLeft/FrontRight for the same 1-indexed input. The manual seat-heater/cooler paths and the 0-indexed Seat enum are intentionally left unchanged (they are correct). Also recorded the dual seat-indexing gotcha in AGENTS.md. Out of scope but noted for the maintainer: the Home Assistant tesla_fleet integration must also pass 1-indexed AutoSeat values to fully close the end-user symptom; HA is not touched here.
What Changed
remote_auto_seat_climate_requestnow standardizes both backends on the 1-indexedAutoSeatenum (FRONT_LEFT=1, FRONT_RIGHT=2), matching Tesla's REST wire values and the protoAutoSeatPosition_*enum; the REST path infleet.pygains theint | AutoSeattype hint andAutoSeatimport (value already forwarded verbatim, no behavior change).commands.pynow casts the 1-indexed int directly onto the proto enum instead of indexing the removed 0-basedAutoSeatClimatePositionstuple, soAutoSeat.FRONT_RIGHT=2no longer raisesIndexError— a deliberate index shift (0→1) for direct callers of the signed method.tests/test_auto_seat_climate.py) asserting the Fleet JSON carriesauto_seat_position=1/2and the signed builder emitsAutoSeatPosition_FrontLeft/FrontRightfor the same input, and documented the dual seat-indexing gotcha inAGENTS.md.Risk Assessment
✅ Low: A tightly-bounded correctness fix that standardizes both backends on the 1-indexed AutoSeat convention matching the proto enum and REST wire values, with matching regression tests and no other affected call sites.
Testing
Baseline
uv syncplusuv run pytest tests(41 passed, 8 subtests) confirm no regressions from the signature/import changes; the newtests/test_auto_seat_climate.py(4 tests) passes and asserts both backends agree on 1-indexed values. Since this is a library (no UI surface), the end-user-experience evidence is a runnable demo capturing the real command payloads: the Fleet REST path forwards auto_seat_position 1/2 verbatim and the signed path maps them onto AutoSeatPosition_FrontLeft/FrontRight, while a reproduction of the removed 0-indexed tuple lookup shows the old bug (IndexError for FRONT_RIGHT=2, and FRONT_LEFT=1 wrongly emitting FrontRight) that the fix eliminates. No visual artifact applies because there is no rendered UI. Transient egg-info change from the editable install was reverted; worktree is clean.Evidence: Auto-seat-climate end-to-end demo (payloads + old-vs-new behavior)
### Caller: remote_auto_seat_climate_request(1, True) [Fleet REST] POST body -> {'auto_seat_position': <AutoSeat.FRONT_LEFT: 1>, 'auto_climate_on': True} [Signed/proto] seat_position -> 1 (AutoSeatPosition_FrontLeft) ### Caller: remote_auto_seat_climate_request(2, True) [Fleet REST] POST body -> {'auto_seat_position': <AutoSeat.FRONT_RIGHT: 2>, 'auto_climate_on': True} [Signed/proto] seat_position -> 2 (AutoSeatPosition_FrontRight) ### Regression: OLD signed-path bug OLD with AutoSeat.FRONT_RIGHT(=2): IndexError: tuple index out of range OLD with AutoSeat.FRONT_LEFT(=1): emitted AutoSeatPosition_FrontRight (wrong seat!) FIX confirmed: new code emits the correct seat for both, no IndexError.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
tesla_fleet_api/tesla/vehicle/commands.py:1012- The signed path previously validated the seat index implicitly: AutoSeatClimatePositions[auto_seat_position] raised IndexError for out-of-range values. The newcast(...)forwards any int verbatim to the proto enum, so an out-of-range value (e.g. old 0-indexed callers passing 0) now silently serializes as AutoSeatPosition_Unknown (proto value 0) instead of failing fast. This matches the REST path (which also never validated) and is consistent with the deliberate 1-indexed standardization, so it's an acceptable tradeoff — noted only for awareness.✅ **Test** - passed
✅ No issues found.
uv run pytest tests/test_auto_seat_climate.py -v— 4 regression tests (Fleet JSON carries auto_seat_position=1/2; signed builder emits AutoSeatPosition_FrontLeft/FrontRight for same 1-indexed input)uv run pytest tests -q— full suite, 41 passed + 8 subtestsuv run python demo_auto_seat_climate.py— end-to-end demo printing the Fleet REST POST body and signed proto seat_position for FRONT_LEFT/FRONT_RIGHT, plus reproduction of the old 0-indexed-tuple bug (IndexError at index 2, wrong-seat at index 1)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.