@teslemetry/pro 0.0.0-stage → 0.1.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/README.md +279 -2
- package/dist/index.cjs +5854 -0
- package/dist/index.d.cts +9454 -0
- package/dist/index.d.mts +9454 -0
- package/dist/index.mjs +5834 -0
- package/package.json +56 -4
package/README.md
CHANGED
|
@@ -1,3 +1,280 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Teslemetry for Business TypeScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The official TypeScript/JavaScript client for the [Teslemetry for Business](https://teslemetry.pro) API.
|
|
4
|
+
|
|
5
|
+
This library provides a strictly typed, easy-to-use wrapper for interacting with Tesla vehicles and energy sites. It supports standard API commands, state retrieval, and real-time streaming data via Server-Sent Events (SSE).
|
|
6
|
+
|
|
7
|
+
## 📚 Documentation
|
|
8
|
+
|
|
9
|
+
- **[Teslemetry API Reference](https://api.teslemetry.pro/docs)**: Detailed documentation for all API endpoints, parameters, and response values.
|
|
10
|
+
- **[Tesla Fleet API](https://developer.tesla.com/docs/fleet-api)**: Official Tesla documentation for underlying vehicle commands and data.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @teslemetry/pro
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { Teslemetry } from "@teslemetry/pro";
|
|
22
|
+
|
|
23
|
+
// Initialize with your access token
|
|
24
|
+
const teslemetry = new Teslemetry(process.env.TESLEMETRY_ACCESS_TOKEN!);
|
|
25
|
+
|
|
26
|
+
// Get a specific vehicle
|
|
27
|
+
const vin = "5YJ...";
|
|
28
|
+
const vehicle = teslemetry.getVehicle(vin);
|
|
29
|
+
|
|
30
|
+
// 1. Get Vehicle State
|
|
31
|
+
const state = await vehicle.api.state();
|
|
32
|
+
console.log("Vehicle State:", state);
|
|
33
|
+
|
|
34
|
+
// 2. Send a Command (e.g., Flash Lights)
|
|
35
|
+
await vehicle.api.flashLights();
|
|
36
|
+
|
|
37
|
+
// 3. Stream Real-time Data
|
|
38
|
+
vehicle.sse.onSignal("VehicleSpeed", (speed) => {
|
|
39
|
+
console.log(`Current Speed: ${speed} mph`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Connect to the stream
|
|
43
|
+
await teslemetry.sse.connect();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
### Initialization
|
|
49
|
+
|
|
50
|
+
The `Teslemetry` class is the main entry point. It automatically handles region detection (NA/EU) upon the first request, or you can specify it manually.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { Teslemetry } from "@teslemetry/pro";
|
|
54
|
+
|
|
55
|
+
// Automatic region detection (recommended)
|
|
56
|
+
const teslemetry = new Teslemetry("YOUR_ACCESS_TOKEN");
|
|
57
|
+
|
|
58
|
+
// Manual region specification
|
|
59
|
+
const teslemetryEu = new Teslemetry("YOUR_ACCESS_TOKEN", { region: "eu" });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Vehicle API
|
|
63
|
+
|
|
64
|
+
Use `getVehicle(vin)` to interact with a vehicle. This returns an object containing two specialized handlers:
|
|
65
|
+
- `api`: for standard REST API calls (commands, state).
|
|
66
|
+
- `sse`: for real-time streaming.
|
|
67
|
+
|
|
68
|
+
#### Commands & State
|
|
69
|
+
The `.api` property contains methods for all supported Tesla commands.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const vehicle = teslemetry.getVehicle("VIN...");
|
|
73
|
+
|
|
74
|
+
// Get full vehicle data
|
|
75
|
+
const data = await vehicle.api.vehicleData();
|
|
76
|
+
|
|
77
|
+
// Climate Control
|
|
78
|
+
await vehicle.api.startAutoConditioning();
|
|
79
|
+
await vehicle.api.setTemps(20, 20); // Driver, Passenger (Celsius)
|
|
80
|
+
|
|
81
|
+
// Charging
|
|
82
|
+
await vehicle.api.startCharging();
|
|
83
|
+
await vehicle.api.setChargeLimit(80);
|
|
84
|
+
|
|
85
|
+
// Locking
|
|
86
|
+
await vehicle.api.lockDoors();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> **Note:** For a comprehensive list of all available methods and their parameters, please refer to the [Teslemetry for Business API Docs](https://api.teslemetry.pro/docs). The SDK methods map 1:1 with these endpoints.
|
|
90
|
+
|
|
91
|
+
#### Real-time Streaming (SSE)
|
|
92
|
+
The `.sse` property allows you to subscribe to specific vehicle signals.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Subscribe to signals
|
|
96
|
+
vehicle.sse.onSignal("PackCurrent", (val) => console.log("Current:", val));
|
|
97
|
+
vehicle.sse.onSignal("ChargerVoltage", (val) => console.log("Voltage:", val));
|
|
98
|
+
|
|
99
|
+
// Monitor connection status
|
|
100
|
+
teslemetry.sse.on("connect", () => console.log("Stream Connected"));
|
|
101
|
+
teslemetry.sse.on("disconnect", () => console.log("Stream Disconnected"));
|
|
102
|
+
|
|
103
|
+
// Start streaming (connects to the shared Teslemetry stream)
|
|
104
|
+
await teslemetry.sse.connect();
|
|
105
|
+
|
|
106
|
+
// Stop streaming
|
|
107
|
+
teslemetry.sse.disconnect();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
##### Stream errors and reconnecting
|
|
111
|
+
|
|
112
|
+
The stream reconnects automatically with exponential backoff (2 seconds,
|
|
113
|
+
doubling up to 60), re-resolving your access token callback on every attempt.
|
|
114
|
+
`connect` is emitted once the server has started answering, not when the
|
|
115
|
+
request is sent. Each failed attempt, and each connection the server ends,
|
|
116
|
+
emits a `stream_error` event with the error, the HTTP status (when one was
|
|
117
|
+
received), and the number of consecutive failures.
|
|
118
|
+
|
|
119
|
+
Authentication failures are handled differently: after a `401`/`403` the
|
|
120
|
+
stream reconnects once immediately (so a refreshed token can take over), and
|
|
121
|
+
if that attempt is also rejected it **stops reconnecting** and emits a
|
|
122
|
+
terminal `auth_failure` event instead of looping forever. Listen for it to
|
|
123
|
+
prompt the user to re-authenticate, then call `connect()` again to resume.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
teslemetry.sse.on("stream_error", ({ error, status, retries }) => {
|
|
127
|
+
console.warn(`Stream attempt ${retries} failed`, status, error);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
teslemetry.sse.on("auth_failure", (error) => {
|
|
131
|
+
// error is a TeslemetryStreamAuthError with a .status of 401 or 403
|
|
132
|
+
console.error("Streaming credentials rejected, reauthorize:", error.status);
|
|
133
|
+
// ...surface reauth to the user, then: await teslemetry.sse.connect();
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
##### Selecting topics
|
|
138
|
+
|
|
139
|
+
By default the stream sends every event applicable to every product you can
|
|
140
|
+
access (legacy-all mode). Pass `stream.topics` to receive only the events you
|
|
141
|
+
need - either exact wire topic names or the bundled presets from
|
|
142
|
+
`SSE_TOPIC_PRESETS` (`vehicleFull`, `vehicleCore`, `energyLive`,
|
|
143
|
+
`energyFullState`, `account`, `products`), which are expanded client-side to exact names
|
|
144
|
+
before the connection opens:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// getToken is any () => Promise<string> that returns a current access token
|
|
148
|
+
const getToken = async () => process.env.TESLEMETRY_ACCESS_TOKEN!;
|
|
149
|
+
|
|
150
|
+
const teslemetry = new Teslemetry(getToken, {
|
|
151
|
+
stream: { topics: ["energyLive", "credits"] },
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Omitting `topics` entirely preserves legacy-all behavior forever - it is
|
|
156
|
+
never reinterpreted as a narrower default.
|
|
157
|
+
|
|
158
|
+
##### Energy tariffs and the composed site-info view
|
|
159
|
+
|
|
160
|
+
`site_info` events no longer carry `tariff_content`/`tariff_content_v2` -
|
|
161
|
+
subscribe separately to `tariff_content_v2`, whose body is `null` when Tesla
|
|
162
|
+
explicitly removes the tariff (not merely "no update yet"):
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
site.sse.on("tariff_content_v2", (event) => {
|
|
166
|
+
if (event.tariff_content_v2 === null) {
|
|
167
|
+
console.log("Tariff was removed");
|
|
168
|
+
} else {
|
|
169
|
+
console.log("Tariff updated:", event.tariff_content_v2);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`site.sse.siteInfoDocument` merges the cached slim `site_info` with the last
|
|
175
|
+
received tariff piece into a single whole-document view, resembling the full
|
|
176
|
+
REST `site_info` response:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
const document = site.sse.siteInfoDocument; // undefined until site_info is cached
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`getTariffPeriods` resolves the current buy/sell rate (and, optionally, the
|
|
183
|
+
upcoming schedule) from a `tariff_content_v2` body - pass the site's IANA
|
|
184
|
+
`installation_time_zone`, since the tariff itself carries no timezone:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { getTariffPeriods, type TariffContentV2 } from "@teslemetry/pro";
|
|
188
|
+
|
|
189
|
+
const tariff = document?.tariff_content_v2 as TariffContentV2 | null;
|
|
190
|
+
if (tariff) {
|
|
191
|
+
const resolution = getTariffPeriods(tariff, new Date(), {
|
|
192
|
+
timeZone: document.installation_time_zone,
|
|
193
|
+
});
|
|
194
|
+
console.log(resolution?.buy.price);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Energy API
|
|
199
|
+
|
|
200
|
+
Interact with Tesla Energy sites (Solar, Powerwall, Wall Connector).
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Get an energy site instance by Site ID
|
|
204
|
+
const site = teslemetry.energySite(12345);
|
|
205
|
+
|
|
206
|
+
// Get site status and info
|
|
207
|
+
const status = await site.getLiveStatus();
|
|
208
|
+
const info = await site.getSiteInfo();
|
|
209
|
+
|
|
210
|
+
// Control operations
|
|
211
|
+
await site.setBackupReserve(20); // Set backup reserve to 20%
|
|
212
|
+
await site.setOperationMode("autonomous");
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Account & Discovery
|
|
216
|
+
|
|
217
|
+
If you don't know your VINs or Site IDs, you can discover every product that customers have consented to share with your business.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// Fetch all consented vehicles and energy sites (follows every page)
|
|
221
|
+
const products = await teslemetry.createProducts();
|
|
222
|
+
|
|
223
|
+
// Access discovered vehicles
|
|
224
|
+
for (const vin in products.vehicles) {
|
|
225
|
+
const vehicle = products.vehicles[vin];
|
|
226
|
+
console.log(`Found ${vehicle.name} (${vehicle.vin})`);
|
|
227
|
+
|
|
228
|
+
// Use the API immediately (a read, not a command)
|
|
229
|
+
await vehicle.api.state();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Access discovered energy sites
|
|
233
|
+
for (const siteId in products.energySites) {
|
|
234
|
+
const site = products.energySites[siteId];
|
|
235
|
+
console.log(`Found Site: ${site.name} (${site.id})`);
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Filtering products
|
|
240
|
+
|
|
241
|
+
`getProducts()` returns one page of consented products. Pass `type` (`"vehicle"` or `"energy"`), `ref` (only the customer with that reference), `since` (only consents granted at or after that time), and `limit`/`cursor` for pagination:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const page = await teslemetry.api.getProducts({ type: "vehicle", limit: 50 });
|
|
245
|
+
console.log(page.count, page.response, page.next_cursor);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Product events
|
|
249
|
+
|
|
250
|
+
The stream emits a `product` event each time a vehicle or energy site joins or leaves your business (`event` is `product.joined` or `product.left`, with `type`, `vin` or `energy_site_id`, `customer`, `cause` on `product.left`, and `timestamp`). Select it with the `products` preset or the exact `product` topic:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
teslemetry.sse.on("product", (event) => {
|
|
254
|
+
console.log(event.event, event.vin ?? event.energy_site_id);
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The business webhook receives the same event as `product.joined`/`product.left`.
|
|
259
|
+
|
|
260
|
+
### Business configuration and webhook
|
|
261
|
+
|
|
262
|
+
The generated client contains business-only functions for `/api/business/config/default*` (`getApiBusinessConfigDefault`, `postApiBusinessConfigDefault`, `putApiBusinessConfigDefault`, `patchApiBusinessConfigDefault`, `deleteApiBusinessConfigDefault`, `getApiBusinessConfigDefaultStatus`: the default telemetry configuration applied to shared vehicles) and `/api/business/webhook` (`getApiBusinessWebhook`, `putApiBusinessWebhook`, `patchApiBusinessWebhook`, `deleteApiBusinessWebhook`: the webhook that receives telemetry from every vehicle shared with your business). `@teslemetry/pro` does not export these functions yet; call the endpoints with `teslemetry.client` or any HTTP client, as described in the [API reference](https://api.teslemetry.pro/docs).
|
|
263
|
+
|
|
264
|
+
### Error Handling
|
|
265
|
+
|
|
266
|
+
The SDK throws standard Javascript `Error` objects for configuration issues and specific errors for API failures. Streaming errors (like connection drops) are emitted via the stream error handler or specific exception classes.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { TeslemetryStreamConnectionError } from "@teslemetry/pro";
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
await vehicle.api.wakeUp();
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error("Failed to wake up vehicle:", error);
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
Apache-2.0
|