@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 CHANGED
@@ -1,3 +1,280 @@
1
- # Temporary Holding Version
1
+ # Teslemetry for Business TypeScript SDK
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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