tesla-fleet-api 0.9.5__py3-none-any.whl → 0.9.6__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- tesla_fleet_api/const.py +1 -1
- tesla_fleet_api/exceptions.py +239 -46
- tesla_fleet_api/pb2/__init__.pyi +9 -0
- tesla_fleet_api/pb2/car_server_pb2.py +164 -386
- tesla_fleet_api/pb2/car_server_pb2.pyi +904 -0
- tesla_fleet_api/pb2/common_pb2.py +26 -60
- tesla_fleet_api/pb2/common_pb2.pyi +130 -0
- tesla_fleet_api/pb2/errors_pb2.py +10 -22
- tesla_fleet_api/pb2/errors_pb2.pyi +32 -0
- tesla_fleet_api/pb2/keys_pb2.py +8 -16
- tesla_fleet_api/pb2/keys_pb2.pyi +21 -0
- tesla_fleet_api/pb2/managed_charging_pb2.py +8 -14
- tesla_fleet_api/pb2/managed_charging_pb2.pyi +17 -0
- tesla_fleet_api/pb2/signatures_pb2.py +28 -75
- tesla_fleet_api/pb2/signatures_pb2.pyi +152 -0
- tesla_fleet_api/pb2/universal_message_pb2.py +22 -78
- tesla_fleet_api/pb2/universal_message_pb2.pyi +148 -0
- tesla_fleet_api/pb2/vcsec_pb2.py +70 -236
- tesla_fleet_api/pb2/vcsec_pb2.pyi +482 -0
- tesla_fleet_api/pb2/vehicle_pb2.py +114 -267
- tesla_fleet_api/pb2/vehicle_pb2.pyi +1183 -0
- tesla_fleet_api/teslafleetapi.py +7 -5
- tesla_fleet_api/teslafleetoauth.py +1 -1
- tesla_fleet_api/teslemetry.py +2 -2
- tesla_fleet_api/vehicle.py +1 -1
- tesla_fleet_api/vehiclesigned.py +142 -94
- {tesla_fleet_api-0.9.5.dist-info → tesla_fleet_api-0.9.6.dist-info}/METADATA +12 -3
- tesla_fleet_api-0.9.6.dist-info/RECORD +42 -0
- {tesla_fleet_api-0.9.5.dist-info → tesla_fleet_api-0.9.6.dist-info}/WHEEL +1 -1
- tesla_fleet_api-0.9.5.dist-info/RECORD +0 -33
- {tesla_fleet_api-0.9.5.dist-info → tesla_fleet_api-0.9.6.dist-info}/LICENSE +0 -0
- {tesla_fleet_api-0.9.5.dist-info → tesla_fleet_api-0.9.6.dist-info}/top_level.txt +0 -0
tesla_fleet_api/teslafleetapi.py
CHANGED
@@ -106,6 +106,11 @@ class TeslaFleetApi:
|
|
106
106
|
if access_token := await self.refresh_hook():
|
107
107
|
self.access_token = access_token
|
108
108
|
|
109
|
+
headers = {
|
110
|
+
"Authorization": f"Bearer {self.access_token}",
|
111
|
+
"X-Library": f"python tesla_fleet_api {VERSION}",
|
112
|
+
}
|
113
|
+
|
109
114
|
# Remove None values from params and json
|
110
115
|
if params:
|
111
116
|
params = {k: v for k, v in params.items() if v is not None}
|
@@ -113,15 +118,12 @@ class TeslaFleetApi:
|
|
113
118
|
if json:
|
114
119
|
json = {k: v for k, v in json.items() if v is not None}
|
115
120
|
LOGGER.debug("Body: %s", dumps(json))
|
121
|
+
headers["Content-Type"] = "application/json"
|
116
122
|
|
117
123
|
async with self.session.request(
|
118
124
|
method,
|
119
125
|
f"{self.server}/{path}",
|
120
|
-
headers=
|
121
|
-
"Authorization": f"Bearer {self.access_token}",
|
122
|
-
"Content-Type": "application/json",
|
123
|
-
"X-Library": f"python tesla_fleet_api {VERSION}",
|
124
|
-
},
|
126
|
+
headers=headers,
|
125
127
|
json=json,
|
126
128
|
params=params,
|
127
129
|
) as resp:
|
@@ -45,7 +45,7 @@ class TeslaFleetOAuth(TeslaFleetApi):
|
|
45
45
|
"""Get the login URL."""
|
46
46
|
if self.redirect_uri is None:
|
47
47
|
raise ValueError("Redirect URI is missing")
|
48
|
-
return f"https://auth.tesla.com/oauth2/v3/authorize?response_type=code&
|
48
|
+
return f"https://auth.tesla.com/oauth2/v3/authorize?response_type=code&client_id={self.client_id}&redirect_uri={self.redirect_uri}&scope={'+'.join(scopes)}&state={state}"
|
49
49
|
|
50
50
|
async def get_refresh_token(self, code: str) -> None:
|
51
51
|
"""Get the refresh token."""
|
tesla_fleet_api/teslemetry.py
CHANGED
@@ -96,11 +96,11 @@ class Teslemetry(TeslaFleetApi):
|
|
96
96
|
)
|
97
97
|
).get("response")
|
98
98
|
|
99
|
-
async def
|
99
|
+
async def vehicle_data_refresh(self, vin: str) -> dict[str, Any]:
|
100
100
|
"""Force a refresh of the vehicle data."""
|
101
101
|
return await self._request(
|
102
102
|
Method.GET,
|
103
|
-
f"api/
|
103
|
+
f"api/refresh/{vin}",
|
104
104
|
)
|
105
105
|
|
106
106
|
async def _request(
|
tesla_fleet_api/vehicle.py
CHANGED
@@ -44,7 +44,7 @@ class Vehicle:
|
|
44
44
|
|
45
45
|
def pre2021(self, vin: str) -> bool:
|
46
46
|
"""Checks if a vehicle is a pre-2021 model S or X."""
|
47
|
-
return vin[9] <= "L" and vin[
|
47
|
+
return vin[3] in ["S", "X"] and (vin[9] <= "L" or (vin[9] == "M" and vin[7] in ['1', '2', '3', '4']))
|
48
48
|
|
49
49
|
async def actuate_trunk(
|
50
50
|
self, vehicle_tag: str | int, which_trunk: Trunk | str
|
tesla_fleet_api/vehiclesigned.py
CHANGED
@@ -8,8 +8,11 @@ import hmac
|
|
8
8
|
import hashlib
|
9
9
|
from cryptography.hazmat.primitives.asymmetric import ec
|
10
10
|
from cryptography.hazmat.primitives.serialization import PublicFormat, Encoding
|
11
|
+
from asyncio import Lock, sleep
|
11
12
|
|
12
|
-
from .
|
13
|
+
from tesla_fleet_api.pb2.errors_pb2 import GenericError_E
|
14
|
+
|
15
|
+
from .exceptions import MESSAGE_FAULTS, SIGNED_MESSAGE_INFORMATION_FAULTS, TeslaFleetMessageFaultIncorrectEpoch, TeslaFleetMessageFaultInvalidTokenOrCounter
|
13
16
|
|
14
17
|
from .const import (
|
15
18
|
LOGGER,
|
@@ -22,19 +25,18 @@ from .const import (
|
|
22
25
|
from .vehiclespecific import VehicleSpecific
|
23
26
|
|
24
27
|
from .pb2.universal_message_pb2 import (
|
25
|
-
# OPERATIONSTATUS_OK,
|
26
|
-
MESSAGEFAULT_ERROR_INCORRECT_EPOCH,
|
27
28
|
OPERATIONSTATUS_WAIT,
|
28
29
|
OPERATIONSTATUS_ERROR,
|
29
30
|
DOMAIN_VEHICLE_SECURITY,
|
30
31
|
DOMAIN_INFOTAINMENT,
|
31
32
|
Domain,
|
32
|
-
# MessageFault_E,
|
33
33
|
RoutableMessage,
|
34
34
|
)
|
35
35
|
from .pb2.car_server_pb2 import (
|
36
|
+
Response,
|
36
37
|
Action,
|
37
38
|
MediaPlayAction,
|
39
|
+
ResultReason,
|
38
40
|
VehicleAction,
|
39
41
|
VehicleControlFlashLightsAction,
|
40
42
|
ChargingStartStopAction,
|
@@ -82,6 +84,8 @@ from .pb2.car_server_pb2 import (
|
|
82
84
|
from .pb2.vehicle_pb2 import VehicleState
|
83
85
|
from .pb2.vcsec_pb2 import (
|
84
86
|
# SignedMessage_information_E,
|
87
|
+
OPERATIONSTATUS_OK,
|
88
|
+
FromVCSECMessage,
|
85
89
|
UnsignedMessage,
|
86
90
|
RKEAction_E,
|
87
91
|
ClosureMoveRequest,
|
@@ -91,6 +95,7 @@ from .pb2.signatures_pb2 import (
|
|
91
95
|
SIGNATURE_TYPE_HMAC_PERSONALIZED,
|
92
96
|
TAG_DOMAIN,
|
93
97
|
TAG_SIGNATURE_TYPE,
|
98
|
+
KeyIdentity,
|
94
99
|
SignatureData,
|
95
100
|
SessionInfo,
|
96
101
|
HMAC_Personalized_Signature_Data,
|
@@ -121,35 +126,38 @@ class Session:
|
|
121
126
|
epoch: bytes
|
122
127
|
delta: int
|
123
128
|
hmac: bytes
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
self.
|
129
|
-
|
130
|
-
|
129
|
+
publicKey: bytes
|
130
|
+
lock: Lock
|
131
|
+
|
132
|
+
def __init__(self):
|
133
|
+
self.lock = Lock()
|
134
|
+
|
135
|
+
def update(self, sessionInfo: SessionInfo, privateKey: ec.EllipticCurvePrivateKey):
|
136
|
+
"""Update the session with new information"""
|
137
|
+
self.counter = sessionInfo.counter
|
138
|
+
self.epoch = sessionInfo.epoch
|
139
|
+
self.delta = int(time.time()) - sessionInfo.clock_time
|
140
|
+
self.publicKey = sessionInfo.publicKey
|
141
|
+
self.key = hashlib.sha1(
|
142
|
+
privateKey.exchange(
|
143
|
+
ec.ECDH(),
|
144
|
+
ec.EllipticCurvePublicKey.from_encoded_point(
|
145
|
+
ec.SECP256R1(), self.publicKey
|
146
|
+
),
|
147
|
+
)
|
148
|
+
).digest()[:16]
|
131
149
|
self.hmac = hmac.new(
|
132
|
-
key, "authenticated command".encode(), hashlib.sha256
|
150
|
+
self.key, "authenticated command".encode(), hashlib.sha256
|
133
151
|
).digest()
|
134
152
|
|
135
153
|
def get(self) -> HMAC_Personalized_Signature_Data:
|
136
154
|
"""Sign a command and return session metadata"""
|
137
155
|
self.counter += 1
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
def tag(
|
145
|
-
self,
|
146
|
-
signature: HMAC_Personalized_Signature_Data,
|
147
|
-
command: bytes,
|
148
|
-
metadata: bytes,
|
149
|
-
) -> HMAC_Personalized_Signature_Data:
|
150
|
-
"""Sign a command and return the signature"""
|
151
|
-
signature.tag = hmac.new(self.hmac, metadata + command, hashlib.sha256).digest()
|
152
|
-
return signature
|
156
|
+
return HMAC_Personalized_Signature_Data(
|
157
|
+
epoch=self.epoch,
|
158
|
+
counter=self.counter,
|
159
|
+
expires_at=int(time.time()) - self.delta + 10,
|
160
|
+
)
|
153
161
|
|
154
162
|
|
155
163
|
class VehicleSigned(VehicleSpecific):
|
@@ -177,22 +185,35 @@ class VehicleSigned(VehicleSpecific):
|
|
177
185
|
self._from_destination = randbytes(16)
|
178
186
|
self._sessions = {}
|
179
187
|
|
180
|
-
async def
|
188
|
+
async def _send(self, msg: RoutableMessage) -> RoutableMessage:
|
181
189
|
"""Serialize a message and send to the signed command endpoint."""
|
182
|
-
routable_message = base64.b64encode(msg.SerializeToString()).decode()
|
183
|
-
resp_json = await self.signed_command(routable_message)
|
184
|
-
resp = RoutableMessage()
|
185
|
-
resp.ParseFromString(base64.b64decode(resp_json["response"]))
|
186
190
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
+
async with self._sessions[msg.to_destination.domain].lock:
|
192
|
+
resp = await self.signed_command(
|
193
|
+
base64.b64encode(msg.SerializeToString()).decode()
|
194
|
+
)
|
195
|
+
|
196
|
+
resp_msg = RoutableMessage.FromString(base64.b64decode(resp["response"]))
|
191
197
|
|
192
|
-
|
198
|
+
# Check UUID?
|
199
|
+
# Check RoutingAdress?
|
193
200
|
|
194
|
-
|
201
|
+
if resp_msg.session_info:
|
202
|
+
self._sessions[resp_msg.from_destination.domain].update(
|
203
|
+
SessionInfo.FromString(resp_msg.session_info), self.private_key
|
204
|
+
)
|
205
|
+
|
206
|
+
if resp_msg.signedMessageStatus.signed_message_fault:
|
207
|
+
raise MESSAGE_FAULTS[resp_msg.signedMessageStatus.signed_message_fault]
|
208
|
+
|
209
|
+
return resp_msg
|
210
|
+
|
211
|
+
async def _handshake(self, domain: Domain) -> Session:
|
195
212
|
"""Perform a handshake with the vehicle."""
|
213
|
+
if session := self._sessions.get(domain):
|
214
|
+
return session
|
215
|
+
self._sessions[domain] = Session()
|
216
|
+
|
196
217
|
LOGGER.debug(f"Handshake with domain {Domain.Name(domain)}")
|
197
218
|
msg = RoutableMessage()
|
198
219
|
msg.to_destination.domain = domain
|
@@ -201,51 +222,34 @@ class VehicleSigned(VehicleSpecific):
|
|
201
222
|
msg.uuid = randbytes(16)
|
202
223
|
|
203
224
|
# Send handshake message
|
204
|
-
|
205
|
-
|
206
|
-
# Get session info with publicKey, epoch, and clock_time
|
207
|
-
info = SessionInfo.FromString(resp.session_info)
|
225
|
+
await self._send(msg)
|
208
226
|
|
209
|
-
|
210
|
-
|
211
|
-
# Derive shared key from private key _key and vehicle public key
|
212
|
-
shared = self.private_key.exchange(
|
213
|
-
ec.ECDH(),
|
214
|
-
ec.EllipticCurvePublicKey.from_encoded_point(
|
215
|
-
ec.SECP256R1(), vehicle_public_key
|
216
|
-
),
|
217
|
-
)
|
218
|
-
|
219
|
-
self._sessions[domain] = Session(
|
220
|
-
key=hashlib.sha1(shared).digest()[:16],
|
221
|
-
counter=info.counter,
|
222
|
-
epoch=info.epoch,
|
223
|
-
delta=int(time.time()) - info.clock_time,
|
224
|
-
)
|
227
|
+
return self._sessions[domain]
|
225
228
|
|
226
229
|
async def _sendVehicleSecurity(self, command: UnsignedMessage) -> dict[str, Any]:
|
227
230
|
"""Sign and send a message to Infotainment computer."""
|
228
|
-
|
229
|
-
await self._handshake(DOMAIN_VEHICLE_SECURITY)
|
230
|
-
return await self._send(DOMAIN_VEHICLE_SECURITY, command.SerializeToString())
|
231
|
+
return await self._sign(DOMAIN_VEHICLE_SECURITY, command.SerializeToString())
|
231
232
|
|
232
233
|
async def _sendInfotainment(self, command: Action) -> dict[str, Any]:
|
233
234
|
"""Sign and send a message to Infotainment computer."""
|
234
|
-
|
235
|
-
await self._handshake(DOMAIN_INFOTAINMENT)
|
236
|
-
return await self._send(DOMAIN_INFOTAINMENT, command.SerializeToString())
|
235
|
+
return await self._sign(DOMAIN_INFOTAINMENT, command.SerializeToString())
|
237
236
|
|
238
|
-
async def
|
237
|
+
async def _sign(
|
238
|
+
self, domain: Domain, command: bytes, attempt: int = 1
|
239
|
+
) -> dict[str, Any]:
|
239
240
|
"""Send a signed message to the vehicle."""
|
240
241
|
LOGGER.debug(f"Sending to domain {Domain.Name(domain)}")
|
242
|
+
|
243
|
+
session = await self._handshake(domain)
|
244
|
+
hmac_personalized = session.get()
|
245
|
+
|
241
246
|
msg = RoutableMessage()
|
242
247
|
msg.to_destination.domain = domain
|
243
248
|
msg.from_destination.routing_address = self._from_destination
|
244
249
|
msg.protobuf_message_as_bytes = command
|
245
250
|
msg.uuid = randbytes(16)
|
246
251
|
|
247
|
-
|
248
|
-
metadata = [
|
252
|
+
metadata = bytes([
|
249
253
|
TAG_SIGNATURE_TYPE,
|
250
254
|
1,
|
251
255
|
SIGNATURE_TYPE_HMAC_PERSONALIZED,
|
@@ -256,48 +260,92 @@ class VehicleSigned(VehicleSpecific):
|
|
256
260
|
17,
|
257
261
|
*self.vin.encode(),
|
258
262
|
TAG_EPOCH,
|
259
|
-
len(
|
260
|
-
*
|
263
|
+
len(hmac_personalized.epoch),
|
264
|
+
*hmac_personalized.epoch,
|
261
265
|
TAG_EXPIRES_AT,
|
262
266
|
4,
|
263
|
-
*struct.pack(">I",
|
267
|
+
*struct.pack(">I", hmac_personalized.expires_at),
|
264
268
|
TAG_COUNTER,
|
265
269
|
4,
|
266
|
-
*struct.pack(">I",
|
270
|
+
*struct.pack(">I", hmac_personalized.counter),
|
267
271
|
TAG_END,
|
268
|
-
]
|
269
|
-
|
270
|
-
session = self._sessions[domain].tag(session, command, bytes(metadata))
|
272
|
+
])
|
271
273
|
|
272
|
-
|
273
|
-
|
274
|
-
|
274
|
+
hmac_personalized.tag = hmac.new(
|
275
|
+
session.hmac, metadata + command, hashlib.sha256
|
276
|
+
).digest()
|
275
277
|
|
276
|
-
|
278
|
+
# I think this whole section could be improved
|
279
|
+
msg.signature_data.HMAC_Personalized_data.CopyFrom(hmac_personalized)
|
280
|
+
msg.signature_data.signer_identity.public_key = self._public_key
|
277
281
|
|
278
282
|
try:
|
279
|
-
resp = await self.
|
280
|
-
except
|
283
|
+
resp = await self._send(msg)
|
284
|
+
except (
|
285
|
+
TeslaFleetMessageFaultIncorrectEpoch,
|
286
|
+
TeslaFleetMessageFaultInvalidTokenOrCounter,
|
287
|
+
) as e:
|
281
288
|
attempt += 1
|
282
289
|
if attempt > 3:
|
283
290
|
# We tried 3 times, give up, raise the error
|
284
291
|
raise e
|
285
|
-
|
286
|
-
await self._handshake(domain)
|
287
|
-
LOGGER.info(f"Handshake complete, retrying message to {Domain.Name(domain)}")
|
288
|
-
return await self._send(domain, command, attempt)
|
292
|
+
return await self._sign(domain, command, attempt)
|
289
293
|
|
290
294
|
if resp.signedMessageStatus.operation_status == OPERATIONSTATUS_WAIT:
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
295
|
+
attempt += 1
|
296
|
+
if attempt > 3:
|
297
|
+
# We tried 3 times, give up, raise the error
|
298
|
+
return {"response": {"result": False, "reason": "Too many retries"}}
|
299
|
+
async with session.lock:
|
300
|
+
await sleep(2)
|
301
|
+
return await self._sign(domain, command, attempt)
|
302
|
+
|
303
|
+
if resp.HasField("signedMessageStatus"):
|
304
|
+
if(resp.from_destination.domain == DOMAIN_VEHICLE_SECURITY):
|
305
|
+
vcsec = FromVCSECMessage.FromString(resp.protobuf_message_as_bytes)
|
306
|
+
LOGGER.debug("VCSEC Response: %s", vcsec)
|
307
|
+
if vcsec.HasField("nominalError"):
|
308
|
+
LOGGER.error("Command failed with reason: %s", vcsec.nominalError.genericError)
|
309
|
+
return {
|
310
|
+
"response": {
|
311
|
+
"result": False,
|
312
|
+
"reason": GenericError_E.Name(vcsec.nominalError.genericError)
|
313
|
+
}
|
314
|
+
}
|
315
|
+
elif vcsec.commandStatus.operationStatus == OPERATIONSTATUS_OK:
|
316
|
+
return {"response": {"result": True, "reason": ""}}
|
317
|
+
elif vcsec.commandStatus.operationStatus == OPERATIONSTATUS_WAIT:
|
318
|
+
attempt += 1
|
319
|
+
if attempt > 3:
|
320
|
+
# We tried 3 times, give up, raise the error
|
321
|
+
return {"response": {"result": False, "reason": "Too many retries"}}
|
322
|
+
async with session.lock:
|
323
|
+
await sleep(2)
|
324
|
+
return await self._sign(domain, command, attempt)
|
325
|
+
elif vcsec.commandStatus.operationStatus == OPERATIONSTATUS_ERROR:
|
326
|
+
if(vcsec.commandStatus.signedMessageStatus):
|
327
|
+
raise SIGNED_MESSAGE_INFORMATION_FAULTS[vcsec.commandStatus.signedMessageStatus.signedMessageInformation]
|
328
|
+
|
329
|
+
elif(resp.from_destination.domain == DOMAIN_INFOTAINMENT):
|
330
|
+
response = Response.FromString(resp.protobuf_message_as_bytes)
|
331
|
+
LOGGER.debug("Infotainment Response: %s", response)
|
332
|
+
if (response.HasField("ping")):
|
333
|
+
print(response.ping)
|
334
|
+
return {
|
335
|
+
"response": {
|
336
|
+
"result": True,
|
337
|
+
"reason": response.ping.local_timestamp
|
338
|
+
}
|
339
|
+
}
|
340
|
+
if response.HasField("actionStatus"):
|
341
|
+
return {
|
342
|
+
"response": {
|
343
|
+
"result": response.actionStatus.result == OPERATIONSTATUS_OK,
|
344
|
+
"reason": response.actionStatus.result_reason.plain_text or ""
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
return {"response": {"result": None, "reason": "No Response"}}
|
301
349
|
|
302
350
|
async def actuate_trunk(self, which_trunk: Trunk | str) -> dict[str, Any]:
|
303
351
|
"""Controls the front or rear trunk."""
|
@@ -1,8 +1,8 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: tesla_fleet_api
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.6
|
4
4
|
Summary: Tesla Fleet API library for Python
|
5
|
-
Home-page: https://github.com/Teslemetry/
|
5
|
+
Home-page: https://github.com/Teslemetry/python-tesla-fleet-api
|
6
6
|
Author: Brett Adams
|
7
7
|
Author-email: hello@teslemetry.com
|
8
8
|
Classifier: Development Status :: 4 - Beta
|
@@ -17,6 +17,15 @@ Requires-Dist: aiofiles
|
|
17
17
|
Requires-Dist: aiolimiter
|
18
18
|
Requires-Dist: cryptography
|
19
19
|
Requires-Dist: protobuf
|
20
|
+
Dynamic: author
|
21
|
+
Dynamic: author-email
|
22
|
+
Dynamic: classifier
|
23
|
+
Dynamic: description
|
24
|
+
Dynamic: description-content-type
|
25
|
+
Dynamic: home-page
|
26
|
+
Dynamic: requires-dist
|
27
|
+
Dynamic: requires-python
|
28
|
+
Dynamic: summary
|
20
29
|
|
21
30
|
# Tesla Fleet Api
|
22
31
|
Python library for Tesla Fleet API and Teslemetry.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
tesla_fleet_api/__init__.py,sha256=BVZUDsfaxT05tAfcMHHWiyFyXwmDOx_wP_IHZBscgho,729
|
2
|
+
tesla_fleet_api/charging.py,sha256=N_mc8axrXj3iduqLj_jCt4Vx86tHqe3xqQT4R1R7HvU,1689
|
3
|
+
tesla_fleet_api/const.py,sha256=UdgXLx2blO4ByR3oY0YP2V0LjBCYbhsmWuMkBr3gwV0,12888
|
4
|
+
tesla_fleet_api/energy.py,sha256=S7D75MPuMVsHgkyUcFfMqjGCLZBM5YVFlWLEHbaX-zw,5957
|
5
|
+
tesla_fleet_api/energyspecific.py,sha256=UfeaGE59aoAa8UhpQCXUi0sOrNCA40xZlqwF73BXTVY,4254
|
6
|
+
tesla_fleet_api/exceptions.py,sha256=qnRWqPJ_5gia4-j3o4mP5OwUuBRtC3SAbZKo-_XSRiI,29729
|
7
|
+
tesla_fleet_api/partner.py,sha256=1vIBUaxKLIfqcC0X6VXZN0dMAzj_CLNPUMjA6QVqZ1k,1223
|
8
|
+
tesla_fleet_api/ratecalculator.py,sha256=4lz8yruUeouHXh_3ezsXX-CTpIegp1T1J4VuRV_qdHA,1791
|
9
|
+
tesla_fleet_api/teslafleetapi.py,sha256=8j-kvV6_oCuIlDdS5kWlCbo9chWsT48Gn2iKt3uOAjg,7409
|
10
|
+
tesla_fleet_api/teslafleetoauth.py,sha256=NmzycAeg68sWASjiWan3B5LdIgrfmoLTDqLHYCmoKKg,4108
|
11
|
+
tesla_fleet_api/teslafleetopensource.py,sha256=TJfVPcqJlA1b3kMoGuLr-g5Gn8UDyYsTZhjvGY1MtIk,2007
|
12
|
+
tesla_fleet_api/teslemetry.py,sha256=_n59RQvJKl82ylLe09bLY_8iyfjz_DHqCdRVsWeif4s,3308
|
13
|
+
tesla_fleet_api/tessie.py,sha256=4dBYxe1G2v9JvJGRbb01wXrAmvWT4jOfV4f_VQE_vkE,2302
|
14
|
+
tesla_fleet_api/user.py,sha256=TZE2oh-n5zrhKXmGRuiNL9voKVODD7rBhGE_IObYVGA,1179
|
15
|
+
tesla_fleet_api/vehicle.py,sha256=mSFJG-bLBNh_iSJnruk9EZSypZUxMpKwMgKA9_8CPDc,32146
|
16
|
+
tesla_fleet_api/vehiclesigned.py,sha256=N06Evfo5_AwkOjNg0cpCHYV7SH-5zjzHsYnMmYpCKZY,42001
|
17
|
+
tesla_fleet_api/vehiclespecific.py,sha256=P7KI8MqUbAyM2cfDC8NqbJXzGL2ZsOIx3IBeqB8xYQY,20656
|
18
|
+
tesla_fleet_api/pb2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
+
tesla_fleet_api/pb2/__init__.pyi,sha256=qFXWNIgl71wB260u-XPzaAwWAHL6krw21q-aXnBtop0,252
|
20
|
+
tesla_fleet_api/pb2/car_server_pb2.py,sha256=v_eb4NDIkx_ZYPYW29_EFRky5vQ4b2q14gwuQSbouYw,29202
|
21
|
+
tesla_fleet_api/pb2/car_server_pb2.pyi,sha256=qkig9HEsOE4Dk2-r38BAWOyALqt7CtUnlirgSVt_oa8,46334
|
22
|
+
tesla_fleet_api/pb2/common_pb2.py,sha256=C5O6BBTckU3F-XItLfivaPG_XVCnzF_JX4mpVfM_jFk,3931
|
23
|
+
tesla_fleet_api/pb2/common_pb2.pyi,sha256=8aZiigp74MfSOMpHtMw0D9Jj0kwPz1zV_BIZfVWhh_0,5012
|
24
|
+
tesla_fleet_api/pb2/errors_pb2.py,sha256=nfOvriyjVgVxnJZIAYNRHiBa1_14dOXhC9Pokc5anV8,1631
|
25
|
+
tesla_fleet_api/pb2/errors_pb2.pyi,sha256=CNsAR7Oe6wavnqjzhInEyAFxMio6TtXfaNT0DUztn6o,1478
|
26
|
+
tesla_fleet_api/pb2/keys_pb2.py,sha256=-hyVP9-W1DypTYLaWwkOSUzgia6l9R3M9wUIgvNs-T0,1252
|
27
|
+
tesla_fleet_api/pb2/keys_pb2.pyi,sha256=HH-TfhE5ihwmoPCGdiVnZ5B7KkaMJglEpusgLc1J02M,676
|
28
|
+
tesla_fleet_api/pb2/managed_charging_pb2.py,sha256=4crkLo6uC0YPkgw90jRjAqlGMFnRze_koUt2-pw14m4,1430
|
29
|
+
tesla_fleet_api/pb2/managed_charging_pb2.pyi,sha256=SqEmrfknTfzYTUYHtsoCpt1Fw2YpU3OyQllX247UfyQ,1227
|
30
|
+
tesla_fleet_api/pb2/signatures_pb2.py,sha256=TRaJ6lzmJtryhhmBC_PbYzftc-pqCmwC6wuBCXHeuTg,4734
|
31
|
+
tesla_fleet_api/pb2/signatures_pb2.pyi,sha256=-OGm9ctBnEJiXk-3nkFCPRTxKgFiqFgMbKeq3x2zGGM,6101
|
32
|
+
tesla_fleet_api/pb2/universal_message_pb2.py,sha256=UklH73qoYsqxylie6IK8iIcw2tmykSqDiaBKSWz66OQ,5093
|
33
|
+
tesla_fleet_api/pb2/universal_message_pb2.pyi,sha256=a_RygTJL26v0rA7QuUwsxiG1_ZBcliwXCqOAqTIJ6UE,7647
|
34
|
+
tesla_fleet_api/pb2/vcsec_pb2.py,sha256=PDv9TfiXnNs6sQ0D5vBrsSSPinSqu3eBUwvTcG8xMWo,15919
|
35
|
+
tesla_fleet_api/pb2/vcsec_pb2.pyi,sha256=cyK1uyRtDjRVqVlyl5uRQYY1RhFlWSJheLg3PGfs-_s,28524
|
36
|
+
tesla_fleet_api/pb2/vehicle_pb2.py,sha256=bqyFJM-1qZ7W9XKREINhYZx8yXAudmq6W8_Pdfkhbkk,44711
|
37
|
+
tesla_fleet_api/pb2/vehicle_pb2.pyi,sha256=sAUW_9aVB8NqJCnhZjXMLfqfePLVZv_7PfSKZKEBaQA,74251
|
38
|
+
tesla_fleet_api-0.9.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
39
|
+
tesla_fleet_api-0.9.6.dist-info/METADATA,sha256=NZZXKNqQjFt6LPS7r8TOsnEH89osm5SqRcVaIvaB5Ck,4022
|
40
|
+
tesla_fleet_api-0.9.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
41
|
+
tesla_fleet_api-0.9.6.dist-info/top_level.txt,sha256=jeNbog_1saXBFrGpom9WyPWmilxsyP3szL_G7JLWQfM,16
|
42
|
+
tesla_fleet_api-0.9.6.dist-info/RECORD,,
|
@@ -1,33 +0,0 @@
|
|
1
|
-
tesla_fleet_api/__init__.py,sha256=BVZUDsfaxT05tAfcMHHWiyFyXwmDOx_wP_IHZBscgho,729
|
2
|
-
tesla_fleet_api/charging.py,sha256=N_mc8axrXj3iduqLj_jCt4Vx86tHqe3xqQT4R1R7HvU,1689
|
3
|
-
tesla_fleet_api/const.py,sha256=40Oi7XwilcT6ZbNcQnm9hOawKNY4JLrfZA0Xc4H7g7s,12888
|
4
|
-
tesla_fleet_api/energy.py,sha256=S7D75MPuMVsHgkyUcFfMqjGCLZBM5YVFlWLEHbaX-zw,5957
|
5
|
-
tesla_fleet_api/energyspecific.py,sha256=UfeaGE59aoAa8UhpQCXUi0sOrNCA40xZlqwF73BXTVY,4254
|
6
|
-
tesla_fleet_api/exceptions.py,sha256=KUozIEvZv9Haal6ofRb0SFHQQBe8UH-lEAFVwkJFzW0,20942
|
7
|
-
tesla_fleet_api/partner.py,sha256=1vIBUaxKLIfqcC0X6VXZN0dMAzj_CLNPUMjA6QVqZ1k,1223
|
8
|
-
tesla_fleet_api/ratecalculator.py,sha256=4lz8yruUeouHXh_3ezsXX-CTpIegp1T1J4VuRV_qdHA,1791
|
9
|
-
tesla_fleet_api/teslafleetapi.py,sha256=4Rnh_HNZkIw54o9SYAaHsA8vY0pmk_bMncrLuJ8MtSk,7389
|
10
|
-
tesla_fleet_api/teslafleetoauth.py,sha256=ClrVh4_lpatW8w44fWM0PZiVB-ciPHr-9h4yw1Zf9w8,4121
|
11
|
-
tesla_fleet_api/teslafleetopensource.py,sha256=TJfVPcqJlA1b3kMoGuLr-g5Gn8UDyYsTZhjvGY1MtIk,2007
|
12
|
-
tesla_fleet_api/teslemetry.py,sha256=IiDxEjDfWdXlpI7qFGW2YwroWoLbUdWSSVM6zCnhQl8,3307
|
13
|
-
tesla_fleet_api/tessie.py,sha256=4dBYxe1G2v9JvJGRbb01wXrAmvWT4jOfV4f_VQE_vkE,2302
|
14
|
-
tesla_fleet_api/user.py,sha256=TZE2oh-n5zrhKXmGRuiNL9voKVODD7rBhGE_IObYVGA,1179
|
15
|
-
tesla_fleet_api/vehicle.py,sha256=e0AotkaI-WftNfxJbLF8peIq3l99f6-ezVSEQbkOD1I,32090
|
16
|
-
tesla_fleet_api/vehiclesigned.py,sha256=PXXBeMpQf_5-ZQccjhtf6wllgCMhOOmtSjZzmjHYgls,39886
|
17
|
-
tesla_fleet_api/vehiclespecific.py,sha256=P7KI8MqUbAyM2cfDC8NqbJXzGL2ZsOIx3IBeqB8xYQY,20656
|
18
|
-
tesla_fleet_api/pb2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
tesla_fleet_api/pb2/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
tesla_fleet_api/pb2/car_server_pb2.py,sha256=I3bq-cbq_4GXZblJatOFtjUny9seZb_1caNWMUciry0,51750
|
21
|
-
tesla_fleet_api/pb2/common_pb2.py,sha256=Iip_uomlO1s6wTyQl2QYxkUdVKB1qqSrpD3MHr-5rl0,6041
|
22
|
-
tesla_fleet_api/pb2/errors_pb2.py,sha256=ESk8GRN-jbsVvPWsWC0WfntmOXfRWVjy3sPT99WL89Q,2149
|
23
|
-
tesla_fleet_api/pb2/keys_pb2.py,sha256=T5q0OMlMiwFJV5xSmn6E2tnLCzr463Rk3pweaLFiPgM,1366
|
24
|
-
tesla_fleet_api/pb2/managed_charging_pb2.py,sha256=g6dJu9sYe9D2BCAWNFUNM_Qr0gJM5AHxmAJikHstQMc,1792
|
25
|
-
tesla_fleet_api/pb2/signatures_pb2.py,sha256=UZCXDYgV-tYIrzVHeqi0NaytUtRZJB-_lC7IVjIbggc,7719
|
26
|
-
tesla_fleet_api/pb2/universal_message_pb2.py,sha256=XF08dOMbhN0F9D4xbaNJhUIAEqbKdK1iYQdZFAloWdk,7826
|
27
|
-
tesla_fleet_api/pb2/vcsec_pb2.py,sha256=CMJ97e4Mm4p7NFcgybbCC2KJRcvtrcqmBy_pGycYhMo,26238
|
28
|
-
tesla_fleet_api/pb2/vehicle_pb2.py,sha256=ViSm74kS3iLjB2C18w-FDZyCkvi2e71GNKVmH2FU8zg,57629
|
29
|
-
tesla_fleet_api-0.9.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
30
|
-
tesla_fleet_api-0.9.5.dist-info/METADATA,sha256=f08KYxa2kQw_SuEZ0lAir5VORsuA95XYMVMmRl-80hE,3818
|
31
|
-
tesla_fleet_api-0.9.5.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
32
|
-
tesla_fleet_api-0.9.5.dist-info/top_level.txt,sha256=jeNbog_1saXBFrGpom9WyPWmilxsyP3szL_G7JLWQfM,16
|
33
|
-
tesla_fleet_api-0.9.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|