tesla-fleet-api 0.1.3 → 0.2.2

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.
Files changed (49) hide show
  1. package/dist/commands.d.ts +352 -0
  2. package/dist/commands.js +875 -0
  3. package/dist/commands.js.map +1 -0
  4. package/dist/energy.js +6 -2
  5. package/dist/energy.js.map +1 -1
  6. package/dist/index.d.ts +7 -1
  7. package/dist/index.js +6 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/signing/crypto.d.ts +10 -0
  10. package/dist/signing/crypto.js +26 -0
  11. package/dist/signing/crypto.js.map +1 -0
  12. package/dist/signing/errors.d.ts +29 -0
  13. package/dist/signing/errors.js +40 -0
  14. package/dist/signing/errors.js.map +1 -0
  15. package/dist/signing/session.d.ts +69 -0
  16. package/dist/signing/session.js +102 -0
  17. package/dist/signing/session.js.map +1 -0
  18. package/dist/tariff.d.ts +29 -0
  19. package/dist/tariff.js +302 -0
  20. package/dist/tariff.js.map +1 -0
  21. package/dist/teslafleetapi.d.ts +7 -0
  22. package/dist/teslafleetapi.js +29 -13
  23. package/dist/teslafleetapi.js.map +1 -1
  24. package/dist/teslemetry.d.ts +4 -0
  25. package/dist/teslemetry.js +15 -1
  26. package/dist/teslemetry.js.map +1 -1
  27. package/dist/types/site_info.d.ts +37 -8
  28. package/dist/vehicle.d.ts +12 -0
  29. package/dist/vehicle.js +12 -0
  30. package/dist/vehicle.js.map +1 -1
  31. package/dist/vehiclesigned.d.ts +13 -0
  32. package/dist/vehiclesigned.js +19 -0
  33. package/dist/vehiclesigned.js.map +1 -0
  34. package/dist/vehiclespecific.d.ts +3 -15
  35. package/dist/vehiclespecific.js.map +1 -1
  36. package/package.json +16 -6
  37. package/src/commands.ts +1134 -0
  38. package/src/energy.ts +197 -135
  39. package/src/index.ts +12 -1
  40. package/src/signing/crypto.ts +29 -0
  41. package/src/signing/errors.ts +50 -0
  42. package/src/signing/session.ts +132 -0
  43. package/src/tariff.ts +375 -0
  44. package/src/teslafleetapi.ts +160 -118
  45. package/src/teslemetry.ts +39 -24
  46. package/src/types/site_info.ts +38 -8
  47. package/src/vehicle.ts +15 -0
  48. package/src/vehiclesigned.ts +20 -0
  49. package/src/vehiclespecific.ts +811 -721
package/dist/tariff.js ADDED
@@ -0,0 +1,302 @@
1
+ const MINUTES_PER_DAY = 1440;
2
+ function formatParts(date, timeZone) {
3
+ const parts = new Intl.DateTimeFormat("en-US", {
4
+ timeZone,
5
+ year: "numeric",
6
+ month: "2-digit",
7
+ day: "2-digit",
8
+ hour: "2-digit",
9
+ minute: "2-digit",
10
+ second: "2-digit",
11
+ hourCycle: "h23",
12
+ }).formatToParts(date);
13
+ const out = {};
14
+ for (const p of parts)
15
+ out[p.type] = Number(p.value);
16
+ return out;
17
+ }
18
+ /** Tesla weekday (Mon=0..Sun=6) for a calendar date, via JS Date.getUTCDay() (Sun=0..Sat=6). */
19
+ function dowFromDate(year, month, day) {
20
+ const jsDow = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
21
+ return (jsDow + 6) % 7;
22
+ }
23
+ function getWallClock(now, timeZone) {
24
+ const { year, month, day, hour, minute } = formatParts(now, timeZone);
25
+ return { year, month, day, dow: dowFromDate(year, month, day), minuteOfDay: hour * 60 + minute };
26
+ }
27
+ /**
28
+ * Converts a target site-local wall-clock (year/month/day/hour/minute in `timeZone`) to the UTC
29
+ * instant it represents. Iterates because the zone's UTC offset at the target instant is itself
30
+ * what we're solving for (DST) - 3 rounds converges for any real-world offset change.
31
+ */
32
+ function wallClockToUtcMillis(year, month, day, hour, minute, timeZone) {
33
+ const target = Date.UTC(year, month - 1, day, hour, minute);
34
+ let guess = target;
35
+ for (let i = 0; i < 3; i++) {
36
+ const p = formatParts(new Date(guess), timeZone);
37
+ const asUtc = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
38
+ const offset = asUtc - guess;
39
+ const next = target - offset;
40
+ if (next === guess)
41
+ break;
42
+ guess = next;
43
+ }
44
+ return guess;
45
+ }
46
+ /**
47
+ * Adds `deltaMinutes` of wall-clock time (not elapsed real time) to a wall-clock reading, staying
48
+ * in pure calendar arithmetic throughout - no `timeZone`/`Intl` round trip, so this is safe to use
49
+ * for "what day/weekday is N minutes from now" even across a DST transition, where a real-time-ms
50
+ * shift and a wall-clock-minutes shift land on different calendar days.
51
+ */
52
+ function wallClockAt(wallClock, deltaMinutes) {
53
+ const naive = new Date(Date.UTC(wallClock.year, wallClock.month - 1, wallClock.day, 0, wallClock.minuteOfDay + deltaMinutes));
54
+ const year = naive.getUTCFullYear();
55
+ const month = naive.getUTCMonth() + 1;
56
+ const day = naive.getUTCDate();
57
+ const minuteOfDay = naive.getUTCHours() * 60 + naive.getUTCMinutes();
58
+ return { year, month, day, dow: dowFromDate(year, month, day), minuteOfDay };
59
+ }
60
+ function dowInRange(d, fromDow, toDow) {
61
+ return fromDow <= toDow ? d >= fromDow && d <= toDow : d >= fromDow || d <= toDow;
62
+ }
63
+ function seasonContains(season, month, day) {
64
+ if (!season?.tou_periods)
65
+ return false;
66
+ const fromMonth = season.fromMonth ?? 1;
67
+ const fromDay = season.fromDay ?? 1;
68
+ const toMonth = season.toMonth ?? 12;
69
+ const toDay = season.toDay ?? 31;
70
+ const from = fromMonth * 100 + fromDay;
71
+ const to = toMonth * 100 + toDay;
72
+ const cur = month * 100 + day;
73
+ return from <= to ? cur >= from && cur <= to : cur >= from || cur <= to;
74
+ }
75
+ function findSeason(seasons, month, day) {
76
+ if (!seasons)
77
+ return null;
78
+ for (const [name, season] of Object.entries(seasons)) {
79
+ if (seasonContains(season, month, day)) {
80
+ return { name, season };
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ /**
86
+ * Expands a season's `tou_periods` into the windows active on one specific calendar day (given
87
+ * as a Tesla weekday, Mon=0..Sun=6). A period whose `fromDayOfWeek..toDayOfWeek` includes `dow`
88
+ * contributes its own window (clamped to this day, `endMin` capped at 1440 if it crosses
89
+ * midnight); a period that crosses midnight and includes *yesterday* also contributes its
90
+ * early-morning continuation here, `trueStartMin` carrying its real (pre-midnight) start so a
91
+ * currently-active continuation can still report an accurate `currentStart`.
92
+ */
93
+ function dayPeriods(touPeriods, dow) {
94
+ const segments = [];
95
+ const prevDow = (dow + 6) % 7;
96
+ for (const [periodName, def] of Object.entries(touPeriods)) {
97
+ for (const window of def.periods ?? []) {
98
+ const fromDow = window.fromDayOfWeek ?? 0;
99
+ const toDow = window.toDayOfWeek ?? 6;
100
+ const fromMin = (window.fromHour ?? 0) * 60 + (window.fromMinute ?? 0);
101
+ const toMin = (window.toHour ?? 0) * 60 + (window.toMinute ?? 0);
102
+ const crossesMidnight = toMin <= fromMin;
103
+ if (dowInRange(dow, fromDow, toDow)) {
104
+ const endMin = crossesMidnight ? MINUTES_PER_DAY : toMin;
105
+ if (endMin > fromMin)
106
+ segments.push({ periodName, startMin: fromMin, endMin, trueStartMin: fromMin });
107
+ }
108
+ if (crossesMidnight && toMin > 0 && dowInRange(prevDow, fromDow, toDow)) {
109
+ segments.push({ periodName, startMin: 0, endMin: toMin, trueStartMin: fromMin - MINUTES_PER_DAY });
110
+ }
111
+ }
112
+ }
113
+ return segments;
114
+ }
115
+ function lookupPrice(charges, seasonName, periodName) {
116
+ if (!charges)
117
+ return null;
118
+ // A season key can be present but carry no rates at all (e.g. an empty `"Winter": {}` stub
119
+ // alongside a populated `"ALL"`) - that must fall back to ALL exactly like a missing key.
120
+ const seasonRates = charges[seasonName]?.rates ?? charges["ALL"]?.rates;
121
+ if (!seasonRates)
122
+ return null;
123
+ const value = Object.prototype.hasOwnProperty.call(seasonRates, periodName) ? seasonRates[periodName] : seasonRates["ALL"];
124
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
125
+ }
126
+ const EMPTY_RATE = { price: null, periodName: null, seasonName: null };
127
+ /**
128
+ * Resolves one grid's (buy's, or sell's) state at `wallClock`: the active period if any, and the
129
+ * next boundary regardless of whether a period is currently active - a sparse tariff's gap still
130
+ * has a "next change" (the gap's own end) and a "since" (the gap's own start), just like an active
131
+ * period does (its own end and start).
132
+ */
133
+ function scheduleAt(seasons, wallClock) {
134
+ const matched = findSeason(seasons, wallClock.month, wallClock.day);
135
+ if (!matched)
136
+ return null;
137
+ const todaySegs = dayPeriods(matched.season.tou_periods, wallClock.dow);
138
+ const current = todaySegs.find((s) => s.startMin <= wallClock.minuteOfDay && wallClock.minuteOfDay < s.endMin) ?? null;
139
+ const laterTodayStarts = todaySegs.filter((s) => s.startMin > wallClock.minuteOfDay).map((s) => s.startMin);
140
+ let nextMin = current ? current.endMin : null;
141
+ if (laterTodayStarts.length > 0) {
142
+ nextMin = nextMin === null ? Math.min(...laterTodayStarts) : Math.min(nextMin, Math.min(...laterTodayStarts));
143
+ }
144
+ else if (nextMin === null || nextMin >= MINUTES_PER_DAY) {
145
+ // Either in a gap with nothing left today, or the active period runs up to midnight -
146
+ // check tomorrow before treating midnight itself as the boundary.
147
+ const tomorrowWallClock = wallClockAt(wallClock, MINUTES_PER_DAY - wallClock.minuteOfDay);
148
+ const tomorrowMatched = findSeason(seasons, tomorrowWallClock.month, tomorrowWallClock.day);
149
+ const tomorrowSegs = tomorrowMatched ? dayPeriods(tomorrowMatched.season.tou_periods, tomorrowWallClock.dow) : [];
150
+ const continuation = current && tomorrowMatched?.name === matched.name ? tomorrowSegs.find((s) => s.startMin === 0 && s.periodName === current.periodName) : undefined;
151
+ if (continuation) {
152
+ nextMin = MINUTES_PER_DAY + continuation.endMin;
153
+ }
154
+ else if (tomorrowSegs.length > 0) {
155
+ const tomorrowFirst = MINUTES_PER_DAY + Math.min(...tomorrowSegs.map((s) => s.startMin));
156
+ nextMin = nextMin === null ? tomorrowFirst : Math.min(nextMin, tomorrowFirst);
157
+ }
158
+ }
159
+ let sinceMin;
160
+ if (current) {
161
+ sinceMin = current.trueStartMin;
162
+ }
163
+ else {
164
+ const earlierTodayEnds = todaySegs.filter((s) => s.endMin <= wallClock.minuteOfDay).map((s) => s.endMin);
165
+ if (earlierTodayEnds.length > 0) {
166
+ sinceMin = Math.max(...earlierTodayEnds);
167
+ }
168
+ else {
169
+ // Nothing has ended yet today either - the gap may have started yesterday (or earlier).
170
+ // Peek one day back, same one-day bound as the forward "tomorrow" check above.
171
+ const yesterdayWallClock = wallClockAt(wallClock, -MINUTES_PER_DAY);
172
+ const yesterdayMatched = findSeason(seasons, yesterdayWallClock.month, yesterdayWallClock.day);
173
+ const yesterdaySegs = yesterdayMatched ? dayPeriods(yesterdayMatched.season.tou_periods, yesterdayWallClock.dow) : [];
174
+ sinceMin = yesterdaySegs.length > 0 ? Math.max(...yesterdaySegs.map((s) => s.endMin)) - MINUTES_PER_DAY : null;
175
+ }
176
+ }
177
+ return {
178
+ seasonName: matched.name,
179
+ current,
180
+ nextChangeGM: nextMin === null ? null : nextMin - wallClock.minuteOfDay,
181
+ sinceGM: sinceMin === null ? null : sinceMin - wallClock.minuteOfDay,
182
+ };
183
+ }
184
+ /** Walks one calendar day at a time across the horizon, re-resolving the season fresh on each day (via pure wall-clock arithmetic, not elapsed-ms/DST-sensitive arithmetic) so a horizon crossing a season boundary re-prices and re-labels correctly. */
185
+ function collectSegments(seasons, wallClock, horizonMinutes) {
186
+ const segments = [];
187
+ let dayStartGM = -wallClock.minuteOfDay;
188
+ while (dayStartGM < horizonMinutes) {
189
+ const dayWallClock = wallClockAt(wallClock, dayStartGM);
190
+ const matched = findSeason(seasons, dayWallClock.month, dayWallClock.day);
191
+ if (matched) {
192
+ for (const seg of dayPeriods(matched.season.tou_periods, dayWallClock.dow)) {
193
+ const startGM = dayStartGM + seg.startMin;
194
+ const endGM = dayStartGM + seg.endMin;
195
+ if (endGM > 0 && startGM < horizonMinutes) {
196
+ segments.push({ startGM, endGM, periodName: seg.periodName, seasonName: matched.name });
197
+ }
198
+ }
199
+ }
200
+ dayStartGM += MINUTES_PER_DAY;
201
+ }
202
+ segments.sort((a, b) => a.startGM - b.startGM);
203
+ const merged = [];
204
+ for (const seg of segments) {
205
+ const last = merged[merged.length - 1];
206
+ if (last && last.endGM === seg.startGM && last.periodName === seg.periodName && last.seasonName === seg.seasonName) {
207
+ last.endGM = seg.endGM;
208
+ }
209
+ else {
210
+ merged.push({ ...seg });
211
+ }
212
+ }
213
+ return merged;
214
+ }
215
+ function buildUpcoming(buySeasons, buyCharges, sellSeasons, sellCharges, hasSell, wallClock, horizonMinutes, toDate) {
216
+ const buySegs = collectSegments(buySeasons, wallClock, horizonMinutes);
217
+ const sellSegs = hasSell ? collectSegments(sellSeasons, wallClock, horizonMinutes) : [];
218
+ const boundaries = new Set([0, horizonMinutes]);
219
+ const addBoundary = (gm) => {
220
+ if (gm > 0 && gm < horizonMinutes)
221
+ boundaries.add(gm);
222
+ };
223
+ for (const s of buySegs) {
224
+ addBoundary(s.startGM);
225
+ addBoundary(s.endGM);
226
+ }
227
+ for (const s of sellSegs) {
228
+ addBoundary(s.startGM);
229
+ addBoundary(s.endGM);
230
+ }
231
+ const sorted = [...boundaries].sort((a, b) => a - b);
232
+ const periods = [];
233
+ for (let i = 0; i < sorted.length - 1; i++) {
234
+ const segStart = sorted[i];
235
+ const segEnd = sorted[i + 1];
236
+ if (segStart === segEnd)
237
+ continue;
238
+ const buyAt = buySegs.find((s) => s.startGM <= segStart && segStart < s.endGM);
239
+ const sellAt = sellSegs.find((s) => s.startGM <= segStart && segStart < s.endGM);
240
+ periods.push({
241
+ start: toDate(segStart),
242
+ end: toDate(segEnd),
243
+ buy: buyAt ? { price: lookupPrice(buyCharges, buyAt.seasonName, buyAt.periodName), periodName: buyAt.periodName, seasonName: buyAt.seasonName } : EMPTY_RATE,
244
+ sell: sellAt ? { price: lookupPrice(sellCharges, sellAt.seasonName, sellAt.periodName), periodName: sellAt.periodName, seasonName: sellAt.seasonName } : EMPTY_RATE,
245
+ });
246
+ }
247
+ return periods;
248
+ }
249
+ /**
250
+ * Resolves the current buy/sell time-of-use rate for a Tariff V2 object at a given instant.
251
+ * `tariff` carries no timezone; the caller must supply the site's IANA zone (e.g. from
252
+ * `site_info.installation_time_zone`) so wall-clock period boundaries match correctly.
253
+ */
254
+ export function getTariffPeriods(tariff, now, opts) {
255
+ if (!tariff?.seasons || !tariff?.energy_charges)
256
+ return null;
257
+ if (!opts?.timeZone)
258
+ throw new Error("getTariffPeriods requires opts.timeZone");
259
+ const timeZone = opts.timeZone;
260
+ const wallClock = getWallClock(now, timeZone);
261
+ const buySchedule = scheduleAt(tariff.seasons, wallClock);
262
+ if (!buySchedule?.current)
263
+ return null;
264
+ const sellSeasons = tariff.sell_tariff?.seasons ?? tariff.seasons;
265
+ const sellSchedule = tariff.sell_tariff ? scheduleAt(sellSeasons, wallClock) : null;
266
+ const buyRate = { price: lookupPrice(tariff.energy_charges, buySchedule.seasonName, buySchedule.current.periodName), periodName: buySchedule.current.periodName, seasonName: buySchedule.seasonName };
267
+ const sellRate = sellSchedule?.current
268
+ ? { price: lookupPrice(tariff.sell_tariff.energy_charges, sellSchedule.seasonName, sellSchedule.current.periodName), periodName: sellSchedule.current.periodName, seasonName: sellSchedule.seasonName }
269
+ : EMPTY_RATE;
270
+ // Boundaries are wall-clock minute deltas, so converting one back to an instant means
271
+ // re-deriving the target wall-clock label and reconverting *that*, not adding elapsed
272
+ // real minutes to `now` - the two differ across a DST transition.
273
+ const toDate = (gm) => {
274
+ const target = wallClockAt(wallClock, gm);
275
+ const hour = Math.floor(target.minuteOfDay / 60);
276
+ const minute = target.minuteOfDay % 60;
277
+ return new Date(wallClockToUtcMillis(target.year, target.month, target.day, hour, minute, timeZone));
278
+ };
279
+ // `scheduleAt` reports a next-boundary GM even for a grid that's currently in a gap (e.g. a
280
+ // sell/export window not open yet), so combining via the sell side's own next boundary - not
281
+ // skipping it just because sell has no active period right now - catches "sell starts" too.
282
+ const nextChangeGM = sellSchedule?.nextChangeGM != null ? Math.min(buySchedule.nextChangeGM, sellSchedule.nextChangeGM) : buySchedule.nextChangeGM;
283
+ // When buy and sell schedules differ, the interval the returned pair is valid for only began
284
+ // once BOTH sides' current *states* began - the later of the two, not just buy's. `sinceGM`
285
+ // covers sell being in a gap too (e.g. an export window that already closed), not only sell
286
+ // having its own active period. `buySchedule.sinceGM` is always non-null: buy is guaranteed to
287
+ // have an active `current` period at this point (checked above), and that branch always sets it.
288
+ const currentStartGM = sellSchedule?.sinceGM != null ? Math.max(buySchedule.sinceGM, sellSchedule.sinceGM) : buySchedule.sinceGM;
289
+ const resolution = {
290
+ buy: buyRate,
291
+ sell: sellRate,
292
+ currentStart: toDate(currentStartGM),
293
+ nextChange: toDate(nextChangeGM),
294
+ currency: typeof tariff.currency === "string" ? tariff.currency : null,
295
+ upcoming: null,
296
+ };
297
+ if (opts.horizonHours) {
298
+ resolution.upcoming = buildUpcoming(tariff.seasons, tariff.energy_charges, sellSeasons, tariff.sell_tariff?.energy_charges, !!tariff.sell_tariff, wallClock, opts.horizonHours * 60, toDate);
299
+ }
300
+ return resolution;
301
+ }
302
+ //# sourceMappingURL=tariff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tariff.js","sourceRoot":"","sources":["../src/tariff.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ export default class TeslaFleetApi {
18
18
  partner?: Partner;
19
19
  user?: User;
20
20
  vehicle?: Vehicle;
21
+ debug: boolean;
21
22
  constructor(options: {
22
23
  accessToken?: string;
23
24
  region?: Region;
@@ -27,7 +28,12 @@ export default class TeslaFleetApi {
27
28
  partnerScope?: boolean;
28
29
  userScope?: boolean;
29
30
  vehicleScope?: boolean;
31
+ debug?: boolean;
30
32
  });
33
+ _response(resp: Response): Promise<{
34
+ status: number;
35
+ data: any;
36
+ }>;
31
37
  /**
32
38
  * Make a request to the Tesla Fleet API.
33
39
  * @param method
@@ -47,5 +53,6 @@ export default class TeslaFleetApi {
47
53
  * @returns A dictionary of vehicles and energy sites, each with an array of those products
48
54
  */
49
55
  products_by_type(): Promise<ProductsByType>;
56
+ loadPrivateKey(path: string): Promise<void>;
50
57
  }
51
58
  export {};
@@ -11,6 +11,8 @@ const servers = {
11
11
  export default class TeslaFleetApi {
12
12
  constructor(options) {
13
13
  this.server = null;
14
+ this.debug = false;
15
+ this.debug = !!options.debug;
14
16
  this.accessToken = options.accessToken;
15
17
  if (options.server) {
16
18
  this.server = options.server;
@@ -21,7 +23,7 @@ export default class TeslaFleetApi {
21
23
  else {
22
24
  throw new Error("Either server or region must be provided.");
23
25
  }
24
- console.debug(`Using server ${this.server}`);
26
+ this.debug && console.debug(`Using server ${this.server}`);
25
27
  if (options.chargingScope !== false) {
26
28
  this.charging = new Charging(this);
27
29
  }
@@ -38,6 +40,9 @@ export default class TeslaFleetApi {
38
40
  this.vehicle = new Vehicle(this);
39
41
  }
40
42
  }
43
+ async _response(resp) {
44
+ return { status: resp.status, data: await resp.json() };
45
+ }
41
46
  /**
42
47
  * Make a request to the Tesla Fleet API.
43
48
  * @param method
@@ -53,15 +58,15 @@ export default class TeslaFleetApi {
53
58
  if (method === "GET" && json !== null) {
54
59
  throw new Error("GET requests cannot have a body.");
55
60
  }
56
- console.debug(`Sending request to ${path}`);
61
+ this.debug && console.debug(`Sending request to ${path}`);
57
62
  // Remove null and undefined values from params and json
58
63
  if (params) {
59
64
  params = Object.fromEntries(Object.entries(params).filter(([_, v]) => v != null));
60
- console.debug(`Parameters: ${JSON.stringify(params)}`);
65
+ this.debug && console.debug(`Parameters: ${JSON.stringify(params)}`);
61
66
  }
62
67
  if (json) {
63
68
  json = Object.fromEntries(Object.entries(json).filter(([_, v]) => v != null));
64
- console.debug(`Body: ${JSON.stringify(json)}`);
69
+ this.debug && console.debug(`Body: ${JSON.stringify(json)}`);
65
70
  }
66
71
  const headers = {
67
72
  Authorization: `Bearer ${this.accessToken}`,
@@ -73,15 +78,13 @@ export default class TeslaFleetApi {
73
78
  method,
74
79
  headers,
75
80
  body: json ? JSON.stringify(json) : null,
76
- }).then((res) => {
77
- return res
78
- .json()
79
- .then((data) => {
80
- if (res.ok)
81
- return data;
82
- return Promise.reject({ status: res.status, data });
83
- }, (e) => Promise.reject(e));
84
- });
81
+ })
82
+ .then(this._response)
83
+ .then(({ status, data }) => {
84
+ if (status <= 299)
85
+ return data;
86
+ return Promise.reject({ status, data });
87
+ }, (e) => Promise.reject({ error: e }));
85
88
  }
86
89
  /**
87
90
  * Returns products mapped to user.
@@ -100,5 +103,18 @@ export default class TeslaFleetApi {
100
103
  energy_sites: products.filter((product) => "energy_site_id" in product),
101
104
  }));
102
105
  }
106
+ async loadPrivateKey(path) {
107
+ // Try read file, if not create it
108
+ return (await import("fs")).promises.readFile(path, "utf8").then((key) => {
109
+ this.accessToken = key;
110
+ }).catch(async () => {
111
+ // Create SECP256R1 private key and save it as a pem file at path
112
+ const { privateKey } = (await import("crypto")).generateKeyPairSync("ec", {
113
+ namedCurve: "secp256r1",
114
+ publicKeyEncoding: { type: "spki", format: "pem" },
115
+ privateKeyEncoding: { type: "pkcs8", format: "pem" },
116
+ });
117
+ });
118
+ }
103
119
  }
104
120
  //# sourceMappingURL=teslafleetapi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"teslafleetapi.js","sourceRoot":"","sources":["../src/teslafleetapi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"teslafleetapi.js","sourceRoot":"","sources":["../src/teslafleetapi.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,10 @@ type Metadata = {
12
12
  };
13
13
  export default class Telemetry extends TeslaFleetApi {
14
14
  constructor(accessToken: string, region?: Region);
15
+ _response(resp: Response): Promise<{
16
+ status: number;
17
+ data: any;
18
+ }>;
15
19
  /**
16
20
  * Test the connection to Teslemetry
17
21
  */
@@ -1,7 +1,21 @@
1
1
  import TeslaFleetApi from "./teslafleetapi.js";
2
2
  export default class Telemetry extends TeslaFleetApi {
3
3
  constructor(accessToken, region = "api") {
4
- super({ accessToken, server: `https://${region}.teslemetry.com`, partnerScope: false, userScope: false });
4
+ super({
5
+ accessToken,
6
+ server: `https://${region}.teslemetry.com`,
7
+ partnerScope: false,
8
+ userScope: false,
9
+ });
10
+ }
11
+ async _response(resp) {
12
+ if (resp.headers.has("x-region")) {
13
+ const region = resp.headers.get("x-region")?.toLowerCase();
14
+ if (region) {
15
+ this.server = `https://${region}.teslemetry.com`;
16
+ }
17
+ }
18
+ return super._response(resp);
5
19
  }
6
20
  /**
7
21
  * Test the connection to Teslemetry
@@ -1 +1 @@
1
- {"version":3,"file":"teslemetry.js","sourceRoot":"","sources":["../src/teslemetry.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAc/C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,aAAa;IAChD,YAAY,WAAmB,EAAE,SAAiB,KAAK;QACnD,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,MAAM,iBAAiB,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC9E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ,CAAC,aAAa,GAAG,IAAI;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC3D,IAAI,aAAa,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,GAAG,WAAW,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAAC;YAC5E,CAAC;YACD,OAAO,QAAQ,CAAC;QACpB,CAAC,CAAC,CAAC;IACP,CAAC;CACJ"}
1
+ {"version":3,"file":"teslemetry.js","sourceRoot":"","sources":["../src/teslemetry.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAc/C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,aAAa;IAClD,YAAY,WAAmB,EAAE,SAAiB,KAAK;QACrD,KAAK,CAAC;YACJ,WAAW;YACX,MAAM,EAAE,WAAW,MAAM,iBAAiB;YAC1C,YAAY,EAAE,KAAK;YACnB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAc;QAC5B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,GAAG,WAAW,MAAM,iBAAiB,CAAC;YACnD,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC5E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ,CAAC,aAAa,GAAG,IAAI;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC7D,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC,MAAM,GAAG,WAAW,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAAC;YAC1E,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -102,20 +102,49 @@ export type UserSettings = {
102
102
  breaker_alert_enabled: boolean;
103
103
  off_grid_vehicle_charging_enabled: boolean;
104
104
  };
105
+ export type TariffPeriodWindow = {
106
+ fromDayOfWeek?: number;
107
+ toDayOfWeek?: number;
108
+ fromHour?: number;
109
+ toHour?: number;
110
+ fromMinute?: number;
111
+ toMinute?: number;
112
+ };
113
+ export type TouPeriods = Record<string, {
114
+ periods: TariffPeriodWindow[];
115
+ }>;
116
+ export type Season = {
117
+ fromDay?: number;
118
+ toDay?: number;
119
+ fromMonth?: number;
120
+ toMonth?: number;
121
+ tou_periods?: TouPeriods;
122
+ };
123
+ export type EnergyCharges = Record<string, {
124
+ rates?: Record<string, number>;
125
+ }>;
126
+ export type SellTariff = {
127
+ name?: string;
128
+ utility?: string;
129
+ daily_charges?: Record<string, any>[];
130
+ demand_charges?: Record<string, any>;
131
+ energy_charges: EnergyCharges;
132
+ seasons?: Record<string, Season>;
133
+ };
105
134
  export type TariffContentV2 = {
106
135
  version: number;
107
- monthly_minimum_bill: number;
108
- min_applicable_demand: number;
109
- max_applicable_demand: number;
110
- monthly_charges: number;
136
+ monthly_minimum_bill?: number;
137
+ min_applicable_demand?: number;
138
+ max_applicable_demand?: number;
139
+ monthly_charges?: number;
111
140
  utility: string;
112
141
  code: string;
113
142
  name: string;
114
143
  currency: string;
115
144
  daily_charges: Record<string, any>[];
116
- daily_demand_charges: Record<string, any>;
145
+ daily_demand_charges?: Record<string, any>;
117
146
  demand_charges: Record<string, any>;
118
- energy_charges: Record<string, any>;
119
- seasons: Record<string, any>[];
120
- sell_tariff: Record<string, any>;
147
+ energy_charges: EnergyCharges;
148
+ seasons: Record<string, Season>;
149
+ sell_tariff?: SellTariff;
121
150
  };
package/dist/vehicle.d.ts CHANGED
@@ -4,8 +4,11 @@ import { OptionsResponse } from "./types/responses.js";
4
4
  import { VehicleResponse } from "./types/vehicle.js";
5
5
  import { VehicleDataResponse } from "./types/vehicle_data.js";
6
6
  import VehicleSpecific from "./vehiclespecific.js";
7
+ import VehicleSigned from "./vehiclesigned.js";
7
8
  export default class Vehicle {
8
9
  parent: TeslaFleetApi;
10
+ /** Fallback private key for `signed()` when a call site doesn't pass one explicitly. */
11
+ private_key?: Buffer;
9
12
  constructor(parent: TeslaFleetApi);
10
13
  /**
11
14
  * Returns a class for a single vehicle.
@@ -13,6 +16,15 @@ export default class Vehicle {
13
16
  * @returns
14
17
  */
15
18
  specific(vin: string): VehicleSpecific;
19
+ /**
20
+ * Returns a class for a single vehicle that signs commands with the
21
+ * Tesla Vehicle Command Protocol and dispatches them through the Fleet
22
+ * API `/signed_command` endpoint, instead of the plaintext REST commands.
23
+ * @param vin
24
+ * @param private_key Raw 32-byte P-256 private key scalar. Falls back to `this.private_key`.
25
+ * @param public_key Uncompressed P-256 public key point. Derived from `private_key` if omitted.
26
+ */
27
+ signed(vin: string, private_key?: Buffer, public_key?: Buffer): VehicleSigned;
16
28
  /**
17
29
  * Return the vehicle model name
18
30
  * @param vin
package/dist/vehicle.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { ClimateModes, Seats } from "./types/commands.js";
2
2
  import VehicleSpecific from "./vehiclespecific.js";
3
+ import VehicleSigned from "./vehiclesigned.js";
3
4
  const Models = {
4
5
  S: "Model S",
5
6
  "3": "Model 3",
@@ -20,6 +21,17 @@ export default class Vehicle {
20
21
  specific(vin) {
21
22
  return new VehicleSpecific(this, vin);
22
23
  }
24
+ /**
25
+ * Returns a class for a single vehicle that signs commands with the
26
+ * Tesla Vehicle Command Protocol and dispatches them through the Fleet
27
+ * API `/signed_command` endpoint, instead of the plaintext REST commands.
28
+ * @param vin
29
+ * @param private_key Raw 32-byte P-256 private key scalar. Falls back to `this.private_key`.
30
+ * @param public_key Uncompressed P-256 public key point. Derived from `private_key` if omitted.
31
+ */
32
+ signed(vin, private_key, public_key) {
33
+ return new VehicleSigned(this, vin, private_key, public_key);
34
+ }
23
35
  /**
24
36
  * Return the vehicle model name
25
37
  * @param vin