@eiannone/tesla-api 1.8.1 → 1.11.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/TeslaApi.js CHANGED
@@ -47,10 +47,17 @@ class TeslaApi {
47
47
  }
48
48
  }
49
49
 
50
- async #apiCall(path, method = 'GET') {
51
- return new Promise((resolve, reject) => {
50
+ async #apiCall(path, method = 'GET', params = undefined) {
51
+ return new Promise((resolve, reject) => {
52
+ const postData = (typeof params != 'undefined')? JSON.stringify(params) : '';
53
+ let headers = { 'user-agent': "TeslaEma", 'Authorization': "Bearer " + this.token };
54
+ if (postData.length > 0) {
55
+ headers['Content-Type'] = 'application/json';
56
+ headers['Content-Length'] = postData.length;
57
+ }
58
+
52
59
  const req = request(BASE_URL + "/api/1/vehicles/" + path, {
53
- headers: { 'user-agent': "TeslaEma", 'Authorization': "Bearer " + this.token },
60
+ headers: headers,
54
61
  timeout: this.timeout,
55
62
  method: method
56
63
  }, res => {
@@ -89,6 +96,7 @@ class TeslaApi {
89
96
  // - ENOTFOUND
90
97
  reject(new ApiError(e.message + " ("+e.code+")", ApiError.NETWORK));
91
98
  });
99
+ if (postData.length > 0) req.write(postData);
92
100
  req.end();
93
101
  });
94
102
  }
@@ -116,19 +124,60 @@ class TeslaApi {
116
124
  return this.#apiCall(vid + "/wake_up", "POST");
117
125
  }
118
126
 
119
- async command(command, vehicle_id = null) {
127
+ async command(command, params = undefined, vehicle_id = null) {
120
128
  const vid = (vehicle_id == null)? this.vid : vehicle_id;
121
- return this.#apiCall(vid + "/command/" + command, "POST");
129
+ return this.#apiCall(vid + "/command/" + command, "POST", params);
122
130
  }
123
131
 
124
- async #oauthCall(params) {
125
- const post_data = JSON.stringify(params);
132
+ // async #oauthCall(params) {
133
+ // return new Promise((resolve, reject) => {
134
+ // const postData = JSON.stringify(params);
135
+ // const req = request(BASE_URL + '/oauth/token', {
136
+ // headers: {
137
+ // 'user-agent': "TeslaEma",
138
+ // 'Content-Type': 'application/json',
139
+ // 'Content-Length': postData.length
140
+ // },
141
+ // timeout: 30000,
142
+ // method: 'POST'
143
+ // }, res => {
144
+ // if (res.statusCode > 199 && res.statusCode < 300) {
145
+ // res.setEncoding('utf8');
146
+ // let rawData = '';
147
+ // res.on('data', chunk => { rawData += chunk; });
148
+ // res.on('end', () => {
149
+ // try {
150
+ // resolve(JSON.parse(rawData));
151
+ // } catch(err) {
152
+ // reject(new ApiError(err));
153
+ // }
154
+ // });
155
+ // } else {
156
+ // let errMsg = res.statusMessage + " ("+res.statusCode+")";
157
+ // reject(new ApiError(errMsg, this.#decodeStatus(res.statusCode)));
158
+ // }
159
+ // });
160
+ // req.on('error', e => {
161
+ // // Error code examples:
162
+ // // - EAI_AGAIN (DNS lookup timeout)
163
+ // // - ECONNRESET
164
+ // // - ECONNREFUSED
165
+ // // - ENOTFOUND
166
+ // reject(new ApiError(e.message + " ("+e.code+")", ApiError.NETWORK));
167
+ // });
168
+ // req.write(postData);
169
+ // req.end();
170
+ // });
171
+ // }
172
+
173
+ async #oauthCall2(params) {
126
174
  return new Promise((resolve, reject) => {
127
- const req = request(BASE_URL + '/oauth/token', {
175
+ const postData = JSON.stringify(params);
176
+ const req = request('https://auth.tesla.com/oauth2/v3/token', {
128
177
  headers: {
129
178
  'user-agent': "TeslaEma",
130
179
  'Content-Type': 'application/json',
131
- 'Content-Length': post_data.length
180
+ 'Content-Length': postData.length
132
181
  },
133
182
  timeout: 30000,
134
183
  method: 'POST'
@@ -157,9 +206,9 @@ class TeslaApi {
157
206
  // - ENOTFOUND
158
207
  reject(new ApiError(e.message + " ("+e.code+")", ApiError.NETWORK));
159
208
  });
160
- req.write(post_data);
209
+ req.write(postData);
161
210
  req.end();
162
- });s
211
+ });
163
212
  }
164
213
 
165
214
  onTokenRefreh(callback) {
@@ -167,7 +216,13 @@ class TeslaApi {
167
216
  }
168
217
 
169
218
  async refreshToken(refresh_token) {
170
- return this.#oauthCall({'grant_type': "refresh_token", 'refresh_token': refresh_token})
219
+ const payLoad = {
220
+ grant_type: 'refresh_token',
221
+ client_id: 'ownerapi',
222
+ refresh_token,
223
+ scope: 'openid email offline_access'
224
+ };
225
+ return this.#oauthCall2(payLoad)
171
226
  .then(async (resp) => {
172
227
  this.token = resp.access_token;
173
228
  this.refresh_token = resp.refresh_token;
@@ -182,15 +237,15 @@ class TeslaApi {
182
237
  });
183
238
  }
184
239
 
185
- async getTokens(email, password) {
186
- return this.#oauthCall({
187
- 'grant_type': "password",
188
- 'email': email,
189
- 'password': password,
190
- 'client_id': "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384",
191
- 'client_secret': "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3"
192
- });
193
- }
240
+ // async getTokens(email, password) {
241
+ // return this.#oauthCall({
242
+ // 'grant_type': "password",
243
+ // 'email': email,
244
+ // 'password': password,
245
+ // 'client_id': "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384",
246
+ // 'client_secret': "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3"
247
+ // });
248
+ // }
194
249
  }
195
250
 
196
251
  export { ApiError, TeslaApi }
package/TeslaStream.js CHANGED
@@ -104,12 +104,12 @@ export default class TeslaStream extends EventEmitter {
104
104
  clearTimeout(this.checkTimeout);
105
105
  if (this.disconnects % 10 == 0) {
106
106
  this.log("Too many disconnects!", "warn");
107
- this.emit('too-many-diconnects');
107
+ this.emit('too-many-disconnects');
108
108
  }
109
109
  else {
110
110
  const ms = (this.lastShiftState != null && this.lastShiftState != "")?
111
111
  this.#expBackOffMs(this.disconnects, 0, 8, 1.3) :
112
- this.#expBackOffMs(this.disconnects, minDelay, 60); // Teslamate uses min 15, max 30
112
+ this.#expBackOffMs(this.disconnects, minDelay, 120); // Teslamate uses min 15, max 30
113
113
  this.log("Waiting for " + Math.round(ms / 1000) + " sec...");
114
114
  this.checkTimeout = setTimeout(_ => { this.#subscribe(tag, token); }, ms);
115
115
  }
@@ -158,12 +158,13 @@ export default class TeslaStream extends EventEmitter {
158
158
  this.#disconnectResubscribe(tag, token, "Vehicle disconnected", resubscribeDelay);
159
159
  break;
160
160
  case "vehicle_error":
161
+ if (d.value == 'Vehicle is offline') this.emit('offline');
161
162
  this.#disconnectResubscribe(tag, token, "Vehicle error: " + d.value, resubscribeDelay);
162
163
  break;
163
164
  case "client_error":
164
165
  this.log("Client error: " + d.value, "error");
165
166
  this.emit('error', d.value);
166
- this.#reconnect();
167
+ if (d.value != "Can't validate token. ") this.#reconnect();
167
168
  break;
168
169
  default:
169
170
  this.log("Stream API error ["+d.error_type+"]: " + data, "error");
@@ -179,7 +180,7 @@ export default class TeslaStream extends EventEmitter {
179
180
  this.log("Websocket error: " + errMsg, "error");
180
181
  });
181
182
  this.ws.on('close', (code, reason) => {
182
- this.log("Websocket closed ("+ code + (reason? ': ' + reason : '') + ").");
183
+ this.log("Websocket closed ("+ code + ((reason != '')? `: ${reason}` : '') + ").");
183
184
  if (code == 1006 && this.state != CLOSING) this.reconnect = true; // Abnormal close
184
185
  if (this.checkTimeout != null) clearTimeout(this.checkTimeout);
185
186
  this.ws = null;
@@ -0,0 +1,11 @@
1
+ import {TeslaApi, ApiError} from '../TeslaApi.js';
2
+
3
+ const api = new TeslaApi();
4
+ api.refreshToken('1234')
5
+ .then(result => console.log(JSON.stringify(result)))
6
+ .catch(err => {
7
+ let reason = (err instanceof ApiError)? err.reason : ApiError.UNKNOWN;
8
+ const errMsg = (err instanceof Error)? err.message : err;
9
+ console.error("ApiError " + reason + ": " + errMsg);
10
+ process.exit(-1);
11
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eiannone/tesla-api",
3
- "version": "1.8.1",
3
+ "version": "1.11.0",
4
4
  "description": "Nodejs Tesla API",
5
5
  "type": "module",
6
6
  "main": "index.js",