tesla-fleet-api 0.9.5__py3-none-any.whl → 0.9.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|