rivian-python-client 2.2.0b0__tar.gz → 2.2.0b2__tar.gz
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_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/PKG-INFO +1 -1
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/pyproject.toml +8 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/__version__.py +1 -1
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/__init__.py +2 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/body.py +70 -46
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/charging.py +63 -43
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/comfort.py +54 -45
- rivian_python_client-2.2.0b2/src/rivian/parallax/device_table.py +99 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/dynamics.py +34 -34
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/energy.py +6 -6
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/gearguard_streaming.py +9 -9
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/geofence.py +11 -5
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/holiday_celebration.py +46 -6
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/navigation.py +6 -3
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/ota.py +37 -24
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/body.proto +86 -27
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/body_pb2.py +72 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/body_pb2.pyi +154 -40
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/charging.proto +16 -7
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/charging_pb2.py +12 -10
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/charging_pb2.pyi +19 -6
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/comfort.proto +33 -26
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/comfort_pb2.py +24 -24
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/comfort_pb2.pyi +57 -43
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/device_table.proto +64 -0
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/device_table_pb2.py +50 -0
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/device_table_pb2.pyi +92 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/geofence.proto +9 -2
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/geofence_pb2.py +5 -3
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/geofence_pb2.pyi +16 -4
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/holiday_celebration.proto +24 -10
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/holiday_celebration_pb2.py +50 -0
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/holiday_celebration_pb2.pyi +92 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/navigation.proto +8 -1
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/navigation_pb2.py +19 -17
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/navigation_pb2.pyi +15 -4
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/ota.proto +24 -12
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/ota_pb2.py +17 -13
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/ota_pb2.pyi +30 -18
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/vehicle.proto +5 -5
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/vehicle_access.proto +19 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/vehicle_access_pb2.py +5 -3
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/vehicle_access_pb2.pyi +25 -0
- rivian_python_client-2.2.0b2/src/rivian/parallax/proto/vehicle_pb2.py +62 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/vehicle_pb2.pyi +20 -20
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/security.py +37 -37
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/vehicle.py +29 -23
- rivian_python_client-2.2.0b2/src/rivian/parallax/vehicle_access.py +39 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/ws_monitor.py +31 -0
- rivian_python_client-2.2.0b0/src/rivian/parallax/device_table.py +0 -59
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/body_pb2.py +0 -64
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/device_table.proto +0 -44
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/device_table_pb2.py +0 -46
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/device_table_pb2.pyi +0 -61
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/holiday_celebration_pb2.py +0 -44
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/holiday_celebration_pb2.pyi +0 -67
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/vehicle_access.proto +0 -8
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/vehicle_access_pb2.pyi +0 -9
- rivian_python_client-2.2.0b0/src/rivian/parallax/proto/vehicle_pb2.py +0 -62
- rivian_python_client-2.2.0b0/src/rivian/parallax/vehicle_access.py +0 -18
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/.gitignore +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/README.md +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/__init__.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/ble.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/const.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/exceptions.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/core.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/departure.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/energy_edge_compute.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/parallax.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/__init__.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/departure.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/departure_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/departure_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/dynamics.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/dynamics_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/dynamics_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy_edge_compute.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy_edge_compute_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy_edge_compute_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/energy_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/gearguard_streaming.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/gearguard_streaming_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/gearguard_streaming_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/parallax.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/parallax_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/parallax_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/secure_file_transfer.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/secure_file_transfer_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/secure_file_transfer_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/security.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/security_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/security_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/user_passcodes.proto +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/user_passcodes_pb2.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/proto/user_passcodes_pb2.pyi +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/secure_file_transfer.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/user_passcodes.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/py.typed +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/rivian.py +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/schemas/charging.graphql +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/schemas/gateway.graphql +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/schemas/orders.graphql +0 -0
- {rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: rivian-python-client
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.0b2
|
|
4
4
|
Summary: Rivian API Client (Unofficial)
|
|
5
5
|
Author-email: Brian Retterer <bretterer@gmail.com>, "J.R. Gutierrez" <jrgutier@gmail.com>, Nathan Spencer <natekspencer@gmail.com>, Trevor Mack <drummer8001@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -36,8 +36,16 @@ dev = [
|
|
|
36
36
|
"pre-commit>=4.6.1,<5",
|
|
37
37
|
"types-protobuf>=7.35.1.20260906",
|
|
38
38
|
"grpcio-tools==1.84.0",
|
|
39
|
+
"pytest-cov>=7.0,<8",
|
|
39
40
|
]
|
|
40
41
|
|
|
42
|
+
[tool.coverage.run]
|
|
43
|
+
source = ["rivian"]
|
|
44
|
+
omit = ["*_pb2.py"]
|
|
45
|
+
|
|
46
|
+
[tool.coverage.report]
|
|
47
|
+
exclude_also = ["if TYPE_CHECKING:"]
|
|
48
|
+
|
|
41
49
|
[tool.hatch.build.hooks.version]
|
|
42
50
|
path = "src/rivian/__version__.py"
|
|
43
51
|
|
{rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/__init__.py
RENAMED
|
@@ -50,7 +50,9 @@ from .core import (
|
|
|
50
50
|
PARALLAX_RVMS: list[str] = list(RVMDecoder.decoders)
|
|
51
51
|
|
|
52
52
|
CHARGING_RVMS: list[str] = [
|
|
53
|
+
"charging.energy.state",
|
|
53
54
|
"charging.session.notification",
|
|
55
|
+
"charging.session.power",
|
|
54
56
|
"charging.session.remote_command",
|
|
55
57
|
"charging.session.soc_slider",
|
|
56
58
|
"charging.session.status",
|
|
@@ -8,28 +8,30 @@ from .core import _LOGGER, RVMDecoder, _enum, _present
|
|
|
8
8
|
from .proto import body_pb2
|
|
9
9
|
|
|
10
10
|
_CLOSURE_MAP: Final[dict[int, str]] = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
body_pb2.DOOR_FRONT_LEFT: "doorFrontLeftClosed",
|
|
12
|
+
body_pb2.DOOR_FRONT_RIGHT: "doorFrontRightClosed",
|
|
13
|
+
body_pb2.DOOR_REAR_LEFT: "doorRearLeftClosed",
|
|
14
|
+
body_pb2.DOOR_REAR_RIGHT: "doorRearRightClosed",
|
|
15
|
+
body_pb2.FRUNK: "closureFrunkClosed",
|
|
16
|
+
body_pb2.TAILGATE: "closureTailgateClosed",
|
|
17
|
+
body_pb2.LIFTGATE: "closureLiftgateClosed",
|
|
18
|
+
body_pb2.SIDE_BIN_LEFT: "closureSideBinLeftClosed",
|
|
19
|
+
body_pb2.SIDE_BIN_RIGHT: "closureSideBinRightClosed",
|
|
20
|
+
body_pb2.CHARGE_PORT: "chargePortState",
|
|
21
|
+
body_pb2.TONNEAU: "closureTonneauClosed",
|
|
22
|
+
body_pb2.WINDOW_FRONT_LEFT: "windowFrontLeftClosed",
|
|
23
|
+
body_pb2.WINDOW_FRONT_RIGHT: "windowFrontRightClosed",
|
|
24
|
+
body_pb2.WINDOW_REAR_LEFT: "windowRearLeftClosed",
|
|
25
|
+
body_pb2.WINDOW_REAR_RIGHT: "windowRearRightClosed",
|
|
26
|
+
body_pb2.WINDOW_REAR: "windowRearClosed",
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
_CLOSURE_STATE_MAP: Final[dict[int, str]] = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
body_pb2.CLOSURE_STATE_OPEN: "open",
|
|
31
|
+
body_pb2.CLOSURE_STATE_CLOSED: "closed",
|
|
32
|
+
body_pb2.CLOSURE_STATE_AJAR: "ajar",
|
|
33
|
+
body_pb2.CLOSURE_STATE_OPENING: "opening",
|
|
34
|
+
body_pb2.CLOSURE_STATE_CLOSING: "closing",
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
|
|
@@ -41,11 +43,7 @@ def _enum_names(enum: Any, prefix: str) -> dict[int, str]:
|
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
_SIDE_BIN_NEXT_ACTIONS: Final[dict[int, str]] = {
|
|
46
|
-
body_pb2.SIDE_BIN_SNA: "sna",
|
|
47
|
-
body_pb2.SIDE_BIN_OPEN_ALLOWED: "open_allowed",
|
|
48
|
-
}
|
|
46
|
+
_SIDE_BIN_NEXT_ACTIONS: Final = _enum_names(body_pb2.SideBinNextAction, "SIDE_BIN_")
|
|
49
47
|
|
|
50
48
|
# Closure id -> (next-action field, result key, value names).
|
|
51
49
|
_NEXT_ACTIONS: Final[dict[int, tuple[str, str, dict[int, str]]]] = {
|
|
@@ -54,6 +52,11 @@ _NEXT_ACTIONS: Final[dict[int, tuple[str, str, dict[int, str]]]] = {
|
|
|
54
52
|
"closureFrunkNextAction",
|
|
55
53
|
_enum_names(body_pb2.FrunkNextAction, "FRUNK_"),
|
|
56
54
|
),
|
|
55
|
+
body_pb2.LIFTGATE: (
|
|
56
|
+
"liftgate_next_action",
|
|
57
|
+
"closureLiftgateNextAction",
|
|
58
|
+
_enum_names(body_pb2.LiftgateNextAction, "LIFTGATE_"),
|
|
59
|
+
),
|
|
57
60
|
body_pb2.SIDE_BIN_LEFT: (
|
|
58
61
|
"side_bin_next_action",
|
|
59
62
|
"closureSideBinLeftNextAction",
|
|
@@ -74,26 +77,42 @@ _NEXT_ACTIONS: Final[dict[int, tuple[str, str, dict[int, str]]]] = {
|
|
|
74
77
|
"closureChargePortDoorNextAction",
|
|
75
78
|
_enum_names(body_pb2.ChargePortDoorNextAction, "CHARGE_PORT_DOOR_"),
|
|
76
79
|
),
|
|
80
|
+
body_pb2.GROUP_WINDOWS: (
|
|
81
|
+
"windows_next_action",
|
|
82
|
+
"windowsNextAction",
|
|
83
|
+
_enum_names(body_pb2.WindowsNextAction, "WINDOWS_"),
|
|
84
|
+
),
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
_LOCK_MAP: Final[dict[int, str]] = {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
body_pb2.LOCK_DOOR_FRONT_LEFT: "doorFrontLeftLocked",
|
|
89
|
+
body_pb2.LOCK_DOOR_FRONT_RIGHT: "doorFrontRightLocked",
|
|
90
|
+
body_pb2.LOCK_DOOR_REAR_LEFT: "doorRearLeftLocked",
|
|
91
|
+
body_pb2.LOCK_DOOR_REAR_RIGHT: "doorRearRightLocked",
|
|
92
|
+
body_pb2.LOCK_FRUNK: "closureFrunkLocked",
|
|
93
|
+
body_pb2.LOCK_TAILGATE: "closureTailgateLocked",
|
|
94
|
+
body_pb2.LOCK_LIFTGATE: "closureLiftgateLocked",
|
|
95
|
+
body_pb2.LOCK_SIDE_BIN_LEFT: "closureSideBinLeftLocked",
|
|
96
|
+
body_pb2.LOCK_SIDE_BIN_RIGHT: "closureSideBinRightLocked",
|
|
97
|
+
body_pb2.LOCK_CHARGE_PORT: "closureChargePortLocked",
|
|
98
|
+
body_pb2.LOCK_TRUNK_SECURITY: "closureTrunkSecurityLocked",
|
|
99
|
+
body_pb2.LOCK_CENTER_CONSOLE: "closureCenterConsoleLocked",
|
|
100
|
+
body_pb2.LOCK_GLOVE_BOX: "closureGloveBoxLocked",
|
|
101
|
+
body_pb2.LOCK_GEAR_GUARD: "gearGuardLocked",
|
|
102
|
+
body_pb2.LOCK_TONNEAU: "closureTonneauLocked",
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_LOCK_STATE_MAP: Final[dict[int, str]] = {
|
|
106
|
+
body_pb2.LOCK_STATE_LOCKED: "locked",
|
|
107
|
+
body_pb2.LOCK_STATE_UNLOCKED: "unlocked",
|
|
108
|
+
body_pb2.LOCK_STATE_PARTIALLY_UNLOCKED: "partially_unlocked",
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
_TRAILER_PRESENCE_MAP: Final[dict[int, str]] = {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
112
|
+
body_pb2.TRAILER_NOT_PRESENT: "trailer_not_present",
|
|
113
|
+
body_pb2.TRAILER_PRESENT: "trailer_present",
|
|
114
|
+
body_pb2.TRAILER_PRESENT_WITH_BRAKES: "trailer_present_with_brakes",
|
|
115
|
+
body_pb2.TRAILER_INVALID: "trailer_invalid",
|
|
97
116
|
}
|
|
98
117
|
|
|
99
118
|
|
|
@@ -103,10 +122,11 @@ def decode_closures(m: body_pb2.ClosuresState) -> dict[str, Any]:
|
|
|
103
122
|
|
|
104
123
|
Fields:
|
|
105
124
|
doorFrontLeftClosed, closureFrunkClosed, etc.: str
|
|
106
|
-
("open" | "closed" | "opening" | "closing")
|
|
107
|
-
closureFrunkNextAction,
|
|
108
|
-
|
|
109
|
-
closureChargePortDoorNextAction
|
|
125
|
+
("open" | "closed" | "ajar" | "opening" | "closing")
|
|
126
|
+
closureFrunkNextAction, closureLiftgateNextAction,
|
|
127
|
+
closureTailgateNextAction, closureSideBinLeftNextAction,
|
|
128
|
+
closureSideBinRightNextAction, closureChargePortDoorNextAction,
|
|
129
|
+
windowsNextAction: str — e.g. "open_allowed" (shut),
|
|
110
130
|
"close_allowed" (open); for the charge port,
|
|
111
131
|
"close_not_available" means plugged in
|
|
112
132
|
|
|
@@ -122,7 +142,7 @@ def decode_closures(m: body_pb2.ClosuresState) -> dict[str, Any]:
|
|
|
122
142
|
result[_CLOSURE_MAP[cid]] = _enum(
|
|
123
143
|
_CLOSURE_STATE_MAP, state_val, what="closure state"
|
|
124
144
|
)
|
|
125
|
-
|
|
145
|
+
elif cid != body_pb2.GROUP_WINDOWS:
|
|
126
146
|
_LOGGER.debug("Unknown closure id %s (state %s)", cid, state_val)
|
|
127
147
|
if cid in _NEXT_ACTIONS:
|
|
128
148
|
field, key, names = _NEXT_ACTIONS[cid]
|
|
@@ -133,10 +153,12 @@ def decode_closures(m: body_pb2.ClosuresState) -> dict[str, Any]:
|
|
|
133
153
|
|
|
134
154
|
@RVMDecoder.register("body.locks.states", body_pb2.LocksState)
|
|
135
155
|
def decode_locks(m: body_pb2.LocksState) -> dict[str, Any]:
|
|
136
|
-
"""body.locks.states — lock state of every
|
|
156
|
+
"""body.locks.states — lock state of every lock.
|
|
137
157
|
|
|
138
158
|
Fields:
|
|
139
|
-
doorFrontLeftLocked, closureFrunkLocked,
|
|
159
|
+
doorFrontLeftLocked, closureFrunkLocked, gearGuardLocked (the Gear
|
|
160
|
+
Guard cable), etc.: str ("locked" | "unlocked" |
|
|
161
|
+
"partially_unlocked")
|
|
140
162
|
"""
|
|
141
163
|
result: dict[str, Any] = {}
|
|
142
164
|
for s in m.lock:
|
|
@@ -145,7 +167,9 @@ def decode_locks(m: body_pb2.LocksState) -> dict[str, Any]:
|
|
|
145
167
|
if state_val is None:
|
|
146
168
|
continue
|
|
147
169
|
if lid in _LOCK_MAP:
|
|
148
|
-
result[_LOCK_MAP[lid]] =
|
|
170
|
+
result[_LOCK_MAP[lid]] = _enum(
|
|
171
|
+
_LOCK_STATE_MAP, state_val, what="lock state"
|
|
172
|
+
)
|
|
149
173
|
else:
|
|
150
174
|
_LOGGER.debug("Unknown lock id %s (state %s)", lid, state_val)
|
|
151
175
|
return result
|
{rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/charging.py
RENAMED
|
@@ -8,13 +8,13 @@ from .core import RVMDecoder, _enum, _present
|
|
|
8
8
|
from .proto import charging_pb2
|
|
9
9
|
|
|
10
10
|
_DAY_OF_WEEK_MAP: Final[dict[int, str]] = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
charging_pb2.ScheduleTimeWindow.SUNDAY: "sunday",
|
|
12
|
+
charging_pb2.ScheduleTimeWindow.MONDAY: "monday",
|
|
13
|
+
charging_pb2.ScheduleTimeWindow.TUESDAY: "tuesday",
|
|
14
|
+
charging_pb2.ScheduleTimeWindow.WEDNESDAY: "wednesday",
|
|
15
|
+
charging_pb2.ScheduleTimeWindow.THURSDAY: "thursday",
|
|
16
|
+
charging_pb2.ScheduleTimeWindow.FRIDAY: "friday",
|
|
17
|
+
charging_pb2.ScheduleTimeWindow.SATURDAY: "saturday",
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
|
|
@@ -65,8 +65,8 @@ def decode_session_notification(m: charging_pb2.SessionNotification) -> dict[str
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
_REMOTE_COMMAND_MAP: Final[dict[int, str]] = {
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
charging_pb2.REMOTE_COMMAND_START: "start",
|
|
69
|
+
charging_pb2.REMOTE_COMMAND_STOP: "stop",
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
|
|
@@ -144,34 +144,34 @@ def decode_weighted_charging_forecast(
|
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
_CONNECTION_STATE_MAP: Final[dict[int, str]] = {
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
charging_pb2.CONNECTION_STATE_DISCONNECTED: "disconnected",
|
|
148
|
+
charging_pb2.CONNECTION_STATE_CONNECTED: "connected",
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
_CHARGING_STATE_MAP: Final[dict[int, str]] = {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
152
|
+
charging_pb2.CHARGING_READY: "charging_ready",
|
|
153
|
+
charging_pb2.CHARGING_CONNECTING: "charging_connecting",
|
|
154
|
+
charging_pb2.CHARGING_ACTIVE: "charging_active",
|
|
155
|
+
charging_pb2.CHARGING_COMPLETE: "charging_complete",
|
|
156
|
+
charging_pb2.CHARGING_SCHEDULED: "charging_scheduled",
|
|
157
|
+
charging_pb2.CHARGING_VEHICLE_ERROR: "charging_vehicle_error",
|
|
158
|
+
charging_pb2.CHARGING_STATION_ERROR: "charging_station_error",
|
|
159
|
+
charging_pb2.CHARGING_USER_STOPPED: "charging_stopped_by_user",
|
|
160
|
+
charging_pb2.CHARGING_STATION_STOPPED: "charging_stopped_by_station",
|
|
161
|
+
charging_pb2.CHARGING_PAYMENT_ERROR: "charging_payment_error",
|
|
162
|
+
charging_pb2.CHARGING_CERT_ERROR: "charging_cert_error",
|
|
163
|
+
charging_pb2.CHARGING_TLS_ERROR: "charging_tls_error",
|
|
164
|
+
charging_pb2.CHARGING_ERROR_AC_ADAPTER_USED_ON_DC: "charging_error_ac_adapter_used_on_dc",
|
|
165
|
+
charging_pb2.CHARGING_ERROR_DC_ADAPTER_USED_ON_AC: "charging_error_dc_adapter_used_on_ac",
|
|
166
|
+
charging_pb2.CHARGING_ERROR_INCOMPATIBLE_CHARGER: "charging_error_incompatible_charger",
|
|
167
|
+
charging_pb2.CHARGING_SD_COMPENSATION: "charging_sd_compensation",
|
|
168
|
+
charging_pb2.WAITING_ON_CHARGER: "waiting_on_charger",
|
|
169
|
+
charging_pb2.CHARGER_NOT_READY_OR_INCOMPATIBLE: "charging_error_not_ready_or_incompatible_charger",
|
|
170
|
+
charging_pb2.CHARGING_VEHICLE_STOPPED: "charging_vehicle_stopped",
|
|
171
|
+
charging_pb2.CHARGING_PAYMENT_ERROR_START_RIVIAN_APP: "charging_payment_error_start_rivian_app",
|
|
172
|
+
charging_pb2.CHARGING_TLS_ERROR_UNKNOWN_CHARGER: "charging_tls_error_unknown_charger",
|
|
173
|
+
charging_pb2.CHARGING_TLS_ERROR_UNEXPECTED_FAIL: "charging_tls_error_unexpected_fail",
|
|
174
|
+
charging_pb2.CHARGING_TLS_ERROR_START_RIVIAN_APP: "charging_tls_error_start_rivian_app",
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
|
|
@@ -210,17 +210,37 @@ def decode_time_estimation(m: charging_pb2.TimeEstimation) -> dict[str, Any]:
|
|
|
210
210
|
return {"timeToEndOfCharge": m.estimated_time_remaining}
|
|
211
211
|
|
|
212
212
|
|
|
213
|
+
_CHARGER_STATUS_MAP: Final[dict[int, str]] = {
|
|
214
|
+
charging_pb2.CHARGER_STATUS_NOT_CONNECTED: "chrgr_sts_not_connected",
|
|
215
|
+
charging_pb2.CHARGER_STATUS_CONNECTED_NO_CHARGE: "chrgr_sts_connected_no_chrg",
|
|
216
|
+
charging_pb2.CHARGER_STATUS_CONNECTED_CHARGING: "chrgr_sts_connected_charging",
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
213
220
|
@RVMDecoder.register("charging.energy.state", charging_pb2.EnergyState)
|
|
214
221
|
def decode_energy_state(m: charging_pb2.EnergyState) -> dict[str, Any]:
|
|
215
|
-
"""charging.energy.state —
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
222
|
+
"""charging.energy.state — charger connection status.
|
|
223
|
+
|
|
224
|
+
Fields:
|
|
225
|
+
chargerStatus: str — GraphQL chargerStatus values
|
|
226
|
+
("chrgr_sts_not_connected" | "chrgr_sts_connected_no_chrg" |
|
|
227
|
+
"chrgr_sts_connected_charging"); inferred
|
|
228
|
+
_field1, _field3, _field11: int — raw
|
|
229
|
+
"""
|
|
230
|
+
result: dict[str, Any] = {}
|
|
231
|
+
if (v := _present(m, "charger_status")) is not None:
|
|
232
|
+
result["chargerStatus"] = _enum(_CHARGER_STATUS_MAP, v, what="charger status")
|
|
233
|
+
for num in (1, 3, 11):
|
|
234
|
+
if (v := _present(m, f"field_{num}")) is not None:
|
|
235
|
+
result[f"_field{num}"] = v
|
|
236
|
+
return result
|
|
221
237
|
|
|
222
238
|
|
|
223
239
|
@RVMDecoder.register("charging.session.power", charging_pb2.SessionPower)
|
|
224
|
-
def decode_session_power(
|
|
225
|
-
"""charging.session.power —
|
|
226
|
-
|
|
240
|
+
def decode_session_power(m: charging_pb2.SessionPower) -> dict[str, Any]:
|
|
241
|
+
"""charging.session.power — live charging power, about every 5 seconds.
|
|
242
|
+
|
|
243
|
+
Fields:
|
|
244
|
+
power: float (kW; 0 when not charging)
|
|
245
|
+
"""
|
|
246
|
+
return {"power": round(m.power, 2)}
|
{rivian_python_client-2.2.0b0 → rivian_python_client-2.2.0b2}/src/rivian/parallax/comfort.py
RENAMED
|
@@ -34,60 +34,69 @@ def decode_user_modes_state(m: comfort_pb2.UserModesState) -> dict[str, Any]:
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
_CLIMATE_HOLD_AVAILABILITY_MAP: Final[dict[int, str]] = {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
comfort_pb2.CLIMATE_HOLD_AVAILABILITY_UNSPECIFIED: "unspecified",
|
|
38
|
+
comfort_pb2.CLIMATE_HOLD_AVAILABLE: "available",
|
|
39
|
+
comfort_pb2.CLIMATE_HOLD_CONTROLLABLE: "controllable",
|
|
40
|
+
comfort_pb2.CLIMATE_HOLD_UNAVAILABLE: "unavailable",
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
_CLIMATE_HOLD_STATUS_MAP: Final[dict[int, str]] = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
comfort_pb2.CLIMATE_HOLD_STATUS_UNSPECIFIED: "unspecified",
|
|
45
|
+
comfort_pb2.CLIMATE_HOLD_STATUS_UNAVAILABLE: "unavailable",
|
|
46
|
+
comfort_pb2.CLIMATE_HOLD_STATUS_OFF: "off",
|
|
47
|
+
comfort_pb2.CLIMATE_HOLD_STATUS_ON: "on",
|
|
48
|
+
comfort_pb2.CLIMATE_HOLD_STATUS_FAULT: "fault",
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
_CLIMATE_HOLD_UNAVAILABILITY_REASON_MAP: Final[dict[int, str]] = {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
comfort_pb2.CLIMATE_HOLD_UNAVAILABILITY_UNSPECIFIED: "unspecified",
|
|
53
|
+
comfort_pb2.CLIMATE_HOLD_UNAVAILABILITY_UNKNOWN: "unknown",
|
|
54
|
+
comfort_pb2.CLIMATE_HOLD_UNAVAILABILITY_LOW_SOC: "low_soc",
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
_PET_MODE_STATE_MAP: Final[dict[int, str]] = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
comfort_pb2.PET_MODE_OFF: "off",
|
|
59
|
+
comfort_pb2.PET_MODE_ON: "on",
|
|
60
|
+
comfort_pb2.PET_MODE_DISABLED: "disabled",
|
|
61
|
+
comfort_pb2.PET_MODE_FAULTY: "faulty",
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
_PET_MODE_TEMPERATURE_MAP: Final[dict[int, str]] = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
comfort_pb2.PET_MODE_TEMPERATURE_DEFAULT: "default",
|
|
66
|
+
comfort_pb2.PET_MODE_TEMPERATURE_COLD: "cold",
|
|
67
|
+
comfort_pb2.PET_MODE_TEMPERATURE_HOT: "hot",
|
|
68
|
+
comfort_pb2.PET_MODE_TEMPERATURE_FAULTY: "faulty",
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
# Seat keys use the GraphQL names: row 1 is "Front", row 2 "Rear", row 3
|
|
72
|
+
# "ThirdRow".
|
|
73
|
+
_CABIN_SURFACE_MAP: Final[dict[int, str]] = {
|
|
74
|
+
comfort_pb2.STEERING_WHEEL: "steeringWheel",
|
|
75
|
+
comfort_pb2.REAR_GLASS: "rearGlass",
|
|
76
|
+
comfort_pb2.FRONT_GLASS: "frontGlass",
|
|
77
|
+
comfort_pb2.SIDEVIEW_MIRRORS: "sideviewMirrors",
|
|
78
|
+
comfort_pb2.SEAT_ROW_1_LEFT: "seatFrontLeft",
|
|
79
|
+
comfort_pb2.SEAT_ROW_1_MIDDLE: "seatFrontMiddle",
|
|
80
|
+
comfort_pb2.SEAT_ROW_1_RIGHT: "seatFrontRight",
|
|
81
|
+
comfort_pb2.SEAT_ROW_2_LEFT: "seatRearLeft",
|
|
82
|
+
comfort_pb2.SEAT_ROW_2_MIDDLE: "seatRearMiddle",
|
|
83
|
+
comfort_pb2.SEAT_ROW_2_RIGHT: "seatRearRight",
|
|
84
|
+
comfort_pb2.SEAT_ROW_3_LEFT: "seatThirdRowLeft",
|
|
85
|
+
comfort_pb2.SEAT_ROW_3_MIDDLE: "seatThirdRowMiddle",
|
|
86
|
+
comfort_pb2.SEAT_ROW_3_RIGHT: "seatThirdRowRight",
|
|
87
|
+
comfort_pb2.WIPER_AREA: "wiperArea",
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
|
|
90
|
+
_CONDITIONING_LEVEL_MAP: Final[dict[int | None, str]] = {
|
|
82
91
|
None: "Off",
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
comfort_pb2.CONDITIONING_LEVEL_1: "Level_1",
|
|
93
|
+
comfort_pb2.CONDITIONING_LEVEL_2: "Level_2",
|
|
94
|
+
comfort_pb2.CONDITIONING_LEVEL_3: "Level_3",
|
|
86
95
|
}
|
|
87
96
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
_CONDITIONING_TYPE_MAP: Final[dict[int, str]] = {
|
|
98
|
+
comfort_pb2.CONDITIONING_HEAT: "Heat",
|
|
99
|
+
comfort_pb2.CONDITIONING_VENT: "Vent",
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
|
|
@@ -247,23 +256,23 @@ def decode_seat_conditioning(m: comfort_pb2.SeatConditioningStatus) -> dict[str,
|
|
|
247
256
|
seatThirdRowLeftHeat, seatThirdRowRightHeat: str
|
|
248
257
|
("Off" | "Level_1" | "Level_2" | "Level_3")
|
|
249
258
|
steeringWheelHeat: str ("Off" | "Level_1")
|
|
259
|
+
plus <surface>Heat/Vent for any other surface sent (middle seats,
|
|
260
|
+
rearGlass, frontGlass, sideviewMirrors, wiperArea)
|
|
250
261
|
|
|
251
262
|
Entries without a state are skipped.
|
|
252
263
|
"""
|
|
253
264
|
result: dict[str, Any] = {}
|
|
254
|
-
for
|
|
255
|
-
|
|
256
|
-
if (state_val := _present(
|
|
265
|
+
for surface in m.surface:
|
|
266
|
+
surface_id, hvac_type = surface.id, surface.type
|
|
267
|
+
if (state_val := _present(surface, "state")) is None:
|
|
257
268
|
continue
|
|
258
|
-
if
|
|
259
|
-
key =
|
|
260
|
-
|
|
261
|
-
)
|
|
262
|
-
result[key] = _SEAT_CONDITIONING_STATUS_MAP.get(state_val, state_val)
|
|
269
|
+
if surface_id in _CABIN_SURFACE_MAP and hvac_type in _CONDITIONING_TYPE_MAP:
|
|
270
|
+
key = f"{_CABIN_SURFACE_MAP[surface_id]}{_CONDITIONING_TYPE_MAP[hvac_type]}"
|
|
271
|
+
result[key] = _CONDITIONING_LEVEL_MAP.get(state_val, state_val)
|
|
263
272
|
else:
|
|
264
273
|
_LOGGER.debug(
|
|
265
|
-
"Unknown
|
|
266
|
-
|
|
274
|
+
"Unknown cabin surface %s (hvac_type %s; state %s)",
|
|
275
|
+
surface_id,
|
|
267
276
|
hvac_type,
|
|
268
277
|
state_val,
|
|
269
278
|
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Decoders for `device_table.*` RVM topics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import uuid
|
|
6
|
+
from typing import Any, Final
|
|
7
|
+
|
|
8
|
+
from .core import RVMDecoder, _enum, _present
|
|
9
|
+
from .proto import device_table_pb2
|
|
10
|
+
|
|
11
|
+
_Devices = device_table_pb2.VasKeyperDevices
|
|
12
|
+
_KEY_STATUS_MAP: Final[dict[int, str]] = {
|
|
13
|
+
_Devices.KEY_STATUS_ACTIVE: "active",
|
|
14
|
+
_Devices.KEY_STATUS_INACTIVE: "inactive",
|
|
15
|
+
_Devices.KEY_STATUS_WAITING_TO_PAIR: "waiting_to_pair",
|
|
16
|
+
_Devices.KEY_STATUS_PAIRING: "pairing",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_KEY_TYPE_MAP: Final[dict[int, str]] = {
|
|
20
|
+
_Devices.KEY_TYPE_PHONE: "phone",
|
|
21
|
+
_Devices.KEY_TYPE_KEY_CARD: "key_card",
|
|
22
|
+
_Devices.KEY_TYPE_KEY_FOB: "key_fob",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@RVMDecoder.register(
|
|
27
|
+
"device_table.vas_keyper.devices", device_table_pb2.VasKeyperDevices
|
|
28
|
+
)
|
|
29
|
+
def decode_vas_keyper_devices(m: device_table_pb2.VasKeyperDevices) -> dict[str, Any]:
|
|
30
|
+
"""device_table.vas_keyper.devices — a key (phone, key card or fob).
|
|
31
|
+
|
|
32
|
+
Covers every driver's keys. A deleted key isn't removed; it's resent
|
|
33
|
+
as inactive.
|
|
34
|
+
|
|
35
|
+
Fields (partial updates, so each only when sent):
|
|
36
|
+
deviceName: str — phone keys, e.g. the phone's name
|
|
37
|
+
keyType: str ("phone" | "key_card" | "key_fob"; key_fob inferred)
|
|
38
|
+
mappedIdentityId: str — the GraphQL device's `mappedIdentityId`
|
|
39
|
+
hrid: str — short human-readable id (key card)
|
|
40
|
+
profileId: str — the driver profile the key belongs to
|
|
41
|
+
publicKey: str — hex; phone keys
|
|
42
|
+
keyRevision: int — key table revision when the entry was last written
|
|
43
|
+
keyStatus: str ("active" | "inactive" | "waiting_to_pair" |
|
|
44
|
+
"pairing"); inactive covers unpaired, no longer paired and
|
|
45
|
+
deleted keys
|
|
46
|
+
infoC: int — 1 while active, 2147483647 while inactive, else the
|
|
47
|
+
pairing attempt number
|
|
48
|
+
infoA, infoB: int — unknown; always equal
|
|
49
|
+
deviceId: str — hex; for a key card, the GraphQL `devices[].id`
|
|
50
|
+
phoneId: str — the phone's UUID; phone keys
|
|
51
|
+
credentialHex: str — hex; likely key material
|
|
52
|
+
active: bool
|
|
53
|
+
"""
|
|
54
|
+
result: dict[str, Any] = {}
|
|
55
|
+
if m.HasField("label"):
|
|
56
|
+
if (v := _present(m.label, "name")) is not None:
|
|
57
|
+
result["deviceName"] = v
|
|
58
|
+
if (v := _present(m.label, "key_type")) is not None:
|
|
59
|
+
result["keyType"] = _enum(_KEY_TYPE_MAP, v, what="key type")
|
|
60
|
+
if m.HasField("device"):
|
|
61
|
+
for field, key in (
|
|
62
|
+
("mapped_identity_id", "mappedIdentityId"),
|
|
63
|
+
("hrid", "hrid"),
|
|
64
|
+
("profile_id", "profileId"),
|
|
65
|
+
("public_key", "publicKey"),
|
|
66
|
+
("revision", "keyRevision"),
|
|
67
|
+
):
|
|
68
|
+
if (v := _present(m.device, field)) is not None:
|
|
69
|
+
result[key] = v
|
|
70
|
+
|
|
71
|
+
if not m.HasField("credentials"):
|
|
72
|
+
return result
|
|
73
|
+
credentials = m.credentials
|
|
74
|
+
if credentials.HasField("info"):
|
|
75
|
+
for field, key in (
|
|
76
|
+
("a", "infoA"),
|
|
77
|
+
("c", "infoC"),
|
|
78
|
+
("b", "infoB"),
|
|
79
|
+
):
|
|
80
|
+
if (v := _present(credentials.info, field)) is not None:
|
|
81
|
+
result[key] = v
|
|
82
|
+
if (v := _present(credentials.info, "status")) is not None:
|
|
83
|
+
result["keyStatus"] = _enum(_KEY_STATUS_MAP, v, what="key status")
|
|
84
|
+
for field in ("card", "fob", "phone"):
|
|
85
|
+
if not credentials.HasField(field):
|
|
86
|
+
continue
|
|
87
|
+
material = getattr(credentials, field)
|
|
88
|
+
if (ident := _present(material, "id")) is not None:
|
|
89
|
+
if field == "phone" and len(ident) == 16:
|
|
90
|
+
result["phoneId"] = str(uuid.UUID(bytes=ident))
|
|
91
|
+
else:
|
|
92
|
+
result["deviceId"] = ident.hex()
|
|
93
|
+
if (cred := _present(material, "credential")) is not None:
|
|
94
|
+
result["credentialHex"] = cred.hex()
|
|
95
|
+
if (v := _present(credentials, "key_type")) is not None:
|
|
96
|
+
result["keyType"] = _enum(_KEY_TYPE_MAP, v, what="key type")
|
|
97
|
+
if (v := _present(credentials, "active")) is not None:
|
|
98
|
+
result["active"] = v
|
|
99
|
+
return result
|