tesla-fleet-api 0.2.0 → 0.3.0
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.
- package/dist/commands.d.ts +352 -0
- package/dist/commands.js +875 -0
- package/dist/commands.js.map +1 -0
- package/dist/energy.js +6 -2
- package/dist/energy.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/signing/crypto.d.ts +10 -0
- package/dist/signing/crypto.js +26 -0
- package/dist/signing/crypto.js.map +1 -0
- package/dist/signing/errors.d.ts +29 -0
- package/dist/signing/errors.js +40 -0
- package/dist/signing/errors.js.map +1 -0
- package/dist/signing/session.d.ts +69 -0
- package/dist/signing/session.js +102 -0
- package/dist/signing/session.js.map +1 -0
- package/dist/tariff.d.ts +29 -0
- package/dist/tariff.js +302 -0
- package/dist/tariff.js.map +1 -0
- package/dist/teslafleetapi.d.ts +5 -0
- package/dist/teslafleetapi.js +23 -9
- package/dist/teslafleetapi.js.map +1 -1
- package/dist/teslemetry.d.ts +4 -0
- package/dist/teslemetry.js +15 -1
- package/dist/teslemetry.js.map +1 -1
- package/dist/types/site_info.d.ts +37 -8
- package/dist/types/vehicle.d.ts +1 -0
- package/dist/types/vehicle.js +9 -1
- package/dist/types/vehicle.js.map +1 -1
- package/dist/vehicle.d.ts +12 -0
- package/dist/vehicle.js +13 -8
- package/dist/vehicle.js.map +1 -1
- package/dist/vehiclesigned.d.ts +13 -0
- package/dist/vehiclesigned.js +19 -0
- package/dist/vehiclesigned.js.map +1 -0
- package/dist/vehiclespecific.d.ts +3 -15
- package/dist/vehiclespecific.js.map +1 -1
- package/package.json +16 -6
- package/src/commands.ts +1134 -0
- package/src/energy.ts +197 -135
- package/src/index.ts +13 -1
- package/src/signing/crypto.ts +29 -0
- package/src/signing/errors.ts +50 -0
- package/src/signing/session.ts +132 -0
- package/src/tariff.ts +375 -0
- package/src/teslafleetapi.ts +160 -121
- package/src/teslemetry.ts +39 -24
- package/src/types/site_info.ts +38 -8
- package/src/types/vehicle.ts +10 -0
- package/src/vehicle.ts +16 -10
- package/src/vehiclesigned.ts +20 -0
- package/src/vehiclespecific.ts +811 -721
package/src/teslemetry.ts
CHANGED
|
@@ -6,34 +6,49 @@ type Region = "na" | "eu" | "api";
|
|
|
6
6
|
type Test = { response: boolean };
|
|
7
7
|
|
|
8
8
|
type Metadata = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
uid: string;
|
|
10
|
+
region: "NA" | "EU";
|
|
11
|
+
scopes: Scope[];
|
|
12
|
+
vins: string[];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export default class Telemetry extends TeslaFleetApi {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
constructor(accessToken: string, region: Region = "api") {
|
|
17
|
+
super({
|
|
18
|
+
accessToken,
|
|
19
|
+
server: `https://${region}.teslemetry.com`,
|
|
20
|
+
partnerScope: false,
|
|
21
|
+
userScope: false,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
async _response(resp: Response) {
|
|
26
|
+
if (resp.headers.has("x-region")) {
|
|
27
|
+
const region = resp.headers.get("x-region")?.toLowerCase();
|
|
28
|
+
if (region) {
|
|
29
|
+
this.server = `https://${region}.teslemetry.com`;
|
|
30
|
+
}
|
|
25
31
|
}
|
|
32
|
+
return super._response(resp);
|
|
33
|
+
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Test the connection to Teslemetry
|
|
37
|
+
*/
|
|
38
|
+
async test(): Promise<Test> {
|
|
39
|
+
return this._request("GET", "/api/test").then(({ response }) => response);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get details about your Teslemetry account
|
|
44
|
+
* @param update_region Update the server URL based on the region in the metadata
|
|
45
|
+
*/
|
|
46
|
+
async metadata(update_region = true): Promise<Metadata> {
|
|
47
|
+
return this._request("GET", "/api/metadata").then((metadata) => {
|
|
48
|
+
if (update_region) {
|
|
49
|
+
this.server = `https://${metadata.region.toLowerCase()}.teslemetry.com`;
|
|
50
|
+
}
|
|
51
|
+
return metadata;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
39
54
|
}
|
package/src/types/site_info.ts
CHANGED
|
@@ -110,20 +110,50 @@ export type UserSettings = {
|
|
|
110
110
|
off_grid_vehicle_charging_enabled: boolean;
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
export type TariffPeriodWindow = {
|
|
114
|
+
fromDayOfWeek?: number;
|
|
115
|
+
toDayOfWeek?: number;
|
|
116
|
+
fromHour?: number;
|
|
117
|
+
toHour?: number;
|
|
118
|
+
fromMinute?: number;
|
|
119
|
+
toMinute?: number;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export type TouPeriods = Record<string, { periods: TariffPeriodWindow[] }>;
|
|
123
|
+
|
|
124
|
+
export type Season = {
|
|
125
|
+
fromDay?: number;
|
|
126
|
+
toDay?: number;
|
|
127
|
+
fromMonth?: number;
|
|
128
|
+
toMonth?: number;
|
|
129
|
+
tou_periods?: TouPeriods;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type EnergyCharges = Record<string, { rates?: Record<string, number> }>;
|
|
133
|
+
|
|
134
|
+
export type SellTariff = {
|
|
135
|
+
name?: string;
|
|
136
|
+
utility?: string;
|
|
137
|
+
daily_charges?: Record<string, any>[];
|
|
138
|
+
demand_charges?: Record<string, any>;
|
|
139
|
+
energy_charges: EnergyCharges;
|
|
140
|
+
seasons?: Record<string, Season>;
|
|
141
|
+
};
|
|
142
|
+
|
|
113
143
|
export type TariffContentV2 = {
|
|
114
144
|
version: number;
|
|
115
|
-
monthly_minimum_bill
|
|
116
|
-
min_applicable_demand
|
|
117
|
-
max_applicable_demand
|
|
118
|
-
monthly_charges
|
|
145
|
+
monthly_minimum_bill?: number;
|
|
146
|
+
min_applicable_demand?: number;
|
|
147
|
+
max_applicable_demand?: number;
|
|
148
|
+
monthly_charges?: number;
|
|
119
149
|
utility: string;
|
|
120
150
|
code: string;
|
|
121
151
|
name: string;
|
|
122
152
|
currency: string;
|
|
123
153
|
daily_charges: Record<string, any>[];
|
|
124
|
-
daily_demand_charges
|
|
154
|
+
daily_demand_charges?: Record<string, any>;
|
|
125
155
|
demand_charges: Record<string, any>;
|
|
126
|
-
energy_charges:
|
|
127
|
-
seasons: Record<string,
|
|
128
|
-
sell_tariff
|
|
156
|
+
energy_charges: EnergyCharges;
|
|
157
|
+
seasons: Record<string, Season>;
|
|
158
|
+
sell_tariff?: SellTariff;
|
|
129
159
|
};
|
package/src/types/vehicle.ts
CHANGED
|
@@ -21,3 +21,13 @@ export type VehicleResponse = {
|
|
|
21
21
|
export type GranularAccess = {
|
|
22
22
|
hide_private: boolean;
|
|
23
23
|
};
|
|
24
|
+
|
|
25
|
+
export const Models: Record<string, string> = {
|
|
26
|
+
S: "Model S",
|
|
27
|
+
"3": "Model 3",
|
|
28
|
+
X: "Model X",
|
|
29
|
+
Y: "Model Y",
|
|
30
|
+
C: "Cybertruck",
|
|
31
|
+
T: "Semi",
|
|
32
|
+
A: "Cybercab",
|
|
33
|
+
};
|
package/src/vehicle.ts
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import TeslaFleetApi from "./teslafleetapi.js";
|
|
2
2
|
import { ClimateMode, ClimateModes, CommandResponse, FleetTelemetryConfig, Level, Seat, Seats, Trunk, VehicleDataEndpoint } from "./types/commands.js";
|
|
3
3
|
import { OptionsResponse } from "./types/responses.js";
|
|
4
|
-
import { VehicleResponse } from "./types/vehicle.js";
|
|
4
|
+
import { Models, VehicleResponse } from "./types/vehicle.js";
|
|
5
5
|
import { VehicleDataResponse } from "./types/vehicle_data.js";
|
|
6
6
|
import VehicleSpecific from "./vehiclespecific.js";
|
|
7
|
-
|
|
8
|
-
const Models: Record<string, string> = {
|
|
9
|
-
S: "Model S",
|
|
10
|
-
"3": "Model 3",
|
|
11
|
-
X: "Model X",
|
|
12
|
-
Y: "Model Y",
|
|
13
|
-
C: "Cybertruck",
|
|
14
|
-
T: "Semi",
|
|
15
|
-
};
|
|
7
|
+
import VehicleSigned from "./vehiclesigned.js";
|
|
16
8
|
|
|
17
9
|
export default class Vehicle {
|
|
18
10
|
parent: TeslaFleetApi;
|
|
11
|
+
/** Fallback private key for `signed()` when a call site doesn't pass one explicitly. */
|
|
12
|
+
private_key?: Buffer;
|
|
19
13
|
|
|
20
14
|
constructor(parent: TeslaFleetApi) {
|
|
21
15
|
this.parent = parent;
|
|
@@ -30,6 +24,18 @@ export default class Vehicle {
|
|
|
30
24
|
return new VehicleSpecific(this, vin);
|
|
31
25
|
}
|
|
32
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Returns a class for a single vehicle that signs commands with the
|
|
29
|
+
* Tesla Vehicle Command Protocol and dispatches them through the Fleet
|
|
30
|
+
* API `/signed_command` endpoint, instead of the plaintext REST commands.
|
|
31
|
+
* @param vin
|
|
32
|
+
* @param private_key Raw 32-byte P-256 private key scalar. Falls back to `this.private_key`.
|
|
33
|
+
* @param public_key Uncompressed P-256 public key point. Derived from `private_key` if omitted.
|
|
34
|
+
*/
|
|
35
|
+
signed(vin: string, private_key?: Buffer, public_key?: Buffer): VehicleSigned {
|
|
36
|
+
return new VehicleSigned(this, vin, private_key, public_key);
|
|
37
|
+
}
|
|
38
|
+
|
|
33
39
|
/**
|
|
34
40
|
* Return the vehicle model name
|
|
35
41
|
* @param vin
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RoutableMessage } from "@teslemetry/tesla-protocol/command/universal_message";
|
|
2
|
+
import { VehicleStatus } from "@teslemetry/tesla-protocol/command/vcsec";
|
|
3
|
+
import Commands from "./commands.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The Fleet API `/signed_command` transport: fills `Commands`'s abstract
|
|
7
|
+
* `_send` seam by base64-encoding the signed `RoutableMessage`, POSTing it to
|
|
8
|
+
* the cloud `signed_command` endpoint, and decoding the reply. A future BLE
|
|
9
|
+
* transport (Story 3) fills the same seam over a GATT link instead - nothing
|
|
10
|
+
* else in `Commands` needs to change for that to work.
|
|
11
|
+
*/
|
|
12
|
+
export default class VehicleSigned extends Commands {
|
|
13
|
+
protected async _send(msg: RoutableMessage, _requires: string, _expectsData?: boolean, _confirmBroadcast?: (status: VehicleStatus) => boolean): Promise<RoutableMessage> {
|
|
14
|
+
const encoded = Buffer.from(RoutableMessage.encode(msg).finish()).toString("base64");
|
|
15
|
+
const json = await this.parent.signed_command(this.vin, encoded);
|
|
16
|
+
const resp = RoutableMessage.decode(Buffer.from(json.response, "base64"));
|
|
17
|
+
this.validateAndUpdateSession(resp, Buffer.from(msg.uuid));
|
|
18
|
+
return resp;
|
|
19
|
+
}
|
|
20
|
+
}
|