@teslemetry/api 0.0.1 → 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,18 +1,13 @@
1
- # Teslemetry TypeScript API
1
+ # Teslemetry TypeScript SDK
2
2
 
3
3
  The official TypeScript/JavaScript client for the [Teslemetry](https://teslemetry.com) API.
4
4
 
5
- This library provides a convenient wrapper for interacting with Tesla vehicles and energy sites via the Teslemetry service, including support for standard API commands and real-time streaming data (Server-Sent Events).
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
6
 
7
- Further information about each API method can be found in the [Teslemetry API Documentation](https://teslemetry.com/docs/api), and [Tesla Fleet API Documentation](https://developer.tesla.com/docs/fleet-api/endpoints/vehicle-commands).
7
+ ## 📚 Documentation
8
8
 
9
- ## Features
10
-
11
- - 🚗 **Vehicle API**: Full control and state retrieval (lock/unlock, climate, charging, etc.).
12
- - ⚡ **Energy API**: Monitor and control Tesla Energy sites (Solar, Powerwall).
13
- - 📡 **Streaming (SSE)**: Real-time vehicle data streaming with `TeslemetryStream`.
14
- - 🌍 **Region Aware**: Automatic region detection and handling (NA/EU).
15
- - 🔒 **Type-Safe**: Built with TypeScript for full type inference and safety.
9
+ - **[Teslemetry API Reference](https://api.teslemetry.com/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.
16
11
 
17
12
  ## Installation
18
13
 
@@ -29,26 +24,26 @@ yarn add @teslemetry/api
29
24
  ```typescript
30
25
  import { Teslemetry } from "@teslemetry/api";
31
26
 
32
- const token = process.env.TESLEMETRY_ACCESS_TOKEN;
33
- const vin = process.env.TESLEMETRY_VIN;
34
-
35
- const teslemetry = new Teslemetry(token);
27
+ // Initialize with your access token
28
+ const teslemetry = new Teslemetry(process.env.TESLEMETRY_ACCESS_TOKEN);
36
29
 
37
- // Get a vehicle instance
30
+ // Get a specific vehicle
31
+ const vin = "5YJ...";
38
32
  const vehicle = teslemetry.getVehicle(vin);
39
33
 
40
- // API: Get vehicle state
34
+ // 1. Get Vehicle State
41
35
  const state = await vehicle.api.state();
42
- console.log("Battery Level:", state.charge_state.battery_level);
36
+ console.log("Vehicle State:", state);
43
37
 
44
- // API: Send a command
38
+ // 2. Send a Command (e.g., Flash Lights)
45
39
  await vehicle.api.flashLights();
46
40
 
47
- // Stream: Listen for real-time data
41
+ // 3. Stream Real-time Data
48
42
  vehicle.sse.onSignal("Speed", (speed) => {
49
- console.log(`Current Speed: ${speed}`);
43
+ console.log(`Current Speed: ${speed} mph`);
50
44
  });
51
45
 
46
+ // Connect to the stream
52
47
  await teslemetry.sse.connect();
53
48
  ```
54
49
 
@@ -56,71 +51,120 @@ await teslemetry.sse.connect();
56
51
 
57
52
  ### Initialization
58
53
 
59
- Initialize the `Teslemetry` client with your access token. You can optionally specify a region ("na" or "eu"), otherwise it will be automatically detected.
54
+ 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.
60
55
 
61
56
  ```typescript
62
57
  import { Teslemetry } from "@teslemetry/api";
63
58
 
59
+ // Automatic region detection (recommended)
64
60
  const teslemetry = new Teslemetry("YOUR_ACCESS_TOKEN");
65
- // or with specific region
66
- const teslemetryEu = new Teslemetry("YOUR_ACCESS_TOKEN", "eu");
61
+
62
+ // Manual region specification
63
+ const teslemetryEu = new Teslemetry("YOUR_ACCESS_TOKEN", { region: "eu" });
67
64
  ```
68
65
 
69
- ### Vehicle Control
66
+ ### Vehicle API
70
67
 
71
- The `getVehicle(vin)` method returns an object containing both `api` and `sse` handlers for a specific vehicle.
68
+ Use `getVehicle(vin)` to interact with a vehicle. This returns an object containing two specialized handlers:
69
+ - `api`: for standard REST API calls (commands, state).
70
+ - `sse`: for real-time streaming.
71
+
72
+ #### Commands & State
73
+ The `.api` property contains methods for all supported Tesla commands.
72
74
 
73
75
  ```typescript
74
- const myCar = teslemetry.getVehicle("VIN123456789");
76
+ const vehicle = teslemetry.getVehicle("VIN...");
77
+
78
+ // Get full vehicle data
79
+ const data = await vehicle.api.vehicleData();
75
80
 
76
- // Get detailed vehicle data
77
- const vehicleData = await myCar.api.vehicleData();
81
+ // Climate Control
82
+ await vehicle.api.autoConditioningStart();
83
+ await vehicle.api.setTemps(20, 20); // Driver, Passenger (Celsius)
78
84
 
79
- // Commands
80
- await myCar.api.doorLock();
81
- await myCar.api.autoConditioningStart();
82
- await myCar.api.chargeStart();
85
+ // Charging
86
+ await vehicle.api.chargeStart();
87
+ await vehicle.api.setChargeLimit(80);
88
+
89
+ // Locking
90
+ await vehicle.api.lockDoors();
83
91
  ```
84
92
 
85
- ### Real-time Streaming (SSE)
93
+ > **Note:** For a comprehensive list of all available methods and their parameters, please refer to the [Teslemetry API Docs](https://teslemetry.com/docs/api). The SDK methods map 1:1 with these endpoints.
86
94
 
87
- Teslemetry supports streaming vehicle data updates via Server-Sent Events.
95
+ #### Real-time Streaming (SSE)
96
+ The `.sse` property allows you to subscribe to specific vehicle signals.
88
97
 
89
98
  ```typescript
90
- const myCar = teslemetry.getVehicle("VIN123456789");
91
-
92
- // Subscribe to specific signals
93
- myCar.sse.onSignal("PackCurrent", (val) => console.log("Current:", val));
94
- myCar.sse.onSignal("ChargerVoltage", (val) => console.log("Voltage:", val));
99
+ // Subscribe to signals
100
+ vehicle.sse.onSignal("PackCurrent", (val) => console.log("Current:", val));
101
+ vehicle.sse.onSignal("ChargerVoltage", (val) => console.log("Voltage:", val));
95
102
 
96
- // Handle connection status
103
+ // Monitor connection status
97
104
  teslemetry.sse.onConnection((isConnected) => {
98
- console.log(isConnected ? "Connected!" : "Disconnected");
105
+ console.log(isConnected ? "Stream Connected" : "Stream Disconnected");
99
106
  });
100
107
 
101
- // Start the stream
108
+ // Start streaming (connects to the shared Teslemetry stream)
102
109
  await teslemetry.sse.connect();
103
110
 
104
111
  // Stop streaming
105
112
  teslemetry.sse.disconnect();
106
113
  ```
107
114
 
108
- ### Energy Sites
115
+ ### Energy API
109
116
 
110
- Interact with Tesla Energy products.
117
+ Interact with Tesla Energy sites (Solar, Powerwall, Wall Connector).
111
118
 
112
119
  ```typescript
120
+ // Get an energy site instance by Site ID
113
121
  const site = teslemetry.energySite(12345);
114
- const data = await site.getSiteInfo();
122
+
123
+ // Get site status and info
124
+ const status = await site.getLiveStatus();
125
+ const info = await site.getSiteInfo();
126
+
127
+ // Control operations
128
+ await site.setBackupReserve(20); // Set backup reserve to 20%
129
+ await site.setOperationMode("autonomous");
115
130
  ```
116
131
 
117
- ## Development
132
+ ### Account & Discovery
118
133
 
119
- To build the package locally:
134
+ If you don't know your VINs or Site IDs, you can discover all products on your account.
120
135
 
121
- ```bash
122
- pnpm install
123
- pnpm build
136
+ ```typescript
137
+ // Fetch all vehicles and energy sites
138
+ const products = await teslemetry.createProducts();
139
+
140
+ // Access discovered vehicles
141
+ for (const vin in products.vehicles) {
142
+ const vehicle = products.vehicles[vin];
143
+ console.log(`Found ${vehicle.name} (${vehicle.vin})`);
144
+
145
+ // Use the API immediately
146
+ await vehicle.api.honkHorn();
147
+ }
148
+
149
+ // Access discovered energy sites
150
+ for (const siteId in products.energySites) {
151
+ const site = products.energySites[siteId];
152
+ console.log(`Found Site: ${site.name} (${site.site})`);
153
+ }
154
+ ```
155
+
156
+ ### Error Handling
157
+
158
+ 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.
159
+
160
+ ```typescript
161
+ import { TeslemetryStreamConnectionError } from "@teslemetry/api";
162
+
163
+ try {
164
+ await vehicle.api.wakeUp();
165
+ } catch (error) {
166
+ console.error("Failed to wake up vehicle:", error);
167
+ }
124
168
  ```
125
169
 
126
170
  ## License
package/dist/index.cjs CHANGED
@@ -623,6 +623,13 @@ const client = createClient(createConfig({
623
623
  //#endregion
624
624
  //#region src/client/sdk.gen.ts
625
625
  /**
626
+ * Streaming field parameters
627
+ */
628
+ const getFieldsJson = (options) => (options?.client ?? client).get({
629
+ url: "/fields.json",
630
+ ...options
631
+ });
632
+ /**
626
633
  * Products
627
634
  *
628
635
  * Returns products mapped to user.
@@ -3081,9 +3088,6 @@ var TeslemetryVehicleStream = class {
3081
3088
  onConnectivity(callback) {
3082
3089
  return this.stream.onConnectivity(callback, { vin: this.vin });
3083
3090
  }
3084
- onCredits(callback) {
3085
- return this.stream.onCredits(callback, { vin: this.vin });
3086
- }
3087
3091
  onVehicleData(callback) {
3088
3092
  return this.stream.onVehicleData(callback, { vin: this.vin });
3089
3093
  }
@@ -3114,15 +3118,17 @@ var TeslemetryVehicleStream = class {
3114
3118
  var TeslemetryStream = class {
3115
3119
  root;
3116
3120
  active = false;
3121
+ connected = false;
3117
3122
  vin;
3123
+ cache;
3118
3124
  logger;
3119
3125
  listeners = /* @__PURE__ */ new Map();
3120
3126
  _connectionListeners = /* @__PURE__ */ new Map();
3121
3127
  vehicles = /* @__PURE__ */ new Map();
3122
- controller = null;
3123
- constructor(root, vin) {
3128
+ constructor(root, options) {
3124
3129
  this.root = root;
3125
- this.vin = vin;
3130
+ this.vin = options?.vin;
3131
+ this.cache = options?.cache;
3126
3132
  this.logger = root.logger;
3127
3133
  if (this.vin) this.getVehicle(this.vin);
3128
3134
  }
@@ -3130,9 +3136,6 @@ var TeslemetryStream = class {
3130
3136
  if (!this.vehicles.has(vin)) this.vehicles.set(vin, new TeslemetryVehicleStream(this.root, this, vin));
3131
3137
  return this.vehicles.get(vin);
3132
3138
  }
3133
- get connected() {
3134
- return this.active;
3135
- }
3136
3139
  async connect() {
3137
3140
  if (this.active) return;
3138
3141
  this.active = true;
@@ -3143,11 +3146,12 @@ var TeslemetryStream = class {
3143
3146
  while (this.active) try {
3144
3147
  const sse = await getSseByVin_({
3145
3148
  client: this.root.client,
3146
- path: { vin: this.vin || "" }
3149
+ path: { vin: this.vin || "" },
3150
+ query: { cache: this.cache }
3147
3151
  });
3148
- if (sse.controller) this.controller = sse.controller;
3149
3152
  this.logger.info(`Connected to stream`);
3150
3153
  retries = 0;
3154
+ this.connected = true;
3151
3155
  this._updateConnectionListeners(true);
3152
3156
  if (sse.stream) for await (const event of sse.stream) {
3153
3157
  if (!this.active) break;
@@ -3156,6 +3160,7 @@ var TeslemetryStream = class {
3156
3160
  } catch (error) {
3157
3161
  if (!this.active) break;
3158
3162
  this.logger.error("SSE error:", error);
3163
+ this.connected = false;
3159
3164
  this._updateConnectionListeners(false);
3160
3165
  retries++;
3161
3166
  const delay = Math.min(2 ** retries, 600) * 1e3;
@@ -3170,10 +3175,6 @@ var TeslemetryStream = class {
3170
3175
  }
3171
3176
  close() {
3172
3177
  this.active = false;
3173
- if (this.controller) {
3174
- this.controller.abort();
3175
- this.controller = null;
3176
- }
3177
3178
  this.logger.info(`Disconnecting from stream`);
3178
3179
  this._updateConnectionListeners(false);
3179
3180
  }
@@ -4906,6 +4907,10 @@ var TeslemetryApi = class {
4906
4907
  energySites: this._energySites
4907
4908
  };
4908
4909
  }
4910
+ async fields() {
4911
+ const { data } = await getFieldsJson({ client: this.root.client });
4912
+ return data;
4913
+ }
4909
4914
  /**
4910
4915
  * Returns a list of products (vehicles and energy sites) associated with the user account.
4911
4916
  * @returns A promise that resolves to an object containing a `response` array and count.
@@ -4939,10 +4944,11 @@ var TeslemetryApi = class {
4939
4944
  * and detailed info for each vehicle.
4940
4945
  */
4941
4946
  async fleetStatus(vins) {
4942
- return postApi1VehiclesFleetStatus({
4947
+ const { data } = await postApi1VehiclesFleetStatus({
4943
4948
  body: { vins },
4944
4949
  client: this.root.client
4945
4950
  });
4951
+ return data;
4946
4952
  }
4947
4953
  /**
4948
4954
  * Returns vehicles belonging to the account. This endpoint is paginated.
@@ -4950,7 +4956,8 @@ var TeslemetryApi = class {
4950
4956
  * pagination details, and a total count.
4951
4957
  */
4952
4958
  async vehicles() {
4953
- return getApi1Vehicles({ client: this.root.client });
4959
+ const { data } = await getApi1Vehicles({ client: this.root.client });
4960
+ return data;
4954
4961
  }
4955
4962
  /**
4956
4963
  * Redeems a share invite. Once redeemed, the account will gain access to the vehicle within the Tesla app.
@@ -4958,10 +4965,11 @@ var TeslemetryApi = class {
4958
4965
  * @returns Promise to an object containing the `vehicle_id_s` and `vin` of the shared vehicle.
4959
4966
  */
4960
4967
  async redeemInvitation(code) {
4961
- return postApi1VehiclesInvitationsRedeem({
4968
+ const { data } = await postApi1VehiclesInvitationsRedeem({
4962
4969
  body: { code },
4963
4970
  client: this.root.client
4964
4971
  });
4972
+ return data;
4965
4973
  }
4966
4974
  };
4967
4975
 
@@ -4989,9 +4997,9 @@ var Teslemetry = class {
4989
4997
  logger;
4990
4998
  _user = null;
4991
4999
  _charging = null;
4992
- constructor(access_token, region, logger = consoleLogger) {
4993
- this.logger = logger;
4994
- if (region) this.region = region;
5000
+ constructor(access_token, options) {
5001
+ this.logger = options?.logger || consoleLogger;
5002
+ if (options?.region) this.region = options.region;
4995
5003
  this.client = createClient({
4996
5004
  auth: access_token,
4997
5005
  baseUrl: `https://${this.region || "api"}.teslemetry.com`,
@@ -5009,7 +5017,7 @@ var Teslemetry = class {
5009
5017
  }
5010
5018
  return response;
5011
5019
  });
5012
- this.sse = new TeslemetryStream(this);
5020
+ this.sse = new TeslemetryStream(this, options?.stream);
5013
5021
  this.api = new TeslemetryApi(this);
5014
5022
  }
5015
5023
  /**
@@ -5033,6 +5041,31 @@ var Teslemetry = class {
5033
5041
  return response.headers.get("x-region");
5034
5042
  }
5035
5043
  /**
5044
+ * Creates API instances for all products (vehicles and energy sites) associated with the account.
5045
+ * @returns A promise that resolves to an object containing vehicle and energy site names, API, and SSE instances.
5046
+ */
5047
+ async createProducts() {
5048
+ const { data } = await getApi1Products({ client: this.client });
5049
+ const result = {
5050
+ vehicles: {},
5051
+ energySites: {}
5052
+ };
5053
+ data.response?.forEach((product) => {
5054
+ if (product.device_type === "vehicle") result.vehicles[product.vin] = {
5055
+ name: product.display_name ?? useTeslaModel(product.vin),
5056
+ vin: product.vin,
5057
+ api: this.api.getVehicle(product.vin),
5058
+ sse: this.sse.getVehicle(product.vin)
5059
+ };
5060
+ if (product.device_type === "energy") result.energySites[product.energy_site_id] = {
5061
+ name: product.site_name ?? "Unnamed",
5062
+ site: product.energy_site_id,
5063
+ api: this.api.getEnergySite(product.energy_site_id)
5064
+ };
5065
+ });
5066
+ return result;
5067
+ }
5068
+ /**
5036
5069
  * Get a vehicle API instance for the specified VIN.
5037
5070
  * @param vin Vehicle Identification Number
5038
5071
  * @returns TeslemetryVehicleApi instance
@@ -5065,6 +5098,15 @@ var Teslemetry = class {
5065
5098
  return this._charging;
5066
5099
  }
5067
5100
  };
5101
+ const model_names = {
5102
+ "3": "Model 3",
5103
+ S: "Model S",
5104
+ X: "Model X",
5105
+ Y: "Model Y",
5106
+ C: "Cybertruck",
5107
+ T: "Semi"
5108
+ };
5109
+ const useTeslaModel = (vin) => model_names?.[vin[3]] ?? "Unknown";
5068
5110
 
5069
5111
  //#endregion
5070
5112
  //#region src/exceptions.ts
@@ -5102,6 +5144,7 @@ var ValueError = class extends Error {
5102
5144
  //#endregion
5103
5145
  exports.Teslemetry = Teslemetry;
5104
5146
  exports.TeslemetryApi = TeslemetryApi;
5147
+ exports.TeslemetryEnergyApi = TeslemetryEnergyApi;
5105
5148
  exports.TeslemetryStream = TeslemetryStream;
5106
5149
  exports.TeslemetryStreamConnectionError = TeslemetryStreamConnectionError;
5107
5150
  exports.TeslemetryStreamEnded = TeslemetryStreamEnded;