rivian-python-client 2.3.0__py3-none-any.whl → 2.4.0__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.
rivian/__version__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '2.3.0'
4
+ __version__ = VERSION = '2.4.0'
rivian/ble.py CHANGED
@@ -7,7 +7,7 @@ import logging
7
7
  import platform
8
8
  import secrets
9
9
 
10
- from .utils import generate_ble_command_hmac
10
+ from .utils import generate_command_hmac
11
11
 
12
12
  _LOGGER = logging.getLogger(__name__)
13
13
 
@@ -96,7 +96,7 @@ async def pair_phone(
96
96
 
97
97
  _LOGGER.debug("Exchanging nonce")
98
98
  phone_nonce = secrets.token_bytes(16)
99
- hmac = generate_ble_command_hmac(phone_nonce, vehicle_key, private_key)
99
+ hmac = generate_command_hmac(phone_nonce, vehicle_key, private_key)
100
100
  await client.write_gatt_char(
101
101
  PHONE_NONCE_VEHICLE_NONCE_UUID, phone_nonce + hmac
102
102
  )
rivian/const.py CHANGED
@@ -185,8 +185,8 @@ class VehicleCommand(StrEnum):
185
185
  VEHICLE_CABIN_PRECONDITION_DISABLE = "VEHICLE_CABIN_PRECONDITION_DISABLE"
186
186
  VEHICLE_CABIN_PRECONDITION_ENABLE = "VEHICLE_CABIN_PRECONDITION_ENABLE"
187
187
  # Gen2 HVAC Controls
188
- CABIN_HVAC_THIRD_ROW_LEFT_SEAT_HEAT = "CABIN_HVAC_THIRD_ROW_LEFT_SEAT_HEAT"
189
- CABIN_HVAC_THIRD_ROW_RIGHT_SEAT_HEAT = "CABIN_HVAC_THIRD_ROW_RIGHT_SEAT_HEAT"
188
+ CABIN_HVAC_3RD_ROW_REAR_LEFT_SEAT_HEAT = "CABIN_HVAC_3RD_ROW_REAR_LEFT_SEAT_HEAT"
189
+ CABIN_HVAC_3RD_ROW_REAR_RIGHT_SEAT_HEAT = "CABIN_HVAC_3RD_ROW_REAR_RIGHT_SEAT_HEAT"
190
190
 
191
191
  # Closures
192
192
  LOCK_ALL_CLOSURES_FEEDBACK = "LOCK_ALL_CLOSURES_FEEDBACK"
@@ -10,10 +10,18 @@ Public API:
10
10
  encode_vehicle_operation(rvm, payload=b"", ...) -> str
11
11
  Builds a `send_vehicle_operation` request; an empty payload reads
12
12
  the RVM, anything else (e.g. `encode_climate_hold_setting`) writes it.
13
+ encode_command(vehicle_id, rvm, payload, ...) -> str
14
+ Builds and signs a `send_parallax_command` request, with a payload
15
+ such as `encode_unlock()`.
16
+ LOCK_RVM / encode_lock(), UNLOCK_RVM / encode_unlock()
17
+ The RVM and payload of a signed lock or unlock command.
18
+ decode_command_state_message(data) -> dict | None
19
+ Reads a raw `subscribe_for_parallax_command_state` message.
13
20
 
14
21
  Layout:
15
- core.py - registry, payload parsing and shared helpers
16
- proto/ - .proto schemas and their generated *_pb2 modules
22
+ core.py - registry, payload parsing and shared helpers
23
+ command.py - signed remote commands and their state messages
24
+ proto/ - .proto schemas and their generated *_pb2 modules
17
25
  <topic prefix>.py - one module per RVM topic prefix (body.*, etc.)
18
26
 
19
27
  To add a decoder, decorate it with
@@ -44,11 +52,13 @@ from . import ( # noqa: F401 (imported to register their decoders)
44
52
  vehicle,
45
53
  vehicle_access,
46
54
  )
55
+ from .body import LOCK_RVM, UNLOCK_RVM, encode_lock, encode_unlock
47
56
  from .comfort import (
48
57
  CLIMATE_HOLD_SETTING_RVM,
49
58
  CLIMATE_HOLD_STATUS_RVM,
50
59
  encode_climate_hold_setting,
51
60
  )
61
+ from .command import decode_command_state_message, encode_command
52
62
  from .core import (
53
63
  RVMDecoder,
54
64
  decode_parallax_message,
@@ -75,9 +85,15 @@ __all__ = [
75
85
  "CHARGING_RVMS",
76
86
  "CLIMATE_HOLD_SETTING_RVM",
77
87
  "CLIMATE_HOLD_STATUS_RVM",
88
+ "LOCK_RVM",
78
89
  "PARALLAX_RVMS",
90
+ "UNLOCK_RVM",
91
+ "decode_command_state_message",
79
92
  "decode_parallax_message",
80
93
  "decode_parallax_subscription_message",
81
94
  "encode_climate_hold_setting",
95
+ "encode_command",
96
+ "encode_lock",
97
+ "encode_unlock",
82
98
  "encode_vehicle_operation",
83
99
  ]
rivian/parallax/body.py CHANGED
@@ -7,6 +7,9 @@ from typing import Any, Final
7
7
  from .core import _LOGGER, RVMDecoder, _enum, _present
8
8
  from .proto import body_pb2
9
9
 
10
+ LOCK_RVM: Final = "body.locks.lock"
11
+ UNLOCK_RVM: Final = "body.locks.unlock"
12
+
10
13
  _CLOSURE_MAP: Final[dict[int, str]] = {
11
14
  body_pb2.DOOR_FRONT_LEFT: "doorFrontLeftClosed",
12
15
  body_pb2.DOOR_FRONT_RIGHT: "doorFrontRightClosed",
@@ -173,6 +176,16 @@ def decode_closures(m: body_pb2.ClosuresState) -> dict[str, Any]:
173
176
  return result
174
177
 
175
178
 
179
+ def encode_lock() -> bytes:
180
+ """Encode a body.locks.lock payload, which has no fields."""
181
+ return body_pb2.LockCommand().SerializeToString()
182
+
183
+
184
+ def encode_unlock() -> bytes:
185
+ """Encode a body.locks.unlock payload that unlocks everything."""
186
+ return body_pb2.UnlockCommand(all=True).SerializeToString()
187
+
188
+
176
189
  @RVMDecoder.register("body.locks.states", body_pb2.LocksState)
177
190
  def decode_locks(m: body_pb2.LocksState) -> dict[str, Any]:
178
191
  """body.locks.states — lock state of every lock.
@@ -0,0 +1,168 @@
1
+ """Encoder and decoder for signed Parallax remote commands.
2
+
3
+ A command such as `body.locks.unlock` is sent with the `sendParallaxPayload`
4
+ mutation (`Rivian.send_parallax_command`). Its payload is an `Operation` in an
5
+ `Envelope`, signed with the secret that `Rivian.send_vehicle_command` derives from
6
+ the phone's key and the vehicle's, but over the operation's bytes. In testing,
7
+ Rivian woke a sleeping vehicle for it.
8
+
9
+ The `vehicleCommandStatePx` subscription
10
+ (`Rivian.subscribe_for_parallax_command_state`) reports on the command as it
11
+ goes: the vehicle waking up, validating and executing it, then the result.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import base64
17
+ import time
18
+ import uuid
19
+ from typing import Any, Final
20
+
21
+ from google.protobuf.message import DecodeError
22
+
23
+ from ..utils import generate_command_hmac
24
+ from .core import _LOGGER, _debug_message, _enum, _present
25
+ from .proto import command_pb2
26
+
27
+ _PROGRESS_MAP: Final[dict[int, str]] = {
28
+ command_pb2.VEHICLE_MODEL_OP_PROGRESS_UNSPECIFIED: "unspecified",
29
+ command_pb2.VEHICLE_MODEL_OP_PROGRESS_VEHICLE_WAKING_UP: "waking_up",
30
+ command_pb2.VEHICLE_MODEL_OP_PROGRESS_VEHICLE_VALIDATING: "validating",
31
+ command_pb2.VEHICLE_MODEL_OP_PROGRESS_VEHICLE_EXECUTING: "executing",
32
+ command_pb2.VEHICLE_MODEL_OP_PROGRESS_VEHICLE_COMPLETE: "complete",
33
+ }
34
+
35
+ _STATUS_MAP: Final[dict[int, str]] = {
36
+ command_pb2.RESPONSE_STATUS_UNDEFINED: "undefined",
37
+ command_pb2.RESPONSE_STATUS_SUCCESS: "success",
38
+ command_pb2.RESPONSE_STATUS_FAIL: "failed",
39
+ command_pb2.RESPONSE_STATUS_INVALID_REQUEST: "invalid_request",
40
+ command_pb2.RESPONSE_STATUS_NOT_SUPPORTED: "not_supported",
41
+ command_pb2.RESPONSE_STATUS_TIMEOUT: "timeout",
42
+ }
43
+
44
+
45
+ def encode_command(
46
+ vehicle_id: str,
47
+ rvm: str,
48
+ payload: bytes,
49
+ *,
50
+ identity_id: str,
51
+ vehicle_key: str,
52
+ private_key: str,
53
+ command_id: str | None = None,
54
+ timestamp: float | None = None,
55
+ ) -> str:
56
+ """Encode and sign a command, as the payload of `sendParallaxPayload`.
57
+
58
+ `payload` is the RVM's message, e.g. `encode_unlock()` for `UNLOCK_RVM`;
59
+ nothing checks that they go together. `identity_id`, `vehicle_key` and
60
+ `private_key` are the ones `send_vehicle_command` takes. The command id, a
61
+ UUID, is a new one unless `command_id` is given (`ValueError` if it isn't
62
+ one); `timestamp` is epoch milliseconds, now unless given.
63
+
64
+ The result is signed and can be replayed until the vehicle rejects its
65
+ timestamp, so treat it as a secret.
66
+ """
67
+ command_id_bytes = (
68
+ uuid.uuid4().bytes if command_id is None else uuid.UUID(command_id).bytes
69
+ )
70
+ timestamp_ms = int(time.time() * 1000 if timestamp is None else timestamp)
71
+ stamp = command_pb2.Timestamp(
72
+ seconds=timestamp_ms // 1000, nanos=timestamp_ms % 1000 * 1_000_000
73
+ )
74
+ operation = command_pb2.Operation(
75
+ rvm=rvm,
76
+ type=command_pb2.PARALLAX_OPERATION_REQUEST,
77
+ command_id=command_id_bytes,
78
+ payload=payload,
79
+ created_at=stamp,
80
+ vehicle_id=vehicle_id,
81
+ ).SerializeToString()
82
+ envelope = command_pb2.Envelope(
83
+ composite=command_pb2.Composite(bytes_val=operation),
84
+ last_update=stamp,
85
+ correlation_id=command_id_bytes,
86
+ security_info=command_pb2.SecurityInfo(
87
+ signature=command_pb2.Signature(
88
+ type=command_pb2.DATA_SIGNATURE_TYPE_HMAC_SHA256,
89
+ # The raw HMAC-SHA256 of the data, as BLE commands use too
90
+ value=generate_command_hmac(operation, vehicle_key, private_key),
91
+ ),
92
+ mapped_identity=identity_id,
93
+ ),
94
+ )
95
+ return base64.b64encode(envelope.SerializeToString()).decode("utf-8")
96
+
97
+
98
+ def decode_command_state(payload: str) -> dict[str, Any] | None:
99
+ """Decode the payload of a `vehicleCommandStatePx` message.
100
+
101
+ Returns None if the payload is empty or can't be read.
102
+
103
+ Fields:
104
+ commandId: str | None — the command's UUID
105
+ rvm: str
106
+ progress: str | int — "unspecified" | "waking_up" | "validating" |
107
+ "executing" | "complete". Any of the ones before "complete" can be
108
+ skipped, and "waking_up" has come more than once for one command.
109
+ status: str | int | None — how the vehicle answered ("undefined" |
110
+ "success" | "failed" | "invalid_request" | "not_supported" |
111
+ "timeout"); None if the message has no result
112
+ error: dict | None — {"code": int, "message": str}, from the result or,
113
+ if the whole operation failed, from the operation error (which has
114
+ no status)
115
+
116
+ A value this library doesn't know comes back as the number it was sent as.
117
+
118
+ The vehicle has done the command when the progress is "complete", the status
119
+ "success" and there is no error. "failed", "invalid_request" and
120
+ "not_supported" mean it has not. With "timeout" or "undefined", or if no
121
+ "complete" message comes at all, it isn't known, and the vehicle may do it
122
+ later.
123
+ """
124
+ try:
125
+ data = base64.b64decode(payload)
126
+ message = command_pb2.CommandState.FromString(data)
127
+ except (TypeError, ValueError, DecodeError):
128
+ _LOGGER.debug("Failed to decode command state", exc_info=True)
129
+ return None
130
+ if not data:
131
+ return None
132
+ _debug_message("command state", message)
133
+
134
+ status: str | int | None = None
135
+ error: dict[str, Any] | None = None
136
+ if (result := _present(message, "data")) is not None:
137
+ status = _enum(_STATUS_MAP, result.response_status, what="command status")
138
+ if (result_error := _present(result, "error")) is not None:
139
+ error = {"code": result_error.code, "message": result_error.message}
140
+ elif (operation_error := _present(message, "operation_error")) is not None:
141
+ error = {"code": operation_error.error, "message": operation_error.message}
142
+ return {
143
+ "commandId": (
144
+ str(uuid.UUID(bytes=message.command_id))
145
+ if len(message.command_id) == 16
146
+ else None
147
+ ),
148
+ "rvm": message.rvm,
149
+ "progress": _enum(_PROGRESS_MAP, message.progress, what="command progress"),
150
+ "status": status,
151
+ "error": error,
152
+ }
153
+
154
+
155
+ def decode_command_state_message(data: dict[str, Any]) -> dict[str, Any] | None:
156
+ """Decode a raw `subscribe_for_parallax_command_state` message.
157
+
158
+ Unwraps `payload.data.vehicleCommandStatePx.payload` for
159
+ `decode_command_state`; returns None if it's missing or can't be read. That
160
+ includes a message that carries GraphQL errors (`data["payload"]["errors"]`)
161
+ instead of a state.
162
+ """
163
+ payload: Any = data
164
+ for key in ("payload", "data", "vehicleCommandStatePx", "payload"):
165
+ if not isinstance(payload, dict):
166
+ return None
167
+ payload = payload.get(key)
168
+ return decode_command_state(payload)
rivian/parallax/core.py CHANGED
@@ -76,6 +76,16 @@ def _describe_unknowns(message: Message, path: str = "") -> list[str]:
76
76
  return found
77
77
 
78
78
 
79
+ def _debug_message(label: str, message: Message) -> None:
80
+ """Debug-log a parsed `message` and anything its schema doesn't define."""
81
+ if _LOGGER.isEnabledFor(logging.DEBUG):
82
+ _LOGGER.debug(
83
+ "%s: %s", label, text_format.MessageToString(message, as_one_line=True)
84
+ )
85
+ for unknown in _describe_unknowns(message):
86
+ _LOGGER.debug("%s: %s", label, unknown)
87
+
88
+
79
89
  class RVMDecoder:
80
90
  """Registry of RVM topic -> (message class, decoder).
81
91
 
@@ -124,12 +134,7 @@ def _decode_rvm_payload(payload: str | None, rvm: str) -> dict[str, Any]:
124
134
  except Exception:
125
135
  _LOGGER.debug("Failed to decode %s payload", rvm, exc_info=True)
126
136
  return {}
127
- if _LOGGER.isEnabledFor(logging.DEBUG):
128
- _LOGGER.debug(
129
- "%s: %s", rvm, text_format.MessageToString(message, as_one_line=True)
130
- )
131
- for unknown in _describe_unknowns(message):
132
- _LOGGER.debug("%s: %s", rvm, unknown)
137
+ _debug_message(rvm, message)
133
138
  return result
134
139
 
135
140
 
@@ -53,11 +53,19 @@ def _decode_schedule(schedule: _Schedules.Schedule) -> dict[str, Any]:
53
53
  entry["name"] = v
54
54
  entry["isEnabled"] = schedule.is_enabled
55
55
 
56
- occurrence = schedule.occurrence
57
- entry["occurrence"] = {
58
- "days": [day for field, day in _WEEKDAYS if getattr(occurrence.days, field)],
59
- "startsAtMin": occurrence.starts_at,
60
- }
56
+ if schedule.HasField("single_occurrence"):
57
+ starts_at = schedule.single_occurrence.starts_at
58
+ entry["occurrence"] = {
59
+ "startsAt": from_epoch(starts_at.seconds + starts_at.nanos / 1e9)
60
+ }
61
+ else:
62
+ occurrence = schedule.occurrence
63
+ entry["occurrence"] = {
64
+ "days": [
65
+ day for field, day in _WEEKDAYS if getattr(occurrence.days, field)
66
+ ],
67
+ "startsAtMin": occurrence.starts_at,
68
+ }
61
69
 
62
70
  settings = schedule.departure_settings
63
71
  comfort = settings.comfort_settings
@@ -87,7 +95,9 @@ def decode_departure_schedules(m: departure_pb2.DepartureSchedules) -> dict[str,
87
95
  departureSchedules: list[dict] — the gateway's DepartureSchedule shape:
88
96
  id: str, name: str, isEnabled: bool
89
97
  occurrence: {"days": list[str] ("monday" ... "sunday"; order
90
- inferred), "startsAtMin": int (minutes after local midnight)}
98
+ inferred), "startsAtMin": int (minutes after local midnight)},
99
+ or {"startsAt": datetime} for the one-off "s-" schedule a
100
+ departNow adds (departing 10 minutes after the call)
91
101
  departureSettings: {"shouldOverrideChargeSchedule": bool,
92
102
  "comfortSettings": {"cabinTempCelsius": float,
93
103
  "frontDefogDefrost": "off" | "defog" | "defrost",
@@ -310,7 +310,9 @@ def decode_trip_info(m: navigation_pb2.TripInfo) -> dict[str, Any]:
310
310
  and incidents ({firstIndex, lastIndex, type})
311
311
  overviewPolyline: str — Google-encoded, whole trip
312
312
  nextWaypointDepartureTime: datetime — the next stop's departure if
313
- it's a charging stop, else its arrival
313
+ it's a charging stop, else its arrival. It stops updating once
314
+ the first stop is reached, keeping that stop's time for the
315
+ rest of the trip; use waypoints[0] instead
314
316
  finalStateOfCharge, finalRangeRemaining: float — the last
315
317
  waypoint's (percent, meters)
316
318
  socIsBelowLimit: bool
@@ -346,9 +348,11 @@ def decode_trip_progress(m: navigation_pb2.TripProgress) -> dict[str, Any]:
346
348
  """navigation.navigation_service.trip_progress — live progress on the active trip.
347
349
 
348
350
  Fields:
349
- nextWaypointArrivalTime: datetime — live ETA
351
+ nextWaypointArrivalTime: datetime — live ETA, to the minute
350
352
  finalDestinationArrivalTime: datetime — live ETA for the last
351
- waypoint; missing for one message after the waypoints change
353
+ waypoint, to the minute; missing while the route is
354
+ recalculating and on the stale progress the vehicle keeps
355
+ resending after navigation ends
352
356
  nextStopIndex: int
353
357
  distanceRemaining, durationRemaining: float — to the next waypoint
354
358
  (meters, seconds)
@@ -266,3 +266,14 @@ enum WiperFluidState {
266
266
  WIPER_FLUID_STATE_LOW = 2;
267
267
  WIPER_FLUID_STATE_EMPTY = 3;
268
268
  }
269
+
270
+ // body.locks.unlock, the payload of a signed command (see ../command.py)
271
+ message UnlockCommand {
272
+ oneof target {
273
+ bool all = 1; // the app always sets this
274
+ bool user_preference = 2; // in the app's schema; its button never sends it
275
+ }
276
+ }
277
+
278
+ // body.locks.lock, the payload of a signed command. It has no fields.
279
+ message LockCommand {}
@@ -24,47 +24,47 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n rivian/parallax/proto/body.proto\x12\x14rivian.parallax.body\"\x89\x06\n\rClosuresState\x12<\n\x07\x63losure\x18\x01 \x03(\x0b\x32+.rivian.parallax.body.ClosuresState.Closure\x1a\xb9\x05\n\x07\x43losure\x12+\n\x02id\x18\x01 \x01(\x0e\x32\x1f.rivian.parallax.body.ClosureId\x12\x36\n\x05state\x18\x02 \x01(\x0e\x32\".rivian.parallax.body.ClosureStateH\x01\x88\x01\x01\x12\x1d\n\x15open_position_percent\x18\x03 \x01(\x05\x12\x31\n\x05\x66\x61ult\x18\x04 \x01(\x0e\x32\".rivian.parallax.body.ClosureFault\x12\x46\n\x13windows_next_action\x18\x05 \x01(\x0e\x32\'.rivian.parallax.body.WindowsNextActionH\x00\x12\x42\n\x11\x66runk_next_action\x18\x06 \x01(\x0e\x32%.rivian.parallax.body.FrunkNextActionH\x00\x12H\n\x14liftgate_next_action\x18\x07 \x01(\x0e\x32(.rivian.parallax.body.LiftgateNextActionH\x00\x12G\n\x14side_bin_next_action\x18\x08 \x01(\x0e\x32\'.rivian.parallax.body.SideBinNextActionH\x00\x12H\n\x14tailgate_next_action\x18\t \x01(\x0e\x32(.rivian.parallax.body.TailgateNextActionH\x00\x12V\n\x1c\x63harge_port_door_next_action\x18\n \x01(\x0e\x32..rivian.parallax.body.ChargePortDoorNextActionH\x00\x12\x1d\n\x13tonneau_next_action\x18\x0b \x01(\x05H\x00\x42\r\n\x0bnext_actionB\x08\n\x06_state\"\xe3\x01\n\nLocksState\x12\x33\n\x04lock\x18\x01 \x03(\x0b\x32%.rivian.parallax.body.LocksState.Lock\x1a\x9f\x01\n\x04Lock\x12(\n\x02id\x18\x01 \x01(\x0e\x32\x1c.rivian.parallax.body.LockId\x12\x33\n\x05state\x18\x02 \x01(\x0e\x32\x1f.rivian.parallax.body.LockStateH\x00\x88\x01\x01\x12.\n\x05\x66\x61ult\x18\x03 \x01(\x0e\x32\x1f.rivian.parallax.body.LockFaultB\x08\n\x06_state\"\xd1\x01\n\x0cWindowsState\x12\x39\n\x06window\x18\x01 \x03(\x0b\x32).rivian.parallax.body.WindowsState.Window\x1a\x85\x01\n\x06Window\x12\x36\n\x08instance\x18\x01 \x01(\x0e\x32$.rivian.parallax.body.WindowInstance\x12\x43\n\x12\x63\x61libration_status\x18\x02 \x01(\x0e\x32\'.rivian.parallax.body.CalibrationStatus\"\x9b\x01\n\x0cTrailerState\x12<\n\x08presence\x18\x01 \x01(\x0e\x32%.rivian.parallax.body.TrailerPresenceH\x00\x88\x01\x01\x12@\n\x11rear_hitch_status\x18\x02 \x01(\x0e\x32%.rivian.parallax.body.RearHitchStatusB\x0b\n\t_presence\"G\n\x0fWiperFluidLevel\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.rivian.parallax.body.WiperFluidState*\xe8\x02\n\tClosureId\x12\x1a\n\x16\x43LOSURE_ID_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x44OOR_FRONT_LEFT\x10\x01\x12\x14\n\x10\x44OOR_FRONT_RIGHT\x10\x02\x12\x12\n\x0e\x44OOR_REAR_LEFT\x10\x03\x12\x13\n\x0f\x44OOR_REAR_RIGHT\x10\x04\x12\t\n\x05\x46RUNK\x10\x05\x12\x0c\n\x08TAILGATE\x10\x06\x12\x0c\n\x08LIFTGATE\x10\x07\x12\x11\n\rSIDE_BIN_LEFT\x10\x08\x12\x12\n\x0eSIDE_BIN_RIGHT\x10\t\x12\x0f\n\x0b\x43HARGE_PORT\x10\n\x12\x0b\n\x07TONNEAU\x10\x0b\x12\x15\n\x11WINDOW_FRONT_LEFT\x10\x0c\x12\x16\n\x12WINDOW_FRONT_RIGHT\x10\r\x12\x14\n\x10WINDOW_REAR_LEFT\x10\x0e\x12\x15\n\x11WINDOW_REAR_RIGHT\x10\x0f\x12\x0f\n\x0bWINDOW_REAR\x10\x10\x12\x12\n\rGROUP_WINDOWS\x10\x90N*\xad\x01\n\x0c\x43losureState\x12\x1d\n\x19\x43LOSURE_STATE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LOSURE_STATE_OPEN\x10\x01\x12\x18\n\x14\x43LOSURE_STATE_CLOSED\x10\x02\x12\x16\n\x12\x43LOSURE_STATE_AJAR\x10\x03\x12\x19\n\x15\x43LOSURE_STATE_OPENING\x10\x04\x12\x19\n\x15\x43LOSURE_STATE_CLOSING\x10\x05*\xf3\x02\n\x06LockId\x12\x17\n\x13LOCK_ID_UNSPECIFIED\x10\x00\x12\x18\n\x14LOCK_DOOR_FRONT_LEFT\x10\x01\x12\x19\n\x15LOCK_DOOR_FRONT_RIGHT\x10\x02\x12\x17\n\x13LOCK_DOOR_REAR_LEFT\x10\x03\x12\x18\n\x14LOCK_DOOR_REAR_RIGHT\x10\x04\x12\x0e\n\nLOCK_FRUNK\x10\x05\x12\x11\n\rLOCK_TAILGATE\x10\x06\x12\x11\n\rLOCK_LIFTGATE\x10\x07\x12\x16\n\x12LOCK_SIDE_BIN_LEFT\x10\x08\x12\x17\n\x13LOCK_SIDE_BIN_RIGHT\x10\t\x12\x14\n\x10LOCK_CHARGE_PORT\x10\n\x12\x17\n\x13LOCK_TRUNK_SECURITY\x10\x0b\x12\x17\n\x13LOCK_CENTER_CONSOLE\x10\x0c\x12\x12\n\x0eLOCK_GLOVE_BOX\x10\r\x12\x13\n\x0fLOCK_GEAR_GUARD\x10\x0e\x12\x10\n\x0cLOCK_TONNEAU\x10\x0f*z\n\tLockState\x12\x1a\n\x16LOCK_STATE_UNSPECIFIED\x10\x00\x12\x15\n\x11LOCK_STATE_LOCKED\x10\x01\x12\x17\n\x13LOCK_STATE_UNLOCKED\x10\x02\x12!\n\x1dLOCK_STATE_PARTIALLY_UNLOCKED\x10\x03*?\n\tLockFault\x12\x1a\n\x16LOCK_FAULT_UNSPECIFIED\x10\x00\x12\x16\n\x12LOCK_FAULT_FAULTED\x10\x01*\xcb\x01\n\x0eWindowInstance\x12\x1f\n\x1bWINDOW_INSTANCE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aWINDOW_INSTANCE_FRONT_LEFT\x10\x01\x12\x1f\n\x1bWINDOW_INSTANCE_FRONT_RIGHT\x10\x02\x12\x1d\n\x19WINDOW_INSTANCE_REAR_LEFT\x10\x03\x12\x1e\n\x1aWINDOW_INSTANCE_REAR_RIGHT\x10\x04\x12\x18\n\x14WINDOW_INSTANCE_REAR\x10\x05*\x81\x01\n\x11\x43\x61librationStatus\x12\"\n\x1e\x43\x41LIBRATION_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1d\x43\x41LIBRATION_STATUS_CALIBRATED\x10\x01\x12%\n!CALIBRATION_STATUS_NOT_CALIBRATED\x10\x02*\xd8\x01\n\x0fRearHitchStatus\x12!\n\x1dREAR_HITCH_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1dREAR_HITCH_STATUS_NOT_PRESENT\x10\x01\x12\x1f\n\x1bREAR_HITCH_STATUS_ACCESSORY\x10\x02\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER1\x10\x03\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER2\x10\x04\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER3\x10\x05*\xaa\x01\n\x0c\x43losureFault\x12\x1d\n\x19\x43LOSURE_FAULT_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43LOSURE_FAULT_NO_FAULT\x10\x01\x12\x19\n\x15\x43LOSURE_FAULT_GENERAL\x10\x02\x12&\n\"CLOSURE_FAULT_NO_POWERED_OPERATION\x10\x03\x12\x1c\n\x18\x43LOSURE_FAULT_OBSTRUCTED\x10\x04*\x97\x01\n\x0fTrailerPresence\x12 \n\x1cTRAILER_PRESENCE_UNSPECIFIED\x10\x00\x12\x17\n\x13TRAILER_NOT_PRESENT\x10\x01\x12\x13\n\x0fTRAILER_PRESENT\x10\x02\x12\x1f\n\x1bTRAILER_PRESENT_WITH_BRAKES\x10\x03\x12\x13\n\x0fTRAILER_INVALID\x10\x04*\x9f\x04\n\x18\x43hargePortDoorNextAction\x12\x18\n\x14\x43HARGE_PORT_DOOR_SNA\x10\x00\x12!\n\x1d\x43HARGE_PORT_DOOR_OPEN_ALLOWED\x10\x01\x12\'\n#CHARGE_PORT_DOOR_OPEN_NOT_AVAILABLE\x10\x02\x12-\n)CHARGE_PORT_DOOR_OPEN_NOT_ALLOWED_FAULTED\x10\x03\x12\x1c\n\x18\x43HARGE_PORT_DOOR_OPENING\x10\x04\x12\"\n\x1e\x43HARGE_PORT_DOOR_CLOSE_ALLOWED\x10\x05\x12;\n7CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_OPENING_CLOSE_ALLOWED\x10\x06\x12:\n6CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_OPENING_OPEN_ALLOWED\x10\x07\x12;\n7CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_CLOSING_CLOSE_ALLOWED\x10\x08\x12(\n$CHARGE_PORT_DOOR_CLOSE_NOT_AVAILABLE\x10\t\x12.\n*CHARGE_PORT_DOOR_CLOSE_NOT_ALLOWED_FAULTED\x10\n\x12\x1c\n\x18\x43HARGE_PORT_DOOR_CLOSING\x10\x0b*\xb0\x03\n\x0f\x46runkNextAction\x12\r\n\tFRUNK_SNA\x10\x00\x12\x16\n\x12\x46RUNK_OPEN_ALLOWED\x10\x01\x12\x17\n\x13\x46RUNK_CLOSE_ALLOWED\x10\x02\x12\x11\n\rFRUNK_OPENING\x10\x03\x12\x11\n\rFRUNK_CLOSING\x10\x04\x12\x1c\n\x18\x46RUNK_OPEN_NOT_AVAILABLE\x10\x05\x12\x1d\n\x19\x46RUNK_CLOSE_NOT_AVAILABLE\x10\x06\x12\"\n\x1e\x46RUNK_OPEN_NOT_ALLOWED_FAULTED\x10\x07\x12#\n\x1f\x46RUNK_CLOSE_NOT_ALLOWED_FAULTED\x10\x08\x12)\n%FRUNK_OPEN_ALLOWED_NO_POWER_OPERATION\x10\t\x12.\n*FRUNK_CLOSE_NOT_ALLOWED_NO_POWER_OPERATION\x10\n\x12*\n&FRUNK_OBSTRUCTED_OPENING_CLOSE_ALLOWED\x10\x0b\x12*\n&FRUNK_OBSTRUCTED_CLOSING_CLOSE_ALLOWED\x10\x0c*\xa7\x06\n\x12LiftgateNextAction\x12\x10\n\x0cLIFTGATE_SNA\x10\x00\x12\x19\n\x15LIFTGATE_OPEN_ALLOWED\x10\x01\x12\x1a\n\x16LIFTGATE_CLOSE_ALLOWED\x10\x02\x12\x14\n\x10LIFTGATE_OPENING\x10\x03\x12\x14\n\x10LIFTGATE_CLOSING\x10\x04\x12\x1f\n\x1bLIFTGATE_OPEN_NOT_AVAILABLE\x10\x05\x12 \n\x1cLIFTGATE_CLOSE_NOT_AVAILABLE\x10\x06\x12%\n!LIFTGATE_OPEN_NOT_ALLOWED_FAULTED\x10\x07\x12&\n\"LIFTGATE_CLOSE_NOT_ALLOWED_FAULTED\x10\x08\x12,\n(LIFTGATE_OPEN_ALLOWED_NO_POWER_OPERATION\x10\t\x12\x31\n-LIFTGATE_CLOSE_NOT_ALLOWED_NO_POWER_OPERATION\x10\n\x12-\n)LIFTGATE_OBSTRUCTED_OPENING_CLOSE_ALLOWED\x10\x0b\x12-\n)LIFTGATE_OBSTRUCTED_CLOSING_CLOSE_ALLOWED\x10\x0c\x12.\n*LIFTGATE_LOWER_GATE_OPEN_CLOSE_NOT_ALLOWED\x10\r\x12&\n\"LIFTGATE_OPENING_PAUSE_NOT_ALLOWED\x10\x0e\x12&\n\"LIFTGATE_CLOSING_PAUSE_NOT_ALLOWED\x10\x0f\x12+\n\'LIFTGATE_OPEN_ALLOWED_OBSTACLE_DETECTED\x10\x10\x12*\n&LIFTGATE_OPEN_ALLOWED_TRAILER_DETECTED\x10\x11\x12,\n(LIFTGATE_CLOSE_ALLOWED_OBSTACLE_DETECTED\x10\x12\x12+\n\'LIFTGATE_CLOSE_ALLOWED_TRAILER_DETECTED\x10\x13\x12\x17\n\x13LIFTGATE_PROCESSING\x10\x14*\xb2\x02\n\x11SideBinNextAction\x12\x10\n\x0cSIDE_BIN_SNA\x10\x00\x12\x19\n\x15SIDE_BIN_OPEN_ALLOWED\x10\x01\x12\x14\n\x10SIDE_BIN_OPENING\x10\x02\x12\x1f\n\x1bSIDE_BIN_OPEN_NOT_AVAILABLE\x10\x03\x12%\n!SIDE_BIN_OPEN_NOT_ALLOWED_FAULTED\x10\x04\x12\x32\n.SIDE_BIN_STUCK_AJAR_WHILE_OPENING_OPEN_ALLOWED\x10\x05\x12-\n)SIDE_BIN_OPEN_ALREADY_NO_ACTION_AVAILABLE\x10\x06\x12/\n+SIDE_BIN_OPEN_ALLOWED_CONFIRM_VEHICLE_ANGLE\x10\x07*\x8c\x03\n\x12TailgateNextAction\x12\x10\n\x0cTAILGATE_SNA\x10\x00\x12\x19\n\x15TAILGATE_OPEN_ALLOWED\x10\x01\x12\x14\n\x10TAILGATE_OPENING\x10\x02\x12\x1f\n\x1bTAILGATE_OPEN_NOT_AVAILABLE\x10\x03\x12%\n!TAILGATE_OPEN_NOT_ALLOWED_FAULTED\x10\x04\x12\x32\n.TAILGATE_STUCK_AJAR_WHILE_OPENING_OPEN_ALLOWED\x10\x05\x12-\n)TAILGATE_OPEN_ALREADY_NO_ACTION_AVAILABLE\x10\x06\x12/\n+TAILGATE_OPEN_ALLOWED_CONFIRM_VEHICLE_ANGLE\x10\x07\x12+\n\'TAILGATE_OPEN_ALLOWED_OBSTACLE_DETECTED\x10\x08\x12*\n&TAILGATE_OPEN_ALLOWED_TRAILER_DETECTED\x10\t*\xb0\x03\n\x11WindowsNextAction\x12\x0f\n\x0bWINDOWS_SNA\x10\x00\x12\x18\n\x14WINDOWS_OPEN_ALLOWED\x10\x01\x12\x19\n\x15WINDOWS_CLOSE_ALLOWED\x10\x02\x12\x13\n\x0fWINDOWS_OPENING\x10\x03\x12\x13\n\x0fWINDOWS_CLOSING\x10\x04\x12\x12\n\x0eWINDOWS_MOVING\x10\x05\x12\x1e\n\x1aWINDOWS_OPEN_NOT_AVAILABLE\x10\x06\x12\x1f\n\x1bWINDOWS_CLOSE_NOT_AVAILABLE\x10\x07\x12$\n WINDOWS_OPEN_NOT_ALLOWED_FAULTED\x10\x08\x12%\n!WINDOWS_CLOSE_NOT_ALLOWED_FAULTED\x10\t\x12\x32\n.WINDOWS_OBSTRUCTED_WHILE_CLOSING_CLOSE_ALLOWED\x10\n\x12*\n&WINDOWS_CLOSE_NOT_ALLOWED_UNCALIBRATED\x10\x0b\x12)\n%WINDOWS_OPEN_NOT_ALLOWED_UNCALIBRATED\x10\x0c*\x8a\x01\n\x0fWiperFluidState\x12!\n\x1dWIPER_FLUID_STATE_UNSPECIFIED\x10\x00\x12\x1c\n\x18WIPER_FLUID_STATE_NORMAL\x10\x01\x12\x19\n\x15WIPER_FLUID_STATE_LOW\x10\x02\x12\x1b\n\x17WIPER_FLUID_STATE_EMPTY\x10\x03\x62\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n rivian/parallax/proto/body.proto\x12\x14rivian.parallax.body\"\x89\x06\n\rClosuresState\x12<\n\x07\x63losure\x18\x01 \x03(\x0b\x32+.rivian.parallax.body.ClosuresState.Closure\x1a\xb9\x05\n\x07\x43losure\x12+\n\x02id\x18\x01 \x01(\x0e\x32\x1f.rivian.parallax.body.ClosureId\x12\x36\n\x05state\x18\x02 \x01(\x0e\x32\".rivian.parallax.body.ClosureStateH\x01\x88\x01\x01\x12\x1d\n\x15open_position_percent\x18\x03 \x01(\x05\x12\x31\n\x05\x66\x61ult\x18\x04 \x01(\x0e\x32\".rivian.parallax.body.ClosureFault\x12\x46\n\x13windows_next_action\x18\x05 \x01(\x0e\x32\'.rivian.parallax.body.WindowsNextActionH\x00\x12\x42\n\x11\x66runk_next_action\x18\x06 \x01(\x0e\x32%.rivian.parallax.body.FrunkNextActionH\x00\x12H\n\x14liftgate_next_action\x18\x07 \x01(\x0e\x32(.rivian.parallax.body.LiftgateNextActionH\x00\x12G\n\x14side_bin_next_action\x18\x08 \x01(\x0e\x32\'.rivian.parallax.body.SideBinNextActionH\x00\x12H\n\x14tailgate_next_action\x18\t \x01(\x0e\x32(.rivian.parallax.body.TailgateNextActionH\x00\x12V\n\x1c\x63harge_port_door_next_action\x18\n \x01(\x0e\x32..rivian.parallax.body.ChargePortDoorNextActionH\x00\x12\x1d\n\x13tonneau_next_action\x18\x0b \x01(\x05H\x00\x42\r\n\x0bnext_actionB\x08\n\x06_state\"\xe3\x01\n\nLocksState\x12\x33\n\x04lock\x18\x01 \x03(\x0b\x32%.rivian.parallax.body.LocksState.Lock\x1a\x9f\x01\n\x04Lock\x12(\n\x02id\x18\x01 \x01(\x0e\x32\x1c.rivian.parallax.body.LockId\x12\x33\n\x05state\x18\x02 \x01(\x0e\x32\x1f.rivian.parallax.body.LockStateH\x00\x88\x01\x01\x12.\n\x05\x66\x61ult\x18\x03 \x01(\x0e\x32\x1f.rivian.parallax.body.LockFaultB\x08\n\x06_state\"\xd1\x01\n\x0cWindowsState\x12\x39\n\x06window\x18\x01 \x03(\x0b\x32).rivian.parallax.body.WindowsState.Window\x1a\x85\x01\n\x06Window\x12\x36\n\x08instance\x18\x01 \x01(\x0e\x32$.rivian.parallax.body.WindowInstance\x12\x43\n\x12\x63\x61libration_status\x18\x02 \x01(\x0e\x32\'.rivian.parallax.body.CalibrationStatus\"\x9b\x01\n\x0cTrailerState\x12<\n\x08presence\x18\x01 \x01(\x0e\x32%.rivian.parallax.body.TrailerPresenceH\x00\x88\x01\x01\x12@\n\x11rear_hitch_status\x18\x02 \x01(\x0e\x32%.rivian.parallax.body.RearHitchStatusB\x0b\n\t_presence\"G\n\x0fWiperFluidLevel\x12\x34\n\x05state\x18\x02 \x01(\x0e\x32%.rivian.parallax.body.WiperFluidState\"C\n\rUnlockCommand\x12\r\n\x03\x61ll\x18\x01 \x01(\x08H\x00\x12\x19\n\x0fuser_preference\x18\x02 \x01(\x08H\x00\x42\x08\n\x06target\"\r\n\x0bLockCommand*\xe8\x02\n\tClosureId\x12\x1a\n\x16\x43LOSURE_ID_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x44OOR_FRONT_LEFT\x10\x01\x12\x14\n\x10\x44OOR_FRONT_RIGHT\x10\x02\x12\x12\n\x0e\x44OOR_REAR_LEFT\x10\x03\x12\x13\n\x0f\x44OOR_REAR_RIGHT\x10\x04\x12\t\n\x05\x46RUNK\x10\x05\x12\x0c\n\x08TAILGATE\x10\x06\x12\x0c\n\x08LIFTGATE\x10\x07\x12\x11\n\rSIDE_BIN_LEFT\x10\x08\x12\x12\n\x0eSIDE_BIN_RIGHT\x10\t\x12\x0f\n\x0b\x43HARGE_PORT\x10\n\x12\x0b\n\x07TONNEAU\x10\x0b\x12\x15\n\x11WINDOW_FRONT_LEFT\x10\x0c\x12\x16\n\x12WINDOW_FRONT_RIGHT\x10\r\x12\x14\n\x10WINDOW_REAR_LEFT\x10\x0e\x12\x15\n\x11WINDOW_REAR_RIGHT\x10\x0f\x12\x0f\n\x0bWINDOW_REAR\x10\x10\x12\x12\n\rGROUP_WINDOWS\x10\x90N*\xad\x01\n\x0c\x43losureState\x12\x1d\n\x19\x43LOSURE_STATE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LOSURE_STATE_OPEN\x10\x01\x12\x18\n\x14\x43LOSURE_STATE_CLOSED\x10\x02\x12\x16\n\x12\x43LOSURE_STATE_AJAR\x10\x03\x12\x19\n\x15\x43LOSURE_STATE_OPENING\x10\x04\x12\x19\n\x15\x43LOSURE_STATE_CLOSING\x10\x05*\xf3\x02\n\x06LockId\x12\x17\n\x13LOCK_ID_UNSPECIFIED\x10\x00\x12\x18\n\x14LOCK_DOOR_FRONT_LEFT\x10\x01\x12\x19\n\x15LOCK_DOOR_FRONT_RIGHT\x10\x02\x12\x17\n\x13LOCK_DOOR_REAR_LEFT\x10\x03\x12\x18\n\x14LOCK_DOOR_REAR_RIGHT\x10\x04\x12\x0e\n\nLOCK_FRUNK\x10\x05\x12\x11\n\rLOCK_TAILGATE\x10\x06\x12\x11\n\rLOCK_LIFTGATE\x10\x07\x12\x16\n\x12LOCK_SIDE_BIN_LEFT\x10\x08\x12\x17\n\x13LOCK_SIDE_BIN_RIGHT\x10\t\x12\x14\n\x10LOCK_CHARGE_PORT\x10\n\x12\x17\n\x13LOCK_TRUNK_SECURITY\x10\x0b\x12\x17\n\x13LOCK_CENTER_CONSOLE\x10\x0c\x12\x12\n\x0eLOCK_GLOVE_BOX\x10\r\x12\x13\n\x0fLOCK_GEAR_GUARD\x10\x0e\x12\x10\n\x0cLOCK_TONNEAU\x10\x0f*z\n\tLockState\x12\x1a\n\x16LOCK_STATE_UNSPECIFIED\x10\x00\x12\x15\n\x11LOCK_STATE_LOCKED\x10\x01\x12\x17\n\x13LOCK_STATE_UNLOCKED\x10\x02\x12!\n\x1dLOCK_STATE_PARTIALLY_UNLOCKED\x10\x03*?\n\tLockFault\x12\x1a\n\x16LOCK_FAULT_UNSPECIFIED\x10\x00\x12\x16\n\x12LOCK_FAULT_FAULTED\x10\x01*\xcb\x01\n\x0eWindowInstance\x12\x1f\n\x1bWINDOW_INSTANCE_UNSPECIFIED\x10\x00\x12\x1e\n\x1aWINDOW_INSTANCE_FRONT_LEFT\x10\x01\x12\x1f\n\x1bWINDOW_INSTANCE_FRONT_RIGHT\x10\x02\x12\x1d\n\x19WINDOW_INSTANCE_REAR_LEFT\x10\x03\x12\x1e\n\x1aWINDOW_INSTANCE_REAR_RIGHT\x10\x04\x12\x18\n\x14WINDOW_INSTANCE_REAR\x10\x05*\x81\x01\n\x11\x43\x61librationStatus\x12\"\n\x1e\x43\x41LIBRATION_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1d\x43\x41LIBRATION_STATUS_CALIBRATED\x10\x01\x12%\n!CALIBRATION_STATUS_NOT_CALIBRATED\x10\x02*\xd8\x01\n\x0fRearHitchStatus\x12!\n\x1dREAR_HITCH_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1dREAR_HITCH_STATUS_NOT_PRESENT\x10\x01\x12\x1f\n\x1bREAR_HITCH_STATUS_ACCESSORY\x10\x02\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER1\x10\x03\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER2\x10\x04\x12\x1e\n\x1aREAR_HITCH_STATUS_TRAILER3\x10\x05*\xaa\x01\n\x0c\x43losureFault\x12\x1d\n\x19\x43LOSURE_FAULT_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43LOSURE_FAULT_NO_FAULT\x10\x01\x12\x19\n\x15\x43LOSURE_FAULT_GENERAL\x10\x02\x12&\n\"CLOSURE_FAULT_NO_POWERED_OPERATION\x10\x03\x12\x1c\n\x18\x43LOSURE_FAULT_OBSTRUCTED\x10\x04*\x97\x01\n\x0fTrailerPresence\x12 \n\x1cTRAILER_PRESENCE_UNSPECIFIED\x10\x00\x12\x17\n\x13TRAILER_NOT_PRESENT\x10\x01\x12\x13\n\x0fTRAILER_PRESENT\x10\x02\x12\x1f\n\x1bTRAILER_PRESENT_WITH_BRAKES\x10\x03\x12\x13\n\x0fTRAILER_INVALID\x10\x04*\x9f\x04\n\x18\x43hargePortDoorNextAction\x12\x18\n\x14\x43HARGE_PORT_DOOR_SNA\x10\x00\x12!\n\x1d\x43HARGE_PORT_DOOR_OPEN_ALLOWED\x10\x01\x12\'\n#CHARGE_PORT_DOOR_OPEN_NOT_AVAILABLE\x10\x02\x12-\n)CHARGE_PORT_DOOR_OPEN_NOT_ALLOWED_FAULTED\x10\x03\x12\x1c\n\x18\x43HARGE_PORT_DOOR_OPENING\x10\x04\x12\"\n\x1e\x43HARGE_PORT_DOOR_CLOSE_ALLOWED\x10\x05\x12;\n7CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_OPENING_CLOSE_ALLOWED\x10\x06\x12:\n6CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_OPENING_OPEN_ALLOWED\x10\x07\x12;\n7CHARGE_PORT_DOOR_OBSTRUCTED_WHILE_CLOSING_CLOSE_ALLOWED\x10\x08\x12(\n$CHARGE_PORT_DOOR_CLOSE_NOT_AVAILABLE\x10\t\x12.\n*CHARGE_PORT_DOOR_CLOSE_NOT_ALLOWED_FAULTED\x10\n\x12\x1c\n\x18\x43HARGE_PORT_DOOR_CLOSING\x10\x0b*\xb0\x03\n\x0f\x46runkNextAction\x12\r\n\tFRUNK_SNA\x10\x00\x12\x16\n\x12\x46RUNK_OPEN_ALLOWED\x10\x01\x12\x17\n\x13\x46RUNK_CLOSE_ALLOWED\x10\x02\x12\x11\n\rFRUNK_OPENING\x10\x03\x12\x11\n\rFRUNK_CLOSING\x10\x04\x12\x1c\n\x18\x46RUNK_OPEN_NOT_AVAILABLE\x10\x05\x12\x1d\n\x19\x46RUNK_CLOSE_NOT_AVAILABLE\x10\x06\x12\"\n\x1e\x46RUNK_OPEN_NOT_ALLOWED_FAULTED\x10\x07\x12#\n\x1f\x46RUNK_CLOSE_NOT_ALLOWED_FAULTED\x10\x08\x12)\n%FRUNK_OPEN_ALLOWED_NO_POWER_OPERATION\x10\t\x12.\n*FRUNK_CLOSE_NOT_ALLOWED_NO_POWER_OPERATION\x10\n\x12*\n&FRUNK_OBSTRUCTED_OPENING_CLOSE_ALLOWED\x10\x0b\x12*\n&FRUNK_OBSTRUCTED_CLOSING_CLOSE_ALLOWED\x10\x0c*\xa7\x06\n\x12LiftgateNextAction\x12\x10\n\x0cLIFTGATE_SNA\x10\x00\x12\x19\n\x15LIFTGATE_OPEN_ALLOWED\x10\x01\x12\x1a\n\x16LIFTGATE_CLOSE_ALLOWED\x10\x02\x12\x14\n\x10LIFTGATE_OPENING\x10\x03\x12\x14\n\x10LIFTGATE_CLOSING\x10\x04\x12\x1f\n\x1bLIFTGATE_OPEN_NOT_AVAILABLE\x10\x05\x12 \n\x1cLIFTGATE_CLOSE_NOT_AVAILABLE\x10\x06\x12%\n!LIFTGATE_OPEN_NOT_ALLOWED_FAULTED\x10\x07\x12&\n\"LIFTGATE_CLOSE_NOT_ALLOWED_FAULTED\x10\x08\x12,\n(LIFTGATE_OPEN_ALLOWED_NO_POWER_OPERATION\x10\t\x12\x31\n-LIFTGATE_CLOSE_NOT_ALLOWED_NO_POWER_OPERATION\x10\n\x12-\n)LIFTGATE_OBSTRUCTED_OPENING_CLOSE_ALLOWED\x10\x0b\x12-\n)LIFTGATE_OBSTRUCTED_CLOSING_CLOSE_ALLOWED\x10\x0c\x12.\n*LIFTGATE_LOWER_GATE_OPEN_CLOSE_NOT_ALLOWED\x10\r\x12&\n\"LIFTGATE_OPENING_PAUSE_NOT_ALLOWED\x10\x0e\x12&\n\"LIFTGATE_CLOSING_PAUSE_NOT_ALLOWED\x10\x0f\x12+\n\'LIFTGATE_OPEN_ALLOWED_OBSTACLE_DETECTED\x10\x10\x12*\n&LIFTGATE_OPEN_ALLOWED_TRAILER_DETECTED\x10\x11\x12,\n(LIFTGATE_CLOSE_ALLOWED_OBSTACLE_DETECTED\x10\x12\x12+\n\'LIFTGATE_CLOSE_ALLOWED_TRAILER_DETECTED\x10\x13\x12\x17\n\x13LIFTGATE_PROCESSING\x10\x14*\xb2\x02\n\x11SideBinNextAction\x12\x10\n\x0cSIDE_BIN_SNA\x10\x00\x12\x19\n\x15SIDE_BIN_OPEN_ALLOWED\x10\x01\x12\x14\n\x10SIDE_BIN_OPENING\x10\x02\x12\x1f\n\x1bSIDE_BIN_OPEN_NOT_AVAILABLE\x10\x03\x12%\n!SIDE_BIN_OPEN_NOT_ALLOWED_FAULTED\x10\x04\x12\x32\n.SIDE_BIN_STUCK_AJAR_WHILE_OPENING_OPEN_ALLOWED\x10\x05\x12-\n)SIDE_BIN_OPEN_ALREADY_NO_ACTION_AVAILABLE\x10\x06\x12/\n+SIDE_BIN_OPEN_ALLOWED_CONFIRM_VEHICLE_ANGLE\x10\x07*\x8c\x03\n\x12TailgateNextAction\x12\x10\n\x0cTAILGATE_SNA\x10\x00\x12\x19\n\x15TAILGATE_OPEN_ALLOWED\x10\x01\x12\x14\n\x10TAILGATE_OPENING\x10\x02\x12\x1f\n\x1bTAILGATE_OPEN_NOT_AVAILABLE\x10\x03\x12%\n!TAILGATE_OPEN_NOT_ALLOWED_FAULTED\x10\x04\x12\x32\n.TAILGATE_STUCK_AJAR_WHILE_OPENING_OPEN_ALLOWED\x10\x05\x12-\n)TAILGATE_OPEN_ALREADY_NO_ACTION_AVAILABLE\x10\x06\x12/\n+TAILGATE_OPEN_ALLOWED_CONFIRM_VEHICLE_ANGLE\x10\x07\x12+\n\'TAILGATE_OPEN_ALLOWED_OBSTACLE_DETECTED\x10\x08\x12*\n&TAILGATE_OPEN_ALLOWED_TRAILER_DETECTED\x10\t*\xb0\x03\n\x11WindowsNextAction\x12\x0f\n\x0bWINDOWS_SNA\x10\x00\x12\x18\n\x14WINDOWS_OPEN_ALLOWED\x10\x01\x12\x19\n\x15WINDOWS_CLOSE_ALLOWED\x10\x02\x12\x13\n\x0fWINDOWS_OPENING\x10\x03\x12\x13\n\x0fWINDOWS_CLOSING\x10\x04\x12\x12\n\x0eWINDOWS_MOVING\x10\x05\x12\x1e\n\x1aWINDOWS_OPEN_NOT_AVAILABLE\x10\x06\x12\x1f\n\x1bWINDOWS_CLOSE_NOT_AVAILABLE\x10\x07\x12$\n WINDOWS_OPEN_NOT_ALLOWED_FAULTED\x10\x08\x12%\n!WINDOWS_CLOSE_NOT_ALLOWED_FAULTED\x10\t\x12\x32\n.WINDOWS_OBSTRUCTED_WHILE_CLOSING_CLOSE_ALLOWED\x10\n\x12*\n&WINDOWS_CLOSE_NOT_ALLOWED_UNCALIBRATED\x10\x0b\x12)\n%WINDOWS_OPEN_NOT_ALLOWED_UNCALIBRATED\x10\x0c*\x8a\x01\n\x0fWiperFluidState\x12!\n\x1dWIPER_FLUID_STATE_UNSPECIFIED\x10\x00\x12\x1c\n\x18WIPER_FLUID_STATE_NORMAL\x10\x01\x12\x19\n\x15WIPER_FLUID_STATE_LOW\x10\x02\x12\x1b\n\x17WIPER_FLUID_STATE_EMPTY\x10\x03\x62\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
31
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'rivian.parallax.proto.body_pb2', _globals)
32
32
  if not _descriptor._USE_C_DESCRIPTORS:
33
33
  DESCRIPTOR._loaded_options = None
34
- _globals['_CLOSUREID']._serialized_start=1512
35
- _globals['_CLOSUREID']._serialized_end=1872
36
- _globals['_CLOSURESTATE']._serialized_start=1875
37
- _globals['_CLOSURESTATE']._serialized_end=2048
38
- _globals['_LOCKID']._serialized_start=2051
39
- _globals['_LOCKID']._serialized_end=2422
40
- _globals['_LOCKSTATE']._serialized_start=2424
41
- _globals['_LOCKSTATE']._serialized_end=2546
42
- _globals['_LOCKFAULT']._serialized_start=2548
43
- _globals['_LOCKFAULT']._serialized_end=2611
44
- _globals['_WINDOWINSTANCE']._serialized_start=2614
45
- _globals['_WINDOWINSTANCE']._serialized_end=2817
46
- _globals['_CALIBRATIONSTATUS']._serialized_start=2820
47
- _globals['_CALIBRATIONSTATUS']._serialized_end=2949
48
- _globals['_REARHITCHSTATUS']._serialized_start=2952
49
- _globals['_REARHITCHSTATUS']._serialized_end=3168
50
- _globals['_CLOSUREFAULT']._serialized_start=3171
51
- _globals['_CLOSUREFAULT']._serialized_end=3341
52
- _globals['_TRAILERPRESENCE']._serialized_start=3344
53
- _globals['_TRAILERPRESENCE']._serialized_end=3495
54
- _globals['_CHARGEPORTDOORNEXTACTION']._serialized_start=3498
55
- _globals['_CHARGEPORTDOORNEXTACTION']._serialized_end=4041
56
- _globals['_FRUNKNEXTACTION']._serialized_start=4044
57
- _globals['_FRUNKNEXTACTION']._serialized_end=4476
58
- _globals['_LIFTGATENEXTACTION']._serialized_start=4479
59
- _globals['_LIFTGATENEXTACTION']._serialized_end=5286
60
- _globals['_SIDEBINNEXTACTION']._serialized_start=5289
61
- _globals['_SIDEBINNEXTACTION']._serialized_end=5595
62
- _globals['_TAILGATENEXTACTION']._serialized_start=5598
63
- _globals['_TAILGATENEXTACTION']._serialized_end=5994
64
- _globals['_WINDOWSNEXTACTION']._serialized_start=5997
65
- _globals['_WINDOWSNEXTACTION']._serialized_end=6429
66
- _globals['_WIPERFLUIDSTATE']._serialized_start=6432
67
- _globals['_WIPERFLUIDSTATE']._serialized_end=6570
34
+ _globals['_CLOSUREID']._serialized_start=1596
35
+ _globals['_CLOSUREID']._serialized_end=1956
36
+ _globals['_CLOSURESTATE']._serialized_start=1959
37
+ _globals['_CLOSURESTATE']._serialized_end=2132
38
+ _globals['_LOCKID']._serialized_start=2135
39
+ _globals['_LOCKID']._serialized_end=2506
40
+ _globals['_LOCKSTATE']._serialized_start=2508
41
+ _globals['_LOCKSTATE']._serialized_end=2630
42
+ _globals['_LOCKFAULT']._serialized_start=2632
43
+ _globals['_LOCKFAULT']._serialized_end=2695
44
+ _globals['_WINDOWINSTANCE']._serialized_start=2698
45
+ _globals['_WINDOWINSTANCE']._serialized_end=2901
46
+ _globals['_CALIBRATIONSTATUS']._serialized_start=2904
47
+ _globals['_CALIBRATIONSTATUS']._serialized_end=3033
48
+ _globals['_REARHITCHSTATUS']._serialized_start=3036
49
+ _globals['_REARHITCHSTATUS']._serialized_end=3252
50
+ _globals['_CLOSUREFAULT']._serialized_start=3255
51
+ _globals['_CLOSUREFAULT']._serialized_end=3425
52
+ _globals['_TRAILERPRESENCE']._serialized_start=3428
53
+ _globals['_TRAILERPRESENCE']._serialized_end=3579
54
+ _globals['_CHARGEPORTDOORNEXTACTION']._serialized_start=3582
55
+ _globals['_CHARGEPORTDOORNEXTACTION']._serialized_end=4125
56
+ _globals['_FRUNKNEXTACTION']._serialized_start=4128
57
+ _globals['_FRUNKNEXTACTION']._serialized_end=4560
58
+ _globals['_LIFTGATENEXTACTION']._serialized_start=4563
59
+ _globals['_LIFTGATENEXTACTION']._serialized_end=5370
60
+ _globals['_SIDEBINNEXTACTION']._serialized_start=5373
61
+ _globals['_SIDEBINNEXTACTION']._serialized_end=5679
62
+ _globals['_TAILGATENEXTACTION']._serialized_start=5682
63
+ _globals['_TAILGATENEXTACTION']._serialized_end=6078
64
+ _globals['_WINDOWSNEXTACTION']._serialized_start=6081
65
+ _globals['_WINDOWSNEXTACTION']._serialized_end=6513
66
+ _globals['_WIPERFLUIDSTATE']._serialized_start=6516
67
+ _globals['_WIPERFLUIDSTATE']._serialized_end=6654
68
68
  _globals['_CLOSURESSTATE']._serialized_start=59
69
69
  _globals['_CLOSURESSTATE']._serialized_end=836
70
70
  _globals['_CLOSURESSTATE_CLOSURE']._serialized_start=139
@@ -81,4 +81,8 @@ if not _descriptor._USE_C_DESCRIPTORS:
81
81
  _globals['_TRAILERSTATE']._serialized_end=1436
82
82
  _globals['_WIPERFLUIDLEVEL']._serialized_start=1438
83
83
  _globals['_WIPERFLUIDLEVEL']._serialized_end=1509
84
+ _globals['_UNLOCKCOMMAND']._serialized_start=1511
85
+ _globals['_UNLOCKCOMMAND']._serialized_end=1578
86
+ _globals['_LOCKCOMMAND']._serialized_start=1580
87
+ _globals['_LOCKCOMMAND']._serialized_end=1593
84
88
  # @@protoc_insertion_point(module_scope)
@@ -434,3 +434,15 @@ class WiperFluidLevel(_message.Message):
434
434
  STATE_FIELD_NUMBER: _ClassVar[int]
435
435
  state: WiperFluidState
436
436
  def __init__(self, state: _Optional[_Union[WiperFluidState, str]] = ...) -> None: ...
437
+
438
+ class UnlockCommand(_message.Message):
439
+ __slots__ = ("all", "user_preference")
440
+ ALL_FIELD_NUMBER: _ClassVar[int]
441
+ USER_PREFERENCE_FIELD_NUMBER: _ClassVar[int]
442
+ all: bool
443
+ user_preference: bool
444
+ def __init__(self, all: bool = ..., user_preference: bool = ...) -> None: ...
445
+
446
+ class LockCommand(_message.Message):
447
+ __slots__ = ()
448
+ def __init__(self) -> None: ...
@@ -0,0 +1,108 @@
1
+ syntax = "proto3";
2
+
3
+ package rivian.parallax.command;
4
+
5
+ // Reverse-engineered `sendParallaxPayload` request for a signed remote command,
6
+ // and the `vehicleCommandStatePx` message that reports on it; see ../command.py.
7
+ // Only the field numbers matter on the wire. Enum values are named as the app
8
+ // names them, except ResponseStatus, which the app names without a prefix. Unlike
9
+ // operation.proto's Operation, this one goes to the vehicle inside a signed
10
+ // Envelope.
11
+
12
+ // Wraps an Operation. Field 17 is what makes it a signed command.
13
+ message Envelope {
14
+ // The app's envelope can hold other kinds of value; a command only uses this
15
+ oneof value {
16
+ Composite composite = 10;
17
+ }
18
+ Timestamp last_update = 12;
19
+ bytes correlation_id = 16; // the command id: 16 bytes of a UUID
20
+ SecurityInfo security_info = 17;
21
+ }
22
+
23
+ message Composite {
24
+ bytes bytes_val = 2; // a serialized Operation
25
+ }
26
+
27
+ message Operation {
28
+ string rvm = 1;
29
+ OperationType type = 2;
30
+ bytes command_id = 3; // the same 16 bytes as the envelope's correlation_id
31
+ bytes payload = 4; // the RVM's message; absent when empty
32
+ Timestamp created_at = 5;
33
+ // 6 is never set by the app
34
+ string vehicle_id = 7;
35
+ }
36
+
37
+ enum OperationType {
38
+ PARALLAX_OPERATION_UNSPECIFIED = 0;
39
+ PARALLAX_OPERATION_PUBLISH = 1;
40
+ PARALLAX_OPERATION_SUBSCRIBE = 2;
41
+ PARALLAX_OPERATION_REQUEST = 3; // the only one a command uses
42
+ }
43
+
44
+ message SecurityInfo {
45
+ Signature signature = 1;
46
+ string mapped_identity = 2; // the enrolled phone's identityId for the vehicle
47
+ }
48
+
49
+ message Signature {
50
+ SignatureType type = 1;
51
+ bytes value = 2; // 32 raw bytes of the HMAC-SHA256, not hex
52
+ }
53
+
54
+ enum SignatureType {
55
+ DATA_SIGNATURE_TYPE_UNSPECIFIED = 0;
56
+ DATA_SIGNATURE_TYPE_HMAC_SHA256 = 1;
57
+ DATA_SIGNATURE_TYPE_RCS = 2;
58
+ }
59
+
60
+ message Timestamp {
61
+ int64 seconds = 1; // epoch seconds
62
+ int32 nanos = 2;
63
+ }
64
+
65
+ // What `vehicleCommandStatePx` sends, base64 encoded, as the command goes on.
66
+ message CommandState {
67
+ bytes command_id = 1; // 16 bytes of a UUID
68
+ string rvm = 2;
69
+ Progress progress = 3;
70
+ oneof result {
71
+ OperationError operation_error = 4;
72
+ // The app declares this as bytes holding a CommandResult, which is the
73
+ // same on the wire. Present, but empty, for an undefined status.
74
+ CommandResult data = 5;
75
+ }
76
+ }
77
+
78
+ enum Progress {
79
+ VEHICLE_MODEL_OP_PROGRESS_UNSPECIFIED = 0;
80
+ VEHICLE_MODEL_OP_PROGRESS_VEHICLE_WAKING_UP = 1; // seen twice for one command
81
+ VEHICLE_MODEL_OP_PROGRESS_VEHICLE_VALIDATING = 2;
82
+ VEHICLE_MODEL_OP_PROGRESS_VEHICLE_EXECUTING = 3;
83
+ VEHICLE_MODEL_OP_PROGRESS_VEHICLE_COMPLETE = 4; // the last message
84
+ }
85
+
86
+ message CommandResult {
87
+ ResponseStatus response_status = 1;
88
+ Error error = 2;
89
+ }
90
+
91
+ enum ResponseStatus {
92
+ RESPONSE_STATUS_UNDEFINED = 0;
93
+ RESPONSE_STATUS_SUCCESS = 1;
94
+ RESPONSE_STATUS_FAIL = 2;
95
+ RESPONSE_STATUS_INVALID_REQUEST = 3;
96
+ RESPONSE_STATUS_NOT_SUPPORTED = 4;
97
+ RESPONSE_STATUS_TIMEOUT = 5;
98
+ }
99
+
100
+ message Error {
101
+ int32 code = 1;
102
+ string message = 2;
103
+ }
104
+
105
+ message OperationError {
106
+ int32 error = 1; // an enum in the app, whose values were not decompiled
107
+ string message = 2;
108
+ }