rivian-python-client 1.0.4__tar.gz → 1.1.1__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-1.0.4 → rivian_python_client-1.1.1}/PKG-INFO +6 -2
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/pyproject.toml +10 -4
- rivian_python_client-1.1.1/src/rivian/ble.py +166 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/const.py +10 -1
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/rivian.py +3 -1
- rivian_python_client-1.1.1/src/rivian/schemas/charging.graphql +179 -0
- rivian_python_client-1.1.1/src/rivian/schemas/gateway.graphql +559 -0
- rivian_python_client-1.1.1/src/rivian/schemas/orders.graphql +254 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/utils.py +8 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/README.md +0 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/__init__.py +0 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/exceptions.py +0 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/py.typed +0 -0
- {rivian_python_client-1.0.4 → rivian_python_client-1.1.1}/src/rivian/ws_monitor.py +0 -0
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rivian-python-client
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Rivian API Client (Unofficial)
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Brian Retterer
|
|
7
7
|
Author-email: bretterer@gmail.com
|
|
8
|
-
Requires-Python: >=3.9,<
|
|
8
|
+
Requires-Python: >=3.9,<3.13
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.9
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Provides-Extra: ble
|
|
14
16
|
Requires-Dist: aiohttp (>=3.0.0)
|
|
15
17
|
Requires-Dist: backports-strenum (>=1.2.4,<2.0.0) ; python_version < "3.11"
|
|
18
|
+
Requires-Dist: bleak (>=0.21,<0.22) ; extra == "ble"
|
|
16
19
|
Requires-Dist: cryptography (>=41.0.1,<42.0.0)
|
|
20
|
+
Requires-Dist: dbus-fast (>=2.11.0,<3.0.0) ; (sys_platform == "linux") and (extra == "ble")
|
|
17
21
|
Description-Content-Type: text/markdown
|
|
18
22
|
|
|
19
23
|
# Python: Rivian API Client
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "rivian-python-client"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.1.1"
|
|
4
4
|
description = "Rivian API Client (Unofficial)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = ["Brian Retterer <bretterer@gmail.com>"]
|
|
@@ -10,19 +10,25 @@ packages = [
|
|
|
10
10
|
]
|
|
11
11
|
|
|
12
12
|
[tool.poetry.dependencies]
|
|
13
|
-
python = "
|
|
13
|
+
python = ">=3.9, <3.13"
|
|
14
14
|
aiohttp = ">=3.0.0"
|
|
15
15
|
cryptography = "^41.0.1"
|
|
16
16
|
backports-strenum = { version = "^1.2.4", python = "<3.11" }
|
|
17
|
+
bleak = { version = "^0.21", optional = true }
|
|
18
|
+
dbus-fast = {version = "^2.11.0", optional = true, platform = "linux"}
|
|
17
19
|
|
|
18
20
|
[tool.poetry.group.dev.dependencies]
|
|
19
21
|
pytest = "^7.1.2"
|
|
20
|
-
pytest-asyncio = "
|
|
22
|
+
pytest-asyncio = ">=0.18.3,<0.22.0"
|
|
21
23
|
python-dotenv = "^0.20.0"
|
|
22
24
|
aresponses = "^2.1.5"
|
|
25
|
+
mypy = "^1.7.0"
|
|
26
|
+
|
|
27
|
+
[tool.poetry.extras]
|
|
28
|
+
ble = ["bleak", "dbus-fast"]
|
|
23
29
|
|
|
24
30
|
[tool.poetry-dynamic-versioning]
|
|
25
|
-
enable =
|
|
31
|
+
enable = false
|
|
26
32
|
vcs = "git"
|
|
27
33
|
style = "semver"
|
|
28
34
|
pattern = "default-unprefixed"
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Rivian BLE handler."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
import logging
|
|
6
|
+
import platform
|
|
7
|
+
import secrets
|
|
8
|
+
|
|
9
|
+
from .utils import generate_ble_command_hmac
|
|
10
|
+
|
|
11
|
+
_LOGGER = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from bleak import BleakClient, BleakScanner, BLEDevice # type: ignore
|
|
15
|
+
except ImportError:
|
|
16
|
+
_LOGGER.error("Please install 'rivian-python-client[ble]' to use BLE features.")
|
|
17
|
+
raise
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
DEVICE_LOCAL_NAME = "Rivian Phone Key"
|
|
21
|
+
|
|
22
|
+
ACTIVE_ENTRY_CHARACTERISTIC_UUID = "5249565F-4D4F-424B-4559-5F5752495445"
|
|
23
|
+
PHONE_ID_VEHICLE_ID_UUID = "AA49565A-4D4F-424B-4559-5F5752495445"
|
|
24
|
+
PHONE_NONCE_VEHICLE_NONCE_UUID = "E020A15D-E730-4B2C-908B-51DAF9D41E19"
|
|
25
|
+
|
|
26
|
+
CONNECT_TIMEOUT = 10.0
|
|
27
|
+
NOTIFICATION_TIMEOUT = 3.0
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BleNotificationResponse:
|
|
31
|
+
"""BLE notification response helper."""
|
|
32
|
+
|
|
33
|
+
def __init__(self) -> None:
|
|
34
|
+
"""Initialize the BLE notification response helper."""
|
|
35
|
+
self.data: bytes | None = None
|
|
36
|
+
self.event = asyncio.Event()
|
|
37
|
+
|
|
38
|
+
def notification_handler(self, _, notification_data: bytearray) -> None:
|
|
39
|
+
"""Notification handler."""
|
|
40
|
+
self.data = notification_data
|
|
41
|
+
self.event.set()
|
|
42
|
+
|
|
43
|
+
async def wait(self, timeout: float | None = NOTIFICATION_TIMEOUT) -> bool:
|
|
44
|
+
"""Wait for the notification response."""
|
|
45
|
+
return await asyncio.wait_for(self.event.wait(), timeout)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def create_notification_handler(
|
|
49
|
+
client: BleakClient, char_specifier: str
|
|
50
|
+
) -> BleNotificationResponse:
|
|
51
|
+
"""Create a notification handler."""
|
|
52
|
+
response = BleNotificationResponse()
|
|
53
|
+
await client.start_notify(char_specifier, response.notification_handler)
|
|
54
|
+
return response
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def pair_phone(
|
|
58
|
+
device: BLEDevice,
|
|
59
|
+
phone_id: str,
|
|
60
|
+
vas_vehicle_id: str,
|
|
61
|
+
vehicle_key: str,
|
|
62
|
+
private_key: str,
|
|
63
|
+
) -> bool:
|
|
64
|
+
"""Pair a phone locally via BLE.
|
|
65
|
+
|
|
66
|
+
The phone must first be enrolled via `rivian.enroll_phone`.
|
|
67
|
+
This finishes the process to enable cloud and local vehicle control.
|
|
68
|
+
"""
|
|
69
|
+
_LOGGER.debug("Connecting to %s", device)
|
|
70
|
+
try:
|
|
71
|
+
async with BleakClient(device, timeout=CONNECT_TIMEOUT) as client:
|
|
72
|
+
_LOGGER.debug("Connected to %s", device)
|
|
73
|
+
vehicle_id_handler = await create_notification_handler(
|
|
74
|
+
client, PHONE_ID_VEHICLE_ID_UUID
|
|
75
|
+
)
|
|
76
|
+
nonce_handler = await create_notification_handler(
|
|
77
|
+
client, PHONE_NONCE_VEHICLE_NONCE_UUID
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
_LOGGER.debug("Validating id")
|
|
81
|
+
await client.write_gatt_char(
|
|
82
|
+
PHONE_ID_VEHICLE_ID_UUID, bytes.fromhex(phone_id.replace("-", ""))
|
|
83
|
+
)
|
|
84
|
+
await vehicle_id_handler.wait()
|
|
85
|
+
|
|
86
|
+
assert vehicle_id_handler.data
|
|
87
|
+
vehicle_id_response = vehicle_id_handler.data.hex()
|
|
88
|
+
if vehicle_id_response != vas_vehicle_id.replace("-", ""):
|
|
89
|
+
_LOGGER.debug(
|
|
90
|
+
"Incorrect vehicle id: received %s, expected %s",
|
|
91
|
+
vehicle_id_response,
|
|
92
|
+
vas_vehicle_id,
|
|
93
|
+
)
|
|
94
|
+
return False
|
|
95
|
+
|
|
96
|
+
_LOGGER.debug("Exchanging nonce")
|
|
97
|
+
phone_nonce = secrets.token_bytes(16)
|
|
98
|
+
hmac = generate_ble_command_hmac(phone_nonce, vehicle_key, private_key)
|
|
99
|
+
await client.write_gatt_char(
|
|
100
|
+
PHONE_NONCE_VEHICLE_NONCE_UUID, phone_nonce + hmac
|
|
101
|
+
)
|
|
102
|
+
await nonce_handler.wait()
|
|
103
|
+
|
|
104
|
+
# Vehicle is authenticated, trigger bonding
|
|
105
|
+
_LOGGER.debug("Attempting to pair")
|
|
106
|
+
if platform.system() == "Darwin":
|
|
107
|
+
# Mac BLE API doesn't have an explicit way to trigger bonding
|
|
108
|
+
# Instead, enable notification on protected characteristic to trigger bonding manually
|
|
109
|
+
await client.start_notify(
|
|
110
|
+
ACTIVE_ENTRY_CHARACTERISTIC_UUID, lambda _, __: None
|
|
111
|
+
)
|
|
112
|
+
else:
|
|
113
|
+
await client.pair()
|
|
114
|
+
|
|
115
|
+
_LOGGER.debug("Successfully paired with %s", device)
|
|
116
|
+
return True
|
|
117
|
+
except Exception as ex: # pylint: disable=broad-except
|
|
118
|
+
_LOGGER.debug(
|
|
119
|
+
"Couldn't connect to %s. "
|
|
120
|
+
'Make sure you are in the correct vehicle and have selected "Set Up" for the appropriate key and try again'
|
|
121
|
+
"%s",
|
|
122
|
+
device,
|
|
123
|
+
("" if isinstance(ex, asyncio.TimeoutError) else f": {ex}"),
|
|
124
|
+
)
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
async def find_phone_key() -> BLEDevice | None:
|
|
129
|
+
"""Find phone key."""
|
|
130
|
+
async with BleakScanner() as scanner:
|
|
131
|
+
return await scanner.find_device_by_name(DEVICE_LOCAL_NAME)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
async def set_bluez_pairable(device: BLEDevice) -> bool:
|
|
135
|
+
"""Set bluez to pairable on Linux systems."""
|
|
136
|
+
if (_os := platform.system()) != "Linux":
|
|
137
|
+
raise OSError(f"BlueZ is not available on {_os}-based systems")
|
|
138
|
+
|
|
139
|
+
# pylint: disable=import-error, import-outside-toplevel
|
|
140
|
+
from dbus_fast import BusType # type: ignore
|
|
141
|
+
from dbus_fast.aio import MessageBus # type: ignore
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
path = device.details["props"]["Adapter"]
|
|
145
|
+
except Exception: # pylint: disable=broad-except
|
|
146
|
+
path = "/org/bluez/hci0"
|
|
147
|
+
_LOGGER.warning(
|
|
148
|
+
"Couldn't determine BT controller path, defaulting to %s: %s",
|
|
149
|
+
path,
|
|
150
|
+
device.details,
|
|
151
|
+
exc_info=True,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
|
|
156
|
+
introspection = await bus.introspect("org.bluez", path)
|
|
157
|
+
pobject = bus.get_proxy_object("org.bluez", path, introspection)
|
|
158
|
+
iface = pobject.get_interface("org.bluez.Adapter1")
|
|
159
|
+
if not await iface.get_pairable():
|
|
160
|
+
await iface.set_pairable(True)
|
|
161
|
+
bus.disconnect()
|
|
162
|
+
except Exception as ex: # pylint: disable=broad-except
|
|
163
|
+
_LOGGER.error(ex)
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
return True
|
|
@@ -36,9 +36,9 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
36
36
|
"gnssLocation",
|
|
37
37
|
# TimeStamped(String|Float|Int)
|
|
38
38
|
"alarmSoundStatus",
|
|
39
|
+
"batteryCapacity",
|
|
39
40
|
"batteryHvThermalEvent",
|
|
40
41
|
"batteryHvThermalEventPropagation",
|
|
41
|
-
"batteryCapacity",
|
|
42
42
|
"batteryLevel",
|
|
43
43
|
"batteryLimit",
|
|
44
44
|
"brakeFluidLow",
|
|
@@ -46,6 +46,7 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
46
46
|
"cabinClimateInteriorTemperature",
|
|
47
47
|
"cabinPreconditioningStatus",
|
|
48
48
|
"cabinPreconditioningType",
|
|
49
|
+
"carWashMode",
|
|
49
50
|
"chargerDerateStatus",
|
|
50
51
|
"chargerState",
|
|
51
52
|
"chargerStatus",
|
|
@@ -57,12 +58,16 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
57
58
|
"closureLiftgateNextAction",
|
|
58
59
|
"closureSideBinLeftClosed",
|
|
59
60
|
"closureSideBinLeftLocked",
|
|
61
|
+
"closureSideBinLeftNextAction",
|
|
60
62
|
"closureSideBinRightClosed",
|
|
61
63
|
"closureSideBinRightLocked",
|
|
64
|
+
"closureSideBinRightNextAction",
|
|
62
65
|
"closureTailgateClosed",
|
|
63
66
|
"closureTailgateLocked",
|
|
67
|
+
"closureTailgateNextAction",
|
|
64
68
|
"closureTonneauClosed",
|
|
65
69
|
"closureTonneauLocked",
|
|
70
|
+
"closureTonneauNextAction",
|
|
66
71
|
"defrostDefogStatus",
|
|
67
72
|
"distanceToEmpty",
|
|
68
73
|
"doorFrontLeftClosed",
|
|
@@ -79,6 +84,7 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
79
84
|
"gearGuardVideoStatus",
|
|
80
85
|
"gearGuardVideoTermsAccepted",
|
|
81
86
|
"gearStatus",
|
|
87
|
+
"gnssAltitude",
|
|
82
88
|
"gnssBearing",
|
|
83
89
|
"gnssSpeed",
|
|
84
90
|
"otaAvailableVersion",
|
|
@@ -123,6 +129,8 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
123
129
|
"tirePressureStatusValidFrontRight",
|
|
124
130
|
"tirePressureStatusValidRearLeft",
|
|
125
131
|
"tirePressureStatusValidRearRight",
|
|
132
|
+
"trailerStatus",
|
|
133
|
+
"twelveVoltBatteryHealth",
|
|
126
134
|
"vehicleMileage",
|
|
127
135
|
"windowFrontLeftCalibrated",
|
|
128
136
|
"windowFrontLeftClosed",
|
|
@@ -132,6 +140,7 @@ VEHICLE_STATE_PROPERTIES: Final[set[str]] = {
|
|
|
132
140
|
"windowRearLeftClosed",
|
|
133
141
|
"windowRearRightCalibrated",
|
|
134
142
|
"windowRearRightClosed",
|
|
143
|
+
"windowsNextAction",
|
|
135
144
|
"wiperFluidState",
|
|
136
145
|
}
|
|
137
146
|
|
|
@@ -248,10 +248,12 @@ class Rivian:
|
|
|
248
248
|
device_name: str,
|
|
249
249
|
public_key: str,
|
|
250
250
|
) -> bool:
|
|
251
|
-
"""
|
|
251
|
+
"""Enroll a phone.
|
|
252
252
|
|
|
253
253
|
To generate a public/private key for enrollment, use the `utils.generate_key_pair` function.
|
|
254
254
|
The private key will need to be retained to sign commands sent via the `send_vehicle_command` method.
|
|
255
|
+
To enable vehicle control, the phone will then also need to be paired locally via BLE,
|
|
256
|
+
which can be done via `ble.pair_phone`.
|
|
255
257
|
"""
|
|
256
258
|
url = GRAPHQL_GATEWAY
|
|
257
259
|
headers = BASE_HEADERS | {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
type Query {
|
|
2
|
+
chargepoint: ChargepointQuery
|
|
3
|
+
getCompletedSessionSummaries($vehicleId: String): [ChargingSessionSummary]
|
|
4
|
+
getLiveSessionData(vehicleId: ID!): LiveSessionData
|
|
5
|
+
getLiveSessionHistory(vehicleId: ID!): LiveSessionHistory
|
|
6
|
+
getNonRivianUserSession: NonRivianUserSessionData
|
|
7
|
+
getRegisteredWallboxes: [WallboxRecord]
|
|
8
|
+
getSessionHistory(
|
|
9
|
+
userId: ID!
|
|
10
|
+
startDate: String!
|
|
11
|
+
endDate: String!
|
|
12
|
+
): [SessionHistorySummary]
|
|
13
|
+
getWallboxStatus(wallboxId: String!): WallboxRecord
|
|
14
|
+
getWallChargerHistory(
|
|
15
|
+
serialNumber: String!
|
|
16
|
+
startDate: String
|
|
17
|
+
endDate: String
|
|
18
|
+
): [SessionSummary]
|
|
19
|
+
payment: PaymentQuery
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type Mutation {
|
|
23
|
+
updateWallbox(
|
|
24
|
+
wallboxId: String!
|
|
25
|
+
wifiId: String
|
|
26
|
+
name: String
|
|
27
|
+
latitude: String
|
|
28
|
+
longitude: String
|
|
29
|
+
): WallboxRecord
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type Card {
|
|
33
|
+
brand: String!
|
|
34
|
+
lastFour: String!
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type ChargepointQuery {
|
|
38
|
+
checkByRivianId: Boolean!
|
|
39
|
+
getLinkedEmailForRivianId: GetLinkedEmailForRivianIdResponse!
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type ChargingSessionSummary {
|
|
43
|
+
chargerType: String
|
|
44
|
+
currencyCode: String
|
|
45
|
+
paidTotal: Float
|
|
46
|
+
startInstant: String!
|
|
47
|
+
endInstant: String!
|
|
48
|
+
totalEnergyKwh: Float!
|
|
49
|
+
rangeAddedKm: Float
|
|
50
|
+
city: String
|
|
51
|
+
transactionId: String!
|
|
52
|
+
vehicleId: String
|
|
53
|
+
vehicleName: String
|
|
54
|
+
vendor: String
|
|
55
|
+
isRoamingNetwork: Boolean
|
|
56
|
+
isPublic: Boolean
|
|
57
|
+
isHomeCharger: Boolean
|
|
58
|
+
meta: ChargingSessionSummaryMeta!
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type ChargingSessionSummaryMeta {
|
|
62
|
+
transactionIdGroupingKey: String!
|
|
63
|
+
dataSources: [String!]!
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type FloatValueRecord {
|
|
67
|
+
value: Float!
|
|
68
|
+
updatedAt: String!
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
type GetLinkedEmailForRivianIdResponse {
|
|
72
|
+
email: String!
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
type LiveSessionData {
|
|
76
|
+
chargerId: String
|
|
77
|
+
current: FloatValueRecord
|
|
78
|
+
currentCurrency: String
|
|
79
|
+
currentMiles: FloatValueRecord
|
|
80
|
+
currentPrice: Float
|
|
81
|
+
isFreeSession: Boolean
|
|
82
|
+
isRivianCharger: Boolean
|
|
83
|
+
kilometersChargedPerHour: FloatValueRecord
|
|
84
|
+
locationId: String
|
|
85
|
+
power: FloatValueRecord
|
|
86
|
+
rangeAddedThisSession: FloatValueRecord
|
|
87
|
+
soc: FloatValueRecord
|
|
88
|
+
startTime: String
|
|
89
|
+
timeElapsed: Float
|
|
90
|
+
timeRemaining: StringValueRecord
|
|
91
|
+
totalChargedEnergy: FloatValueRecord
|
|
92
|
+
vehicleChargerState: StringValueRecord
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
type LiveSessionHistory {
|
|
96
|
+
chartData: [FloatValueRecord]
|
|
97
|
+
startTime: Float
|
|
98
|
+
vehicleId: String
|
|
99
|
+
chargerId: String
|
|
100
|
+
transactionId: String
|
|
101
|
+
current: FloatValueRecord
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
type NonRivianUserSessionData {
|
|
105
|
+
chargerId: String
|
|
106
|
+
transactionId: String
|
|
107
|
+
isRivianCharger: Boolean!
|
|
108
|
+
vehicleChargerState: StringValueRecord
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
type PaymentMethod {
|
|
112
|
+
default: Boolean!
|
|
113
|
+
card: Card
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
type PaymentQuery {
|
|
117
|
+
getPaymentMethods: [PaymentMethod!]!
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
type SessionHistorySummary {
|
|
121
|
+
transactionId: String!
|
|
122
|
+
locationId: String!
|
|
123
|
+
vehicleId: String
|
|
124
|
+
startDateTime: String!
|
|
125
|
+
endDateTime: String!
|
|
126
|
+
currency: String!
|
|
127
|
+
cost: Float!
|
|
128
|
+
paidTotal: Float!
|
|
129
|
+
energyOffered: Float!
|
|
130
|
+
energyUnits: String
|
|
131
|
+
rangeAdded: Float
|
|
132
|
+
rangeUnits: String
|
|
133
|
+
vendor: String!
|
|
134
|
+
chargerType: String!
|
|
135
|
+
chargerName: String!
|
|
136
|
+
address: String!
|
|
137
|
+
city: String!
|
|
138
|
+
country: String!
|
|
139
|
+
postalCode: string!
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
type SessionSummary {
|
|
143
|
+
transactionId: String
|
|
144
|
+
vehicleInfo: VehicleInfo
|
|
145
|
+
startDateTime: String!
|
|
146
|
+
endDateTime: String!
|
|
147
|
+
totalEnergyKwh: Float!
|
|
148
|
+
rangeAddedKm: Float
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
type StringValueRecord {
|
|
152
|
+
value: String!
|
|
153
|
+
updatedAt: String!
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
type VehicleInfo {
|
|
157
|
+
name: String
|
|
158
|
+
vin: String
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
type WallboxRecord {
|
|
162
|
+
wallboxId: String!
|
|
163
|
+
userId: String!
|
|
164
|
+
wifiId: String!
|
|
165
|
+
name: String!
|
|
166
|
+
linked: Boolean!
|
|
167
|
+
latitude: String!
|
|
168
|
+
longitude: String!
|
|
169
|
+
chargingStatus: String!
|
|
170
|
+
power: String
|
|
171
|
+
currentVoltage: String
|
|
172
|
+
currentAmps: String
|
|
173
|
+
softwareVersion: String!
|
|
174
|
+
model: String!
|
|
175
|
+
serialNumber: String!
|
|
176
|
+
maxPower: String!
|
|
177
|
+
maxVoltage: String!
|
|
178
|
+
maxAmps: String
|
|
179
|
+
}
|
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
type Query {
|
|
2
|
+
currentUser: User
|
|
3
|
+
delivery(orderId: ID!): Delivery
|
|
4
|
+
getVehicle(id: String!): Vehicle
|
|
5
|
+
getVehicleCommand(id: String!): GetVehicleCommandState
|
|
6
|
+
getVehicleMobileImages(
|
|
7
|
+
resolution: String
|
|
8
|
+
extension: String
|
|
9
|
+
version: String
|
|
10
|
+
): VehicleMobileImage
|
|
11
|
+
getVehicleOrderMobileImages(
|
|
12
|
+
resolution: String
|
|
13
|
+
extension: String
|
|
14
|
+
version: String
|
|
15
|
+
): VehicleMobileImage
|
|
16
|
+
planTrip(
|
|
17
|
+
origin: CoordinatesInput!
|
|
18
|
+
destination: CoordinatesInput!
|
|
19
|
+
bearing: Float!
|
|
20
|
+
vehicleId: String!
|
|
21
|
+
startingSoc: Float!
|
|
22
|
+
startingRangeMeters: Float!
|
|
23
|
+
targetArrivalSocPercent: Float
|
|
24
|
+
networkPreferences: [NetworkPreference!]
|
|
25
|
+
): PlanTripResponse
|
|
26
|
+
vehicleState(id: String!): VehicleState
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Mutation {
|
|
30
|
+
createCsrfToken: CreateCsrfTokenResponse
|
|
31
|
+
disenrollPhone(attrs: DisenrollPhoneAttributes!): DisenrollPhoneResponse
|
|
32
|
+
enrollPhone(attrs: EnrollPhoneAttributes!): EnrollPhoneResponse
|
|
33
|
+
login(email: String!, password: String!): LoginResponse
|
|
34
|
+
loginWithOTP(
|
|
35
|
+
email: String!
|
|
36
|
+
otpToken: String!
|
|
37
|
+
otpCode: String!
|
|
38
|
+
): MobileLoginResponse
|
|
39
|
+
sendVehicleCommand(attrs: VehicleCommandAttributes!): SendVehicleCommandState
|
|
40
|
+
setChargingSchedules(
|
|
41
|
+
vehicleId: String!
|
|
42
|
+
chargingSchedules: [InputChargingSchedule!]!
|
|
43
|
+
): OK
|
|
44
|
+
setVehicleName(vehicleId: String!, name: String!): OK
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type Subscription {
|
|
48
|
+
vehicleState(id: String!): VehicleState
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
input CoordinatesInput {
|
|
52
|
+
latitude: Float!
|
|
53
|
+
longitude: Float!
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
input DisenrollPhoneAttributes {
|
|
57
|
+
enrollmentId: String!
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
input EnrollPhoneAttributes {
|
|
61
|
+
userId: String!
|
|
62
|
+
vehicleId: String!
|
|
63
|
+
publicKey: String!
|
|
64
|
+
type: String!
|
|
65
|
+
name: String
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
input InputChargingSchedule {
|
|
69
|
+
weekDays: [String!]!
|
|
70
|
+
startTime: Int!
|
|
71
|
+
duration: Int!
|
|
72
|
+
location: CoordinatesInput!
|
|
73
|
+
amperage: Int!
|
|
74
|
+
enabled: Boolean!
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
input NetworkPreference {
|
|
78
|
+
networkId: String!
|
|
79
|
+
preference: Float
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
input VehicleCommandAttributes {
|
|
83
|
+
command: String!
|
|
84
|
+
hmac: String!
|
|
85
|
+
timestamp: String!
|
|
86
|
+
vasPhoneId: String!
|
|
87
|
+
deviceId: String!
|
|
88
|
+
vehicleId: String!
|
|
89
|
+
params: VehicleCommandParameters
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
input VehicleCommandParameters {
|
|
93
|
+
level: Int
|
|
94
|
+
HVAC_set_temp: Float
|
|
95
|
+
SOC_limit: Int
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface TimeStamped {
|
|
99
|
+
timeStamp: String!
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type CampSpeaker {
|
|
103
|
+
id: String!
|
|
104
|
+
serialNumber: String!
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type ChargingSchedule {
|
|
108
|
+
startTime: Int!
|
|
109
|
+
duration: Int!
|
|
110
|
+
location: GeoCoordinates!
|
|
111
|
+
amperage: Int!
|
|
112
|
+
enabled: Boolean!
|
|
113
|
+
weekDays: [String!]!
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
type CreateCsrfTokenResponse {
|
|
117
|
+
csrfToken: String!
|
|
118
|
+
appSessionToken: String!
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
type Delivery {
|
|
122
|
+
status: String!
|
|
123
|
+
carrier: String!
|
|
124
|
+
deliveryAddress: DeliveryAddressDetails!
|
|
125
|
+
appointmentDetails: DeliveryAppointment!
|
|
126
|
+
vehicleVIN: String!
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
type DeliveryAddressDetails {
|
|
130
|
+
addressLine1: String!
|
|
131
|
+
addressLine2: String
|
|
132
|
+
city: String!
|
|
133
|
+
state: String!
|
|
134
|
+
country: String!
|
|
135
|
+
zipcode: String!
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type DeliveryAppointment {
|
|
139
|
+
appointmentId: String!
|
|
140
|
+
startDateTime: String!
|
|
141
|
+
endDateTime: String!
|
|
142
|
+
timeZone: String!
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
type DisenrollPhoneResponse {
|
|
146
|
+
success: Boolean!
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type EnrollPhoneResponse {
|
|
150
|
+
success: Boolean!
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
type GeoCoordinates {
|
|
154
|
+
latitude: Float!
|
|
155
|
+
longitude: Float!
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
type GetVehicleCommandState {
|
|
159
|
+
id: String!
|
|
160
|
+
command: String!
|
|
161
|
+
createdAt: String!
|
|
162
|
+
state: Int!
|
|
163
|
+
responseCode: Int
|
|
164
|
+
statusCode: Int
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
type MobileLoginResponse {
|
|
168
|
+
accessToken: String!
|
|
169
|
+
refreshToken: String!
|
|
170
|
+
userSessionToken: String!
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
type MobileMFALoginResponse {
|
|
174
|
+
otpToken: String!
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
type NameSetting {
|
|
178
|
+
value: String!
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
type OK {
|
|
182
|
+
success: Boolean!
|
|
183
|
+
value: String
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
type OTAUpdateDetails {
|
|
187
|
+
url: String!
|
|
188
|
+
version: String!
|
|
189
|
+
locale: String!
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
type PlanTripResponse {
|
|
193
|
+
routes: [Route!]!
|
|
194
|
+
tripPlanStatus: String!
|
|
195
|
+
chargeStationsAvailable: Boolean!
|
|
196
|
+
socBelowLimit: Boolean!
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
type ProvisionedUser {
|
|
200
|
+
firstName: String!
|
|
201
|
+
lastName: String!
|
|
202
|
+
email: String!
|
|
203
|
+
userId: String!
|
|
204
|
+
roles: [String!]!
|
|
205
|
+
devices: [ProvisionedUserDevice!]!
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
type ProvisionedUserDevice {
|
|
209
|
+
type: String!
|
|
210
|
+
mappedIdentityId: String!
|
|
211
|
+
id: String!
|
|
212
|
+
hrid: String
|
|
213
|
+
deviceName: String!
|
|
214
|
+
isPaired: Boolean!
|
|
215
|
+
isEnabled: Boolean!
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
type RegistrationChannel {
|
|
219
|
+
type: String!
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
type Route {
|
|
223
|
+
routeResponse: String!
|
|
224
|
+
destinationReached: Boolean!
|
|
225
|
+
totalChargingDuration: Int!
|
|
226
|
+
arrivalSOC: Int!
|
|
227
|
+
arrivalReachableDistance: Float!
|
|
228
|
+
waypoints: [WayPoint!]!
|
|
229
|
+
energyConsumptionOnLeg: Float
|
|
230
|
+
batteryEmptyToDestinationDistance: Float
|
|
231
|
+
batteryEmptyLocationLatitude: Float
|
|
232
|
+
batteryEmptyLocationLongitude: Float
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
type SendVehicleCommandState {
|
|
236
|
+
id: String!
|
|
237
|
+
command: String!
|
|
238
|
+
state: Int!
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
type SupportedFeature {
|
|
242
|
+
name: String!
|
|
243
|
+
status: String!
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
type TimeStampedFloat implements TimeStamped {
|
|
247
|
+
timeStamp: String!
|
|
248
|
+
value: Float!
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
type TimeStampedNullableFloat implements TimeStamped {
|
|
252
|
+
timeStamp: String!
|
|
253
|
+
value: Float
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
type TimeStampedInt implements TimeStamped {
|
|
257
|
+
timeStamp: String!
|
|
258
|
+
value: Int!
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
type TimeStampedString implements TimeStamped {
|
|
262
|
+
timeStamp: String!
|
|
263
|
+
value: String!
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
type UnprovisionedUser {
|
|
267
|
+
email: String!
|
|
268
|
+
inviteId: String!
|
|
269
|
+
status: String!
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type User {
|
|
273
|
+
id: String!
|
|
274
|
+
firstName: String!
|
|
275
|
+
lastName: String!
|
|
276
|
+
email: String!
|
|
277
|
+
address: UserAddress!
|
|
278
|
+
enrolledPhones: [UserEnrolledPhone]!
|
|
279
|
+
pendingInvites: [UserInvitation!]!
|
|
280
|
+
phones: [UserPhone!]!
|
|
281
|
+
registrationChannels: [RegistrationChannel!]!
|
|
282
|
+
vehicles: [UserVehicle!]!
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
type UserAddress {
|
|
286
|
+
country: String!
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
type UserEnrolledPhone {
|
|
290
|
+
vas: UserEnrolledPhoneAccess!
|
|
291
|
+
enrolled: [UserEnrolledPhoneEntry!]!
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
type UserEnrolledPhoneAccess {
|
|
295
|
+
vasPhoneId: String!
|
|
296
|
+
publicKey: String!
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
type UserEnrolledPhoneEntry {
|
|
300
|
+
deviceType: String!
|
|
301
|
+
deviceName: String!
|
|
302
|
+
vehicleId: String!
|
|
303
|
+
identityId: String!
|
|
304
|
+
shortName: String!
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
type UserInvitation {
|
|
308
|
+
id: String!
|
|
309
|
+
invitedByFirstName: String
|
|
310
|
+
role: String
|
|
311
|
+
status: String
|
|
312
|
+
vehicleId: String
|
|
313
|
+
vehicleModel: String
|
|
314
|
+
email: String
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
type UserPhone {
|
|
318
|
+
countryCode: String!
|
|
319
|
+
formatted: String!
|
|
320
|
+
phone: String!
|
|
321
|
+
national: String!
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
type UserVehicle {
|
|
325
|
+
id: String!
|
|
326
|
+
vin: String!
|
|
327
|
+
name: String!
|
|
328
|
+
owner: String
|
|
329
|
+
state: String
|
|
330
|
+
createdAt: String!
|
|
331
|
+
updatedAt: String
|
|
332
|
+
vas: UserVehicleAccess!
|
|
333
|
+
vehicle: Vehicle!
|
|
334
|
+
roles: [String!]!
|
|
335
|
+
connectedProducts: [ConnectedProduct!]!
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
type UserVehicleAccess {
|
|
339
|
+
vasVehicleId: String!
|
|
340
|
+
vehiclePublicKey: String!
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
type UserVehicleSettingsMap {
|
|
344
|
+
name: NameSetting!
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
type Vehicle {
|
|
348
|
+
id: String!
|
|
349
|
+
vin: String!
|
|
350
|
+
make: String!
|
|
351
|
+
model: String!
|
|
352
|
+
modelYear: Int!
|
|
353
|
+
expectedBuildDate: String
|
|
354
|
+
plannedBuildDate: String
|
|
355
|
+
expectedGeneralAssemblyStartDate: String
|
|
356
|
+
actualGeneralAssemblyDate: String
|
|
357
|
+
otaEarlyAccessStatus: Boolean!
|
|
358
|
+
currentOTAUpdateDetails: OTAUpdateDetails!
|
|
359
|
+
availableOTAUpdateDetails: OTAUpdateDetails
|
|
360
|
+
mobileConfiguration: VehicleMobileConfiguration!
|
|
361
|
+
settings: UserVehicleSettingsMap!
|
|
362
|
+
vehicleState: VehicleState!
|
|
363
|
+
invitedUsers: [InvitedUser!]!
|
|
364
|
+
chargingSchedules: [ChargingSchedule!]!
|
|
365
|
+
estimatedRange(startSoc: Float!): Float!
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
type VehicleCloudConnection {
|
|
369
|
+
lastSync: String!
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
type VehicleLocation implements TimeStamped {
|
|
373
|
+
timeStamp: String!
|
|
374
|
+
latitude: Float!
|
|
375
|
+
longitude: Float!
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
type VehicleMobileConfiguration {
|
|
379
|
+
trimOption: VehicleMobileConfigurationOption!
|
|
380
|
+
driveSystemOption: VehicleMobileConfigurationOption!
|
|
381
|
+
exteriorColorOption: VehicleMobileConfigurationOption!
|
|
382
|
+
interiorColorOption: VehicleMobileConfigurationOption!
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
type VehicleMobileConfigurationOption {
|
|
386
|
+
optionId: String!
|
|
387
|
+
optionName: String!
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
type VehicleMobileImage {
|
|
391
|
+
orderId: String
|
|
392
|
+
vehicleId: String
|
|
393
|
+
design: String!
|
|
394
|
+
extension: String!
|
|
395
|
+
placement: String!
|
|
396
|
+
resolution: String!
|
|
397
|
+
size: String!
|
|
398
|
+
url: String!
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
type VehicleState {
|
|
402
|
+
alarmSoundStatus: TimeStampedString
|
|
403
|
+
|
|
404
|
+
batteryCapacity: TimeStampedFloat
|
|
405
|
+
batteryHvThermalEvent: TimeStampedString
|
|
406
|
+
batteryHvThermalEventPropagation: TimeStampedString
|
|
407
|
+
batteryLevel: TimeStampedFloat
|
|
408
|
+
batteryLimit: TimeStampedInt
|
|
409
|
+
|
|
410
|
+
brakeFluidLow: TimeStampedString
|
|
411
|
+
|
|
412
|
+
cabinClimateDriverTemperature: TimeStampedFloat
|
|
413
|
+
cabinClimateInteriorTemperature: TimeStampedFloat
|
|
414
|
+
cabinPreconditioningStatus: TimeStampedString
|
|
415
|
+
cabinPreconditioningType: TimeStampedString
|
|
416
|
+
|
|
417
|
+
carWashMode: TimeStampedString
|
|
418
|
+
|
|
419
|
+
chargerDerateStatus: TimeStampedString
|
|
420
|
+
chargerState: TimeStampedString
|
|
421
|
+
chargerStatus: TimeStampedString
|
|
422
|
+
|
|
423
|
+
closureFrunkClosed: TimeStampedString
|
|
424
|
+
closureFrunkLocked: TimeStampedString
|
|
425
|
+
closureFrunkNextAction: TimeStampedString
|
|
426
|
+
closureLiftgateClosed: TimeStampedString
|
|
427
|
+
closureLiftgateLocked: TimeStampedString
|
|
428
|
+
closureLiftgateNextAction: TimeStampedString
|
|
429
|
+
closureSideBinLeftClosed: TimeStampedString
|
|
430
|
+
closureSideBinLeftLocked: TimeStampedString
|
|
431
|
+
closureSideBinLeftNextAction: TimeStampedString
|
|
432
|
+
closureSideBinRightClosed: TimeStampedString
|
|
433
|
+
closureSideBinRightLocked: TimeStampedString
|
|
434
|
+
closureSideBinRightNextAction: TimeStampedString
|
|
435
|
+
closureTailgateClosed: TimeStampedString
|
|
436
|
+
closureTailgateLocked: TimeStampedString
|
|
437
|
+
closureTailgateNextAction: TimeStampedString
|
|
438
|
+
closureTonneauClosed: TimeStampedString
|
|
439
|
+
closureTonneauLocked: TimeStampedString
|
|
440
|
+
closureTonneauNextAction: TimeStampedString
|
|
441
|
+
|
|
442
|
+
cloudConnection: VehicleCloudConnection
|
|
443
|
+
|
|
444
|
+
defrostDefogStatus: TimeStampedString
|
|
445
|
+
|
|
446
|
+
distanceToEmpty: TimeStampedInt
|
|
447
|
+
|
|
448
|
+
doorFrontLeftClosed: TimeStampedString
|
|
449
|
+
doorFrontLeftLocked: TimeStampedString
|
|
450
|
+
doorFrontRightClosed: TimeStampedString
|
|
451
|
+
doorFrontRightLocked: TimeStampedString
|
|
452
|
+
doorRearLeftClosed: TimeStampedString
|
|
453
|
+
doorRearLeftLocked: TimeStampedString
|
|
454
|
+
doorRearRightClosed: TimeStampedString
|
|
455
|
+
doorRearRightLocked: TimeStampedString
|
|
456
|
+
|
|
457
|
+
driveMode: TimeStampedString
|
|
458
|
+
|
|
459
|
+
gearGuardLocked: TimeStampedString
|
|
460
|
+
gearGuardVideoMode: TimeStampedString
|
|
461
|
+
gearGuardVideoStatus: TimeStampedString
|
|
462
|
+
gearGuardVideoTermsAccepted: TimeStampedString
|
|
463
|
+
gearStatus: TimeStampedString
|
|
464
|
+
|
|
465
|
+
gnssAltitude: TimeStampedNullableFloat
|
|
466
|
+
gnssBearing: TimeStampedFloat
|
|
467
|
+
gnssLocation: VehicleLocation
|
|
468
|
+
gnssSpeed: TimeStampedFloat
|
|
469
|
+
|
|
470
|
+
otaAvailableVersion: TimeStampedString
|
|
471
|
+
otaAvailableVersionGitHash: TimeStampedString
|
|
472
|
+
otaAvailableVersionNumber: TimeStampedInt
|
|
473
|
+
otaAvailableVersionWeek: TimeStampedInt
|
|
474
|
+
otaAvailableVersionYear: TimeStampedInt
|
|
475
|
+
otaCurrentStatus: TimeStampedString
|
|
476
|
+
otaCurrentVersion: TimeStampedString
|
|
477
|
+
otaCurrentVersionGitHash: TimeStampedString
|
|
478
|
+
otaCurrentVersionNumber: TimeStampedInt
|
|
479
|
+
otaCurrentVersionWeek: TimeStampedInt
|
|
480
|
+
otaCurrentVersionYear: TimeStampedInt
|
|
481
|
+
otaDownloadProgress: TimeStampedInt
|
|
482
|
+
otaInstallDuration: TimeStampedInt
|
|
483
|
+
otaInstallProgress: TimeStampedInt
|
|
484
|
+
otaInstallReady: TimeStampedString
|
|
485
|
+
otaInstallTime: TimeStampedInt
|
|
486
|
+
otaInstallType: TimeStampedString
|
|
487
|
+
otaStatus: TimeStampedString
|
|
488
|
+
|
|
489
|
+
petModeStatus: TimeStampedString
|
|
490
|
+
petModeTemperatureStatus: TimeStampedString
|
|
491
|
+
|
|
492
|
+
powerState: TimeStampedString
|
|
493
|
+
|
|
494
|
+
rangeThreshold: TimeStampedString
|
|
495
|
+
|
|
496
|
+
remoteChargingAvailable: TimeStampedInt
|
|
497
|
+
|
|
498
|
+
seatFrontLeftHeat: TimeStampedString
|
|
499
|
+
seatFrontLeftVent: TimeStampedString
|
|
500
|
+
seatFrontRightHeat: TimeStampedString
|
|
501
|
+
seatFrontRightVent: TimeStampedString
|
|
502
|
+
seatRearLeftHeat: TimeStampedString
|
|
503
|
+
seatRearRightHeat: TimeStampedString
|
|
504
|
+
seatThirdRowLeftHeat: TimeStampedString
|
|
505
|
+
seatThirdRowRightHeat: TimeStampedString
|
|
506
|
+
|
|
507
|
+
serviceMode: TimeStampedString
|
|
508
|
+
|
|
509
|
+
steeringWheelHeat: TimeStampedString
|
|
510
|
+
|
|
511
|
+
timeToEndOfCharge: TimeStampedFloat
|
|
512
|
+
|
|
513
|
+
tirePressureStatusFrontLeft: TimeStampedString
|
|
514
|
+
tirePressureStatusFrontRight: TimeStampedString
|
|
515
|
+
tirePressureStatusRearLeft: TimeStampedString
|
|
516
|
+
tirePressureStatusRearRight: TimeStampedString
|
|
517
|
+
tirePressureStatusValidFrontLeft: TimeStampedString
|
|
518
|
+
tirePressureStatusValidFrontRight: TimeStampedString
|
|
519
|
+
tirePressureStatusValidRearLeft: TimeStampedString
|
|
520
|
+
tirePressureStatusValidRearRight: TimeStampedString
|
|
521
|
+
|
|
522
|
+
trailerStatus: TimeStampedString
|
|
523
|
+
|
|
524
|
+
twelveVoltBatteryHealth: TimeStampedString
|
|
525
|
+
|
|
526
|
+
vehicleMileage: TimeStampedInt
|
|
527
|
+
|
|
528
|
+
windowFrontLeftCalibrated: TimeStampedString
|
|
529
|
+
windowFrontLeftClosed: TimeStampedString
|
|
530
|
+
windowFrontRightCalibrated: TimeStampedString
|
|
531
|
+
windowFrontRightClosed: TimeStampedString
|
|
532
|
+
windowRearLeftCalibrated: TimeStampedString
|
|
533
|
+
windowRearLeftClosed: TimeStampedString
|
|
534
|
+
windowRearRightCalibrated: TimeStampedString
|
|
535
|
+
windowRearRightClosed: TimeStampedString
|
|
536
|
+
windowsNextAction: TimeStampedString
|
|
537
|
+
|
|
538
|
+
wiperFluidState: TimeStampedString
|
|
539
|
+
|
|
540
|
+
supportedFeatures: [SupportedFeature!]!
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
type WayPoint {
|
|
544
|
+
waypointType: String!
|
|
545
|
+
entityId: String
|
|
546
|
+
name: String
|
|
547
|
+
latitude: Float!
|
|
548
|
+
longitude: Float!
|
|
549
|
+
maxPower: Int
|
|
550
|
+
chargeDuration: Int
|
|
551
|
+
arrivalSOC: Int!
|
|
552
|
+
arrivalReachableDistance: Float!
|
|
553
|
+
departureSOC: Int!
|
|
554
|
+
departureReachableDistance: Float!
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
union ConnectedProduct = CampSpeaker
|
|
558
|
+
union InvitedUser = ProvisionedUser | UnprovisionedUser
|
|
559
|
+
union LoginResponse = MobileLoginResponse | MobileMFALoginResponse
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
type Query {
|
|
2
|
+
order(id: String!): Order
|
|
3
|
+
user: User
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
enum UserVehicleInviteStateEnum {
|
|
7
|
+
PENDING
|
|
8
|
+
COMPLETED
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
enum OrderSnapshotTypeEnum {
|
|
12
|
+
PRE_ORDER
|
|
13
|
+
RETAIL
|
|
14
|
+
VEHICLE
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type Address {
|
|
18
|
+
id: String!
|
|
19
|
+
type: [String!]!
|
|
20
|
+
line1: String!
|
|
21
|
+
line2: String
|
|
22
|
+
city: String!
|
|
23
|
+
state: String!
|
|
24
|
+
country: String!
|
|
25
|
+
postalCode: String!
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type BankDetails {
|
|
29
|
+
bankName: String!
|
|
30
|
+
country: String!
|
|
31
|
+
last4: String!
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type CardDetails {
|
|
35
|
+
brand: String!
|
|
36
|
+
last4: String!
|
|
37
|
+
expiryDate: String!
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type ConfiguratorRulesetGroup {
|
|
41
|
+
name: String
|
|
42
|
+
attrs: String
|
|
43
|
+
multiselect: Boolean!
|
|
44
|
+
required: Boolean!
|
|
45
|
+
options: [String!]!
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type ConfiguratorRulesetOption {
|
|
49
|
+
name: String
|
|
50
|
+
attrs: String
|
|
51
|
+
price: Float!
|
|
52
|
+
visualExterior: Boolean
|
|
53
|
+
visualInterior: Boolean
|
|
54
|
+
hidden: Boolean
|
|
55
|
+
disabled: Boolean
|
|
56
|
+
required: Boolean
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type Email {
|
|
60
|
+
email: String!
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type Order {
|
|
64
|
+
id: String!
|
|
65
|
+
vehicleId: String
|
|
66
|
+
vin: String
|
|
67
|
+
state: String!
|
|
68
|
+
billingAddress: OrderAddress
|
|
69
|
+
shippingAddress: OrderAddress
|
|
70
|
+
orderCancelDate: String
|
|
71
|
+
orderEmail: String
|
|
72
|
+
currency: String!
|
|
73
|
+
locale: String!
|
|
74
|
+
storeId: String!
|
|
75
|
+
type: String!
|
|
76
|
+
subtotal: Float!
|
|
77
|
+
discountTotal: Float!
|
|
78
|
+
taxTotal: Float!
|
|
79
|
+
feesTotal: Float!
|
|
80
|
+
paidTotal: Float!
|
|
81
|
+
remainingTotal: Float!
|
|
82
|
+
outstandingBalance: Float!
|
|
83
|
+
costAfterCredits: Float!
|
|
84
|
+
total: Float!
|
|
85
|
+
payments: [OrderPayment!]!
|
|
86
|
+
tradeIns: [TradeIn!]
|
|
87
|
+
vehicle: Vehicle
|
|
88
|
+
items: [OrderItem!]!
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type OrderAddress {
|
|
92
|
+
firstName: String!
|
|
93
|
+
lastName: String!
|
|
94
|
+
line1: String!
|
|
95
|
+
line2: String
|
|
96
|
+
city: String!
|
|
97
|
+
state: String!
|
|
98
|
+
country: String!
|
|
99
|
+
postalCode: String!
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type OrderConfiguration {
|
|
103
|
+
version: String!
|
|
104
|
+
basePrice: Float!
|
|
105
|
+
options: [OrderConfigurationOption!]!
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
type OrderConfigurationOption {
|
|
109
|
+
optionId: String!
|
|
110
|
+
optionName: String!
|
|
111
|
+
optionDetails: ConfiguratorRulesetOption!
|
|
112
|
+
groupId: String!
|
|
113
|
+
groupName: String!
|
|
114
|
+
groupDetails: ConfiguratorRulesetGroup!
|
|
115
|
+
price: Float!
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type OrderItem {
|
|
119
|
+
id: String!
|
|
120
|
+
productId: String!
|
|
121
|
+
type: String!
|
|
122
|
+
sku: String!
|
|
123
|
+
title: String!
|
|
124
|
+
configuration: OrderConfiguration
|
|
125
|
+
discounts: [OrderItemDiscount!]
|
|
126
|
+
subtotal: Float!
|
|
127
|
+
quantity: Int!
|
|
128
|
+
unitPrice: Float!
|
|
129
|
+
fees: [OrderItemFees!]
|
|
130
|
+
taxes: [OrderItemTaxes!]
|
|
131
|
+
shippingAddress: OrderItemFulfillmentAddress!
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
type OrderItemDiscount {
|
|
135
|
+
total: Float!
|
|
136
|
+
items: [OrderItemDiscountItem!]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type OrderItemDiscountItem {
|
|
140
|
+
amount: Float!
|
|
141
|
+
title: String!
|
|
142
|
+
code: String!
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
type OrderItemFeeItem {
|
|
146
|
+
description: String!
|
|
147
|
+
amount: Float!
|
|
148
|
+
code: String!
|
|
149
|
+
type: String!
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
type OrderItemFees {
|
|
153
|
+
items: [OrderItemFeeItem!]!
|
|
154
|
+
total: Float!
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type OrderItemFulfillmentAddress {
|
|
158
|
+
firstName: String!
|
|
159
|
+
lastName: String!
|
|
160
|
+
line1: String!
|
|
161
|
+
line2: String
|
|
162
|
+
city: String!
|
|
163
|
+
state: String!
|
|
164
|
+
country: String!
|
|
165
|
+
postalCode: String!
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
type OrderItemTaxItem {
|
|
169
|
+
description: String!
|
|
170
|
+
amount: Float!
|
|
171
|
+
code: String!
|
|
172
|
+
rate: Float
|
|
173
|
+
type: String
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
type OrderItemTaxes {
|
|
177
|
+
items: [OrderItemTaxItem!]!
|
|
178
|
+
total: Float!
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
type OrderPayment {
|
|
182
|
+
id: String!
|
|
183
|
+
intent: String!
|
|
184
|
+
date: String!
|
|
185
|
+
method: String!
|
|
186
|
+
amount: Float!
|
|
187
|
+
referenceNumber: String
|
|
188
|
+
status: String!
|
|
189
|
+
card: CardDetails
|
|
190
|
+
bank: BankDetails
|
|
191
|
+
transactionNotes: String!
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
type OrderSnapshot {
|
|
195
|
+
id: String!
|
|
196
|
+
total: Float!
|
|
197
|
+
paidTotal: Float!
|
|
198
|
+
subtotal: Float!
|
|
199
|
+
state: String!
|
|
200
|
+
configurationStatus: String!
|
|
201
|
+
currency: String!
|
|
202
|
+
orderDate: String!
|
|
203
|
+
type: String!
|
|
204
|
+
fulfillmentSummaryStatus: String!
|
|
205
|
+
vehicleId: String
|
|
206
|
+
vin: String
|
|
207
|
+
items: [OrderItem!]!
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
type Phone {
|
|
211
|
+
formatted: String!
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
type RivianIdVehicle {
|
|
215
|
+
id: String!
|
|
216
|
+
vin: String!
|
|
217
|
+
highestPriorityRole: String!
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
type TradeIn {
|
|
221
|
+
tradeInReferenceId: String!
|
|
222
|
+
amount: Float!
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
type User {
|
|
226
|
+
email: Email!
|
|
227
|
+
phone: Phone!
|
|
228
|
+
firstName: String!
|
|
229
|
+
lastName: String!
|
|
230
|
+
addresses: [Address!]!
|
|
231
|
+
newsletterSubscription: Boolean!
|
|
232
|
+
smsSubscription: Boolean!
|
|
233
|
+
registrationChannels2FA: String!
|
|
234
|
+
userId: String!
|
|
235
|
+
vehicles: [RivianIdVehicle!]!
|
|
236
|
+
invites(filterStates: [UserVehicleInviteStateEnum!]): [UserVehicleInvite!]!
|
|
237
|
+
orderSnapshots(filterTypes: [OrderSnapshotTypeEnum!]): [OrderSnapshot!]!
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
type UserVehicleInvite {
|
|
241
|
+
id: String!
|
|
242
|
+
inviteState: String!
|
|
243
|
+
vehicleModel: String!
|
|
244
|
+
vehicleId: String!
|
|
245
|
+
creatorFirstName: String!
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
type Vehicle {
|
|
249
|
+
vehicleId: String!
|
|
250
|
+
vin: String!
|
|
251
|
+
modelYear: String!
|
|
252
|
+
model: String!
|
|
253
|
+
make: String!
|
|
254
|
+
}
|
|
@@ -67,6 +67,14 @@ def generate_key_pair() -> tuple[str, str]:
|
|
|
67
67
|
return (public_key_str, private_key_str)
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
def generate_ble_command_hmac(
|
|
71
|
+
hmac_data: bytes, vehicle_key: str, private_key: str
|
|
72
|
+
) -> bytes:
|
|
73
|
+
"""Generate ble command hmac."""
|
|
74
|
+
secret_key = get_secret_key(private_key, vehicle_key)
|
|
75
|
+
return bytes.fromhex(get_message_signature(secret_key, hmac_data))
|
|
76
|
+
|
|
77
|
+
|
|
70
78
|
def generate_vehicle_command_hmac(
|
|
71
79
|
command: str, timestamp: str, vehicle_key: str, private_key: str
|
|
72
80
|
):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|