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 +4 -0
- package/io-package.json +12 -1
- package/lib/extractKeys.js +1 -1
- package/main.js +38 -5
- package/package.json +58 -59
package/README.md
CHANGED
package/io-package.json
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "bmw",
|
|
4
|
-
"version": "2.
|
|
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"
|
package/lib/extractKeys.js
CHANGED
|
@@ -324,7 +324,7 @@ const description = {
|
|
|
324
324
|
cbsType: "Service Art",
|
|
325
325
|
VEHICLE_CHECK: "Fahrzeug Überprüfung",
|
|
326
326
|
position: "Position",
|
|
327
|
-
heading: "
|
|
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: "
|
|
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 + "&
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
}
|