Skip to content

Decode the trip target's SoC and minutes from their own fields - #234

Draft
jrgutier wants to merge 2 commits into
bretterer:mainfrom
jrgutier:up/trip-target-fields
Draft

jrgutier wants to merge 2 commits into
bretterer:mainfrom
jrgutier:up/trip-target-fields

Conversation

@jrgutier

@jrgutier jrgutier commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

charging.session.trip_target is decoded with the wrong field layout. The schema has one
field, soc_limit = 2. The app's message for this topic (d5l, dispatched from
c97.java:581 in app 3.16.0) has three:

# app field what it is
1 soc target state of charge, percent
2 time_estimate minutes until that SoC is reached
3 status enum, values not recoverable from the app

The app stores #1 and #2 unchanged as chargingTripTargetSoc and
chargingTripTargetMinsRemaining (qp2.java:130-131), the same names as the two gateway
fields in schemas/gateway.graphql. So today the decoder reports the minutes as the SoC
and never reads the SoC at all.

The same bytes, an 80% target with 45 minutes to go (08 50 10 2d 18 01):

result
before {"chargingTripTargetSoc": 45}
after {"chargingTripTargetSoc": 80, "chargingTripTargetMinsRemaining": 45, "_chargingTripTargetStatus": 1}

The one frame we have captured from a vehicle is 10 ff ff 03: #2 = 0xFFFF and no #1. The
current comment, "0xFFFF when not set", comes from frames like this one, and the
decoder gives None for it before and after this change. The 0xFFFF belongs to the minutes,
though, not to the SoC.

Changes

  • charging.proto: TripTarget gets soc = 1, time_estimate = 2 and status = 3
    (int32, enum type unknown). Regenerated charging_pb2.py/.pyi. No other module changed.
  • decode_trip_target:
    • chargingTripTargetSoc keeps its key. It is set only when GraphQL Endpoints #1 is 1-100, the same check
      the app makes before it shows a trip target on any screen (np4.java:81,
      y13.java:397, j23.java:1146). Otherwise it is None, as before.
    • New chargingTripTargetMinsRemaining (minutes), with the gateway's name. It is set only
      when there is a target and the value is 1 to 0xFFFE. Otherwise it is None: Add CI to run tests #2 absent
      or 0 (the app hides the minutes when they are <= 0), or 0xFFFF.
    • _chargingTripTargetStatus is the raw value, following _unexpectedStopReason.
    • Fields section of the docstring updated.
  • tests/parallax/test_charging.py: the 80%/45 min case, with a check that it
    serializes to 0850102d1801, so the field numbers are pinned; the 0xFFFF minutes case; an
    80% target with Add CI to run tests #2 absent (08 50), which gives None minutes rather than 0; no target at
    SoC 0 and 101; and the captured 10ffff03 frame.

Testing

PYTHONPATH=src pytest -q -p no:cacheprovider && ruff check . && ruff format --check . && mypy src/rivian

236 passed (232 before, plus 4 new; test_trip_target was rewritten). Ruff and mypy are
clean.

Notes

  • The field numbers come from the app's schema. No captured frame has a trip target
    set yet. The only capture is the "no target" frame above. We will check one live frame with a
    target set before marking this ready.
  • 0xFFFF minutes becomes None because the captured frame sends it. The app itself never
    tests for 0xFFFF. It only hides the indicator when the SoC is outside 1-100, and the
    minutes when they are <= 0, which the decoder follows by reporting None there too, so
    a consumer shows unknown instead of "0 min".
  • status (Fixes error in publish #3) has no accessor in any of the 54 app versions we checked, so it stays raw.

charging.session.trip_target read field 2 as the target SoC. In the
app's message (d5l) field 1 is the SoC, field 2 the minutes until it is
reached and field 3 a status, so a target of 80% with 45 minutes to go
was reported as 45%. Read all three, emitting the minutes as
chargingTripTargetMinsRemaining, the name GraphQL already uses.
A frame with a target but no time estimate (#2 absent or 0) decoded as 0 minutes, which a consumer shows as "0 min". The app hides the minutes when they are <= 0, so report None for them, as for 0xFFFF.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant