iobroker.bmw 2.4.1 → 2.5.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.
package/README.md CHANGED
@@ -27,6 +27,10 @@ bmw.0.VIN.remotev2
27
27
 
28
28
  ## Changelog
29
29
 
30
+ ### 2.5.0
31
+
32
+ - Fix login
33
+
30
34
  ### 2.4.1
31
35
 
32
36
  - Add support for MINI and force refresh remote
package/io-package.json CHANGED
@@ -1,8 +1,19 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "bmw",
4
- "version": "2.4.1",
4
+ "version": "2.5.2",
5
5
  "news": {
6
+ "2.5.2": {
7
+ "en": "Bugfixes"
8
+ },
9
+ "2.5.1": {
10
+ "en": "Add login error message",
11
+ "de": "Loginproblem Nachricht hinzugefügt"
12
+ },
13
+ "2.5.0": {
14
+ "en": "Fix Login",
15
+ "de": "Loginproblem behoben"
16
+ },
6
17
  "2.4.1": {
7
18
  "en": "Add support for MINI and a force refresh remote",
8
19
  "de": "Support für MINI hinzugefügt und ein Update erzwingen remote"
@@ -324,7 +324,7 @@ const description = {
324
324
  cbsType: "Service Art",
325
325
  VEHICLE_CHECK: "Fahrzeug Überprüfung",
326
326
  position: "Position",
327
- heading: "Überschrift",
327
+ heading: "Richtung",
328
328
  lat: "Latitude",
329
329
  lon: "Longitude",
330
330
  DCS_CCH_Activation: "DCS CCH Aktivierung",
package/main.js CHANGED
@@ -8,6 +8,8 @@
8
8
  // you need to create an adapter
9
9
  const utils = require("@iobroker/adapter-core");
10
10
  const axios = require("axios");
11
+
12
+ const crypto = require("crypto");
11
13
  const qs = require("qs");
12
14
  const { extractKeys } = require("./lib/extractKeys");
13
15
  const axiosCookieJarSupport = require("axios-cookiejar-support").default;
@@ -48,10 +50,13 @@ class Bmw extends utils.Adapter {
48
50
  this.statusBlock = {};
49
51
  this.nonChargingHistory = {};
50
52
  this.subscribeStates("*");
51
-
53
+ if (!this.config.username || !this.config.password) {
54
+ this.log.error("Please set username and password");
55
+ return;
56
+ }
52
57
  await this.login();
53
58
  if (this.session.access_token) {
54
- await this.getVehicles();
59
+ // await this.getVehicles(); //old depracted api
55
60
  await this.cleanObjects();
56
61
  await this.getVehiclesv2();
57
62
  this.updateInterval = setInterval(async () => {
@@ -69,17 +74,21 @@ class Bmw extends utils.Adapter {
69
74
  "Accept-Language": "de-de",
70
75
  "Content-Type": "application/x-www-form-urlencoded",
71
76
  };
77
+ const [code_verifier, codeChallenge] = this.getCodeChallenge();
72
78
  const data = {
73
79
  client_id: "31c357a0-7a1d-4590-aa99-33b97244d048",
74
80
  response_type: "code",
75
81
  scope: "openid profile email offline_access smacc vehicle_data perseus dlm svds cesim vsapi remote_services fupo authenticate_user",
76
82
  redirect_uri: "com.bmw.connected://oauth",
77
- state: "cEG9eLAIi6Nv-aaCAniziE_B6FPoobva3qr5gukilYw",
83
+ state: "cwU-gIE27j67poy2UcL3KQ",
78
84
  nonce: "login_nonce",
85
+ code_challenge_method: "S256",
86
+ code_challenge: codeChallenge,
79
87
  username: this.config.username,
80
88
  password: this.config.password,
81
89
  grant_type: "authorization_code",
82
90
  };
91
+
83
92
  const authUrl = await this.requestClient({
84
93
  method: "post",
85
94
  url: "https://customer.bmwgroup.com/gcdm/oauth/authenticate",
@@ -93,12 +102,19 @@ class Bmw extends utils.Adapter {
93
102
  return res.data;
94
103
  })
95
104
  .catch((error) => {
105
+ this.log.error("Login failed");
96
106
  this.log.error(error);
97
107
  if (error.response) {
98
108
  this.log.error(JSON.stringify(error.response.data));
99
109
  }
100
110
  if (error.response && error.response.status === 401) {
101
- this.log.error("Please check username and password");
111
+ this.log.error("Please check username and password or too many logins in 5 minutes");
112
+
113
+ this.log.error("Start relogin in 5min");
114
+ this.reLoginTimeout && clearTimeout(this.reLoginTimeout);
115
+ this.reLoginTimeout = setTimeout(() => {
116
+ this.login();
117
+ }, 5000 * 60 * 1);
102
118
  }
103
119
  if (error.response && error.response.status === 400) {
104
120
  this.log.error("Please check username and password");
@@ -151,7 +167,7 @@ class Bmw extends utils.Adapter {
151
167
  "Accept-Language": "de-de",
152
168
  Authorization: "Basic MzFjMzU3YTAtN2ExZC00NTkwLWFhOTktMzNiOTcyNDRkMDQ4OmMwZTMzOTNkLTcwYTItNGY2Zi05ZDNjLTg1MzBhZjY0ZDU1Mg==",
153
169
  },
154
- data: "code=" + code + "&code_verifier=7PsmfPS5MpaNt0jEcPpi-B7M7u0gs1Nzw6ex0Y9pa-0&redirect_uri=com.bmw.connected://oauth&grant_type=authorization_code",
170
+ data: "code=" + code + "&redirect_uri=com.bmw.connected://oauth&grant_type=authorization_code&code_verifier=" + code_verifier,
155
171
  })
156
172
  .then((res) => {
157
173
  this.log.debug(JSON.stringify(res.data));
@@ -160,12 +176,24 @@ class Bmw extends utils.Adapter {
160
176
  return res.data;
161
177
  })
162
178
  .catch((error) => {
179
+ this.log.error("Login step 3 failed");
163
180
  this.log.error(error);
164
181
  if (error.response) {
165
182
  this.log.error(JSON.stringify(error.response.data));
166
183
  }
167
184
  });
168
185
  }
186
+ getCodeChallenge() {
187
+ let hash = "";
188
+ let result = "";
189
+ const chars = "0123456789abcdef";
190
+ result = "";
191
+ for (let i = 64; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
192
+ hash = crypto.createHash("sha256").update(result).digest("base64");
193
+ hash = hash.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
194
+
195
+ return [result, hash];
196
+ }
169
197
  async getVehicles() {
170
198
  const headers = {
171
199
  "Content-Type": "application/json",
@@ -208,6 +236,7 @@ class Bmw extends utils.Adapter {
208
236
  }
209
237
  })
210
238
  .catch((error) => {
239
+ this.log.error("getVehicles failed");
211
240
  this.log.error(error);
212
241
  error.response && this.log.error(JSON.stringify(error.response.data));
213
242
  });
@@ -284,6 +313,7 @@ class Bmw extends utils.Adapter {
284
313
  }
285
314
  })
286
315
  .catch((error) => {
316
+ this.log.error("getvehicles v2 failed");
287
317
  this.log.error(error);
288
318
  });
289
319
  }
@@ -344,6 +374,7 @@ class Bmw extends utils.Adapter {
344
374
  this.nonChargingHistory[vin] = true;
345
375
  return;
346
376
  }
377
+ this.log.error("updateChargingSessionv2 failed");
347
378
  this.log.error(element.url);
348
379
  this.log.error(error);
349
380
  error.response && this.log.error(JSON.stringify(error.response.data));
@@ -412,6 +443,7 @@ class Bmw extends utils.Adapter {
412
443
  this.log.error(error);
413
444
  error.response && this.log.error(JSON.stringify(error.response.data));
414
445
  this.log.error("Start relogin in 1min");
446
+ this.reLoginTimeout && clearTimeout(this.reLoginTimeout);
415
447
  this.reLoginTimeout = setTimeout(() => {
416
448
  this.login();
417
449
  }, 1000 * 60 * 1);
@@ -483,6 +515,7 @@ class Bmw extends utils.Adapter {
483
515
  return res.data;
484
516
  })
485
517
  .catch((error) => {
518
+ this.log.error("Remote command failed");
486
519
  this.log.error(error);
487
520
  if (error.response) {
488
521
  this.log.error(JSON.stringify(error.response.data));
package/package.json CHANGED
@@ -1,60 +1,59 @@
1
1
  {
2
- "name": "iobroker.bmw",
3
- "version": "2.4.1",
4
- "description": "Adapter for BMW",
5
- "author": {
6
- "name": "TA2k",
7
- "email": "tombox2020@gmail.com"
8
- },
9
- "homepage": "https://github.com/TA2k/ioBroker.bmw",
10
- "license": "MIT",
11
- "keywords": [
12
- "BMW"
13
- ],
14
- "repository": {
15
- "type": "git",
16
- "url": "https://github.com/TA2k/ioBroker.bmw"
17
- },
18
- "dependencies": {
19
- "@iobroker/adapter-core": "^2.5.1",
20
- "axios": "^0.24.0",
21
- "json-bigint": "^1.0.0",
22
- "qs": "^6.10.1",
23
- "axios-cookiejar-support": "^1.0.1",
24
- "tough-cookie": "^4.0.0"
25
- },
26
- "devDependencies": {
27
- "@iobroker/testing": "^2.5.2",
28
- "@types/chai": "^4.2.22",
29
- "@types/chai-as-promised": "^7.1.4",
30
- "@types/gulp": "^4.0.9",
31
- "@types/mocha": "^9.0.0",
32
- "@types/node": "^14.17.32",
33
- "@types/proxyquire": "^1.3.28",
34
- "@types/sinon": "^10.0.6",
35
- "@types/sinon-chai": "^3.2.5",
36
- "chai": "^4.3.4",
37
- "chai-as-promised": "^7.1.1",
38
- "eslint": "^8.1.0",
39
- "gulp": "^4.0.2",
40
- "mocha": "^9.1.3",
41
- "proxyquire": "^2.1.3",
42
- "sinon": "^12.0.0",
43
- "sinon-chai": "^3.7.0",
44
- "typescript": "~4.4.4"
45
- },
46
- "main": "main.js",
47
- "scripts": {
48
- "test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
49
- "test:package": "mocha test/package --exit",
50
- "test:unit": "mocha test/unit --exit",
51
- "test:integration": "mocha test/integration --exit",
52
- "test": "npm run test:js && npm run test:package",
53
- "check": "tsc --noEmit -p tsconfig.check.json",
54
- "lint": "eslint"
55
- },
56
- "bugs": {
57
- "url": "https://github.com/TA2k/ioBroker.bmw/issues"
58
- },
59
- "readmeFilename": "README.md"
60
- }
2
+ "name": "iobroker.bmw",
3
+ "version": "2.5.2",
4
+ "description": "Adapter for BMW",
5
+ "author": {
6
+ "name": "TA2k",
7
+ "email": "tombox2020@gmail.com"
8
+ },
9
+ "homepage": "https://github.com/TA2k/ioBroker.bmw",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "BMW"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/TA2k/ioBroker.bmw"
17
+ },
18
+ "dependencies": {
19
+ "@iobroker/adapter-core": "^2.6.0",
20
+ "axios": "^0.24.0",
21
+ "axios-cookiejar-support": "^1.0.1",
22
+ "json-bigint": "^1.0.0",
23
+ "qs": "^6.10.3",
24
+ "tough-cookie": "^4.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@iobroker/testing": "^2.5.6",
28
+ "@types/chai": "^4.3.0",
29
+ "@types/chai-as-promised": "^7.1.5",
30
+ "@types/gulp": "^4.0.9",
31
+ "@types/mocha": "^9.1.0",
32
+ "@types/node": "^14.18.12",
33
+ "@types/proxyquire": "^1.3.28",
34
+ "@types/sinon": "^10.0.11",
35
+ "@types/sinon-chai": "^3.2.8",
36
+ "chai": "^4.3.6",
37
+ "chai-as-promised": "^7.1.1",
38
+ "eslint": "^7.32.0",
39
+ "mocha": "^9.2.1",
40
+ "proxyquire": "^2.1.3",
41
+ "sinon": "^12.0.1",
42
+ "sinon-chai": "^3.7.0",
43
+ "typescript": "~4.4.4"
44
+ },
45
+ "main": "main.js",
46
+ "scripts": {
47
+ "test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
48
+ "test:package": "mocha test/package --exit",
49
+ "test:unit": "mocha test/unit --exit",
50
+ "test:integration": "mocha test/integration --exit",
51
+ "test": "npm run test:js && npm run test:package",
52
+ "check": "tsc --noEmit -p tsconfig.check.json",
53
+ "lint": "eslint"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/TA2k/ioBroker.bmw/issues"
57
+ },
58
+ "readmeFilename": "README.md"
59
+ }