iobroker.bmw 2.7.0 → 2.7.1
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/LICENSE +1 -1
- package/README.md +4 -3
- package/io-package.json +7 -1
- package/lib/extractKeys.js +342 -342
- package/main.js +6 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2021 TA2k <tombox2020@gmail.com>
|
|
3
|
+
Copyright (c) 2021-2024 TA2k <tombox2020@gmail.com>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -26,9 +26,10 @@ bmw.0.VIN.remotev2
|
|
|
26
26
|
|
|
27
27
|
## Changelog
|
|
28
28
|
|
|
29
|
-
### 2.
|
|
29
|
+
### 2.7.1
|
|
30
|
+
|
|
31
|
+
- Bugfixes
|
|
30
32
|
|
|
31
|
-
- Fix charging message
|
|
32
33
|
### 2.5.5
|
|
33
34
|
|
|
34
35
|
- Fix login
|
|
@@ -57,7 +58,7 @@ bmw.0.VIN.remotev2
|
|
|
57
58
|
|
|
58
59
|
MIT License
|
|
59
60
|
|
|
60
|
-
Copyright (c) 2021 TA2k <tombox2020@gmail.com>
|
|
61
|
+
Copyright (c) 2021-2024 TA2k <tombox2020@gmail.com>
|
|
61
62
|
|
|
62
63
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
63
64
|
of this software and associated documentation files (the "Software"), to deal
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "bmw",
|
|
4
|
-
"version": "2.7.
|
|
4
|
+
"version": "2.7.1",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.7.1": {
|
|
7
|
+
"en": "Move Rate Limit messages to debug",
|
|
8
|
+
"de": "Rate Limit Nachrichten in debug verschoben"
|
|
9
|
+
},
|
|
6
10
|
"2.7.0": {
|
|
7
11
|
"en": "Improve rate limit handling",
|
|
8
12
|
"de": "Rate Limit Handling verbessert"
|
|
@@ -81,6 +85,7 @@
|
|
|
81
85
|
"it": "BMW",
|
|
82
86
|
"es": "BMW",
|
|
83
87
|
"pl": "BMW",
|
|
88
|
+
"uk": "BMW",
|
|
84
89
|
"zh-cn": "宝马"
|
|
85
90
|
},
|
|
86
91
|
"desc": {
|
|
@@ -93,6 +98,7 @@
|
|
|
93
98
|
"it": "Adattatore per BMW",
|
|
94
99
|
"es": "Adaptador para BMW",
|
|
95
100
|
"pl": "Adapter do BMW",
|
|
101
|
+
"uk": "Adapter for BMW",
|
|
96
102
|
"zh-cn": "宝马适配器"
|
|
97
103
|
},
|
|
98
104
|
"authors": ["TA2k <tombox2020@gmail.com>"],
|
package/lib/extractKeys.js
CHANGED
|
@@ -2,365 +2,365 @@
|
|
|
2
2
|
const JSONbig = require("json-bigint")({ storeAsString: true });
|
|
3
3
|
const alreadyCreatedOBjects = {};
|
|
4
4
|
async function extractKeys(adapter, path, element, preferedArrayName, forceIndex, write, channelName) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
try {
|
|
6
|
+
if (element === null || element === undefined) {
|
|
7
|
+
adapter.log.debug("Cannot extract empty: " + path);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const objectKeys = Object.keys(element);
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (typeof element === "string" || typeof element === "number") {
|
|
18
|
-
let name = element;
|
|
19
|
-
if (typeof element === "number") {
|
|
20
|
-
name = element.toString();
|
|
21
|
-
}
|
|
22
|
-
if (!alreadyCreatedOBjects[path]) {
|
|
23
|
-
await adapter
|
|
24
|
-
.setObjectNotExistsAsync(path, {
|
|
25
|
-
type: "state",
|
|
26
|
-
common: {
|
|
27
|
-
name: name,
|
|
28
|
-
role: getRole(element, write),
|
|
29
|
-
type: typeof element,
|
|
30
|
-
write: write,
|
|
31
|
-
read: true,
|
|
32
|
-
},
|
|
33
|
-
native: {},
|
|
34
|
-
})
|
|
35
|
-
.then(() => {
|
|
36
|
-
alreadyCreatedOBjects[path] = true;
|
|
37
|
-
})
|
|
38
|
-
.catch((error) => {
|
|
39
|
-
adapter.log.error(error);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
13
|
+
if (!write) {
|
|
14
|
+
write = false;
|
|
15
|
+
}
|
|
42
16
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
objectKeys.forEach(async (key) => {
|
|
69
|
-
if (isJsonString(element[key])) {
|
|
70
|
-
element[key] = JSONbig.parse(element[key]);
|
|
71
|
-
}
|
|
17
|
+
if (typeof element === "string" || typeof element === "number") {
|
|
18
|
+
let name = element;
|
|
19
|
+
if (typeof element === "number") {
|
|
20
|
+
name = element.toString();
|
|
21
|
+
}
|
|
22
|
+
if (!alreadyCreatedOBjects[path]) {
|
|
23
|
+
await adapter
|
|
24
|
+
.setObjectNotExistsAsync(path, {
|
|
25
|
+
type: "state",
|
|
26
|
+
common: {
|
|
27
|
+
name: name,
|
|
28
|
+
role: getRole(element, write),
|
|
29
|
+
type: typeof element,
|
|
30
|
+
write: write,
|
|
31
|
+
read: true,
|
|
32
|
+
},
|
|
33
|
+
native: {},
|
|
34
|
+
})
|
|
35
|
+
.then(() => {
|
|
36
|
+
alreadyCreatedOBjects[path] = true;
|
|
37
|
+
})
|
|
38
|
+
.catch((error) => {
|
|
39
|
+
adapter.log.error(error);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
72
42
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (description[key]) {
|
|
93
|
-
adapter.extendObject(path + "." + key, {
|
|
94
|
-
type: "state",
|
|
95
|
-
common: {
|
|
96
|
-
name: description[key],
|
|
97
|
-
role: getRole(element[key], write),
|
|
98
|
-
type: typeof element[key],
|
|
99
|
-
write: write,
|
|
100
|
-
read: true,
|
|
101
|
-
},
|
|
102
|
-
native: {},
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
alreadyCreatedOBjects[path + "." + key] = true;
|
|
106
|
-
})
|
|
107
|
-
.catch((error) => {
|
|
108
|
-
adapter.log.error(error);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
adapter.setState(path + "." + key, element[key], true);
|
|
112
|
-
}
|
|
43
|
+
adapter.setState(path, element, true);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!alreadyCreatedOBjects[path]) {
|
|
47
|
+
await adapter
|
|
48
|
+
.setObjectNotExistsAsync(path, {
|
|
49
|
+
type: "channel",
|
|
50
|
+
common: {
|
|
51
|
+
name: channelName || "",
|
|
52
|
+
write: false,
|
|
53
|
+
read: true,
|
|
54
|
+
},
|
|
55
|
+
native: {},
|
|
56
|
+
})
|
|
57
|
+
.then(() => {
|
|
58
|
+
alreadyCreatedOBjects[path] = true;
|
|
59
|
+
})
|
|
60
|
+
.catch((error) => {
|
|
61
|
+
adapter.log.error(error);
|
|
113
62
|
});
|
|
114
|
-
} catch (error) {
|
|
115
|
-
adapter.log.error("Error extract keys: " + path + " " + JSON.stringify(element));
|
|
116
|
-
adapter.log.error(error);
|
|
117
63
|
}
|
|
64
|
+
if (Array.isArray(element)) {
|
|
65
|
+
extractArray(adapter, element, "", path, write, preferedArrayName, forceIndex);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
objectKeys.forEach(async (key) => {
|
|
69
|
+
if (isJsonString(element[key])) {
|
|
70
|
+
element[key] = JSONbig.parse(element[key]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(element[key])) {
|
|
74
|
+
extractArray(adapter, element, key, path, write, preferedArrayName, forceIndex);
|
|
75
|
+
} else if (element[key] !== null && typeof element[key] === "object") {
|
|
76
|
+
extractKeys(adapter, path + "." + key, element[key], preferedArrayName, forceIndex, write);
|
|
77
|
+
} else {
|
|
78
|
+
if (!alreadyCreatedOBjects[path + "." + key]) {
|
|
79
|
+
await adapter
|
|
80
|
+
.setObjectNotExistsAsync(path + "." + key, {
|
|
81
|
+
type: "state",
|
|
82
|
+
common: {
|
|
83
|
+
name: key,
|
|
84
|
+
role: getRole(element[key], write),
|
|
85
|
+
type: typeof element[key],
|
|
86
|
+
write: write,
|
|
87
|
+
read: true,
|
|
88
|
+
},
|
|
89
|
+
native: {},
|
|
90
|
+
})
|
|
91
|
+
.then(() => {
|
|
92
|
+
if (description[key]) {
|
|
93
|
+
adapter.extendObject(path + "." + key, {
|
|
94
|
+
type: "state",
|
|
95
|
+
common: {
|
|
96
|
+
name: description[key],
|
|
97
|
+
role: getRole(element[key], write),
|
|
98
|
+
type: typeof element[key],
|
|
99
|
+
write: write,
|
|
100
|
+
read: true,
|
|
101
|
+
},
|
|
102
|
+
native: {},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
alreadyCreatedOBjects[path + "." + key] = true;
|
|
106
|
+
})
|
|
107
|
+
.catch((error) => {
|
|
108
|
+
adapter.log.error(error);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
adapter.setState(path + "." + key, element[key], true);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
adapter.log.error("Error extract keys: " + path + " " + JSON.stringify(element));
|
|
116
|
+
adapter.log.error(error);
|
|
117
|
+
}
|
|
118
118
|
}
|
|
119
119
|
function extractArray(adapter, element, key, path, write, preferedArrayName, forceIndex) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
try {
|
|
121
|
+
if (key) {
|
|
122
|
+
element = element[key];
|
|
123
|
+
}
|
|
124
|
+
element.forEach(async (arrayElement, index) => {
|
|
125
|
+
index = index + 1;
|
|
126
|
+
if (index < 10) {
|
|
127
|
+
index = "0" + index;
|
|
128
|
+
}
|
|
129
|
+
let arrayPath = key + index;
|
|
130
|
+
if (typeof arrayElement === "string") {
|
|
131
|
+
extractKeys(adapter, path + "." + key + "." + arrayElement, arrayElement, preferedArrayName, forceIndex, write);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (typeof arrayElement[Object.keys(arrayElement)[0]] === "string") {
|
|
135
|
+
arrayPath = arrayElement[Object.keys(arrayElement)[0]];
|
|
136
|
+
}
|
|
137
|
+
Object.keys(arrayElement).forEach((keyName) => {
|
|
138
|
+
if (keyName.endsWith("Id") && arrayElement[keyName] !== null) {
|
|
139
|
+
if (arrayElement[keyName] && arrayElement[keyName].replace) {
|
|
140
|
+
arrayPath = arrayElement[keyName].replace(/\./g, "").replace(/ ~ /g, "").replace(/,/g, "_");
|
|
141
|
+
} else {
|
|
142
|
+
arrayPath = arrayElement[keyName];
|
|
143
|
+
}
|
|
123
144
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (typeof arrayElement === "string") {
|
|
131
|
-
extractKeys(adapter, path + "." + key + "." + arrayElement, arrayElement, preferedArrayName, forceIndex, write);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
if (typeof arrayElement[Object.keys(arrayElement)[0]] === "string") {
|
|
135
|
-
arrayPath = arrayElement[Object.keys(arrayElement)[0]];
|
|
136
|
-
}
|
|
137
|
-
Object.keys(arrayElement).forEach((keyName) => {
|
|
138
|
-
if (keyName.endsWith("Id") && arrayElement[keyName] !== null) {
|
|
139
|
-
if (arrayElement[keyName] && arrayElement[keyName].replace) {
|
|
140
|
-
arrayPath = arrayElement[keyName].replace(/\./g, "");
|
|
141
|
-
} else {
|
|
142
|
-
arrayPath = arrayElement[keyName];
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
Object.keys(arrayElement).forEach((keyName) => {
|
|
147
|
-
if (keyName.endsWith("Name")) {
|
|
148
|
-
arrayPath = arrayElement[keyName];
|
|
149
|
-
}
|
|
150
|
-
});
|
|
145
|
+
});
|
|
146
|
+
Object.keys(arrayElement).forEach((keyName) => {
|
|
147
|
+
if (keyName.endsWith("Name")) {
|
|
148
|
+
arrayPath = arrayElement[keyName];
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
152
|
+
if (arrayElement.id) {
|
|
153
|
+
if (arrayElement.id.replace) {
|
|
154
|
+
arrayPath = arrayElement.id.replace(/\./g, "").replace(/ ~ /g, "").replace(/,/g, "_");
|
|
155
|
+
} else {
|
|
156
|
+
arrayPath = arrayElement.id;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (arrayElement.name) {
|
|
160
|
+
arrayPath = arrayElement.name.replace(/\./g, "").replace(/ ~ /g, "").replace(/,/g, "_");
|
|
161
|
+
}
|
|
162
|
+
if (arrayElement.start_date_time) {
|
|
163
|
+
arrayPath = arrayElement.start_date_time.replace(/\./g, "").replace(/ ~ /g, "").replace(/,/g, "_");
|
|
164
|
+
}
|
|
165
|
+
if (preferedArrayName && arrayElement[preferedArrayName]) {
|
|
166
|
+
arrayPath = arrayElement[preferedArrayName].replace(/\./g, "").replace(/ ~ /g, "").replace(/,/g, "_");
|
|
167
|
+
}
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
169
|
+
if (forceIndex) {
|
|
170
|
+
arrayPath = key + index;
|
|
171
|
+
}
|
|
172
|
+
//special case array with 2 string objects
|
|
173
|
+
if (
|
|
174
|
+
Object.keys(arrayElement).length === 2 &&
|
|
175
|
+
typeof Object.keys(arrayElement)[0] === "string" &&
|
|
176
|
+
typeof Object.keys(arrayElement)[1] === "string" &&
|
|
177
|
+
typeof arrayElement[Object.keys(arrayElement)[0]] !== "object" &&
|
|
178
|
+
typeof arrayElement[Object.keys(arrayElement)[1]] !== "object" &&
|
|
179
|
+
arrayElement[Object.keys(arrayElement)[0]] !== "null"
|
|
180
|
+
) {
|
|
181
|
+
let subKey = arrayElement[Object.keys(arrayElement)[0]];
|
|
182
|
+
const subValue = arrayElement[Object.keys(arrayElement)[1]];
|
|
183
|
+
const subName = Object.keys(arrayElement)[0] + " " + Object.keys(arrayElement)[1];
|
|
184
|
+
if (key) {
|
|
185
|
+
subKey = key + "." + subKey;
|
|
186
|
+
}
|
|
187
|
+
if (!alreadyCreatedOBjects[path + "." + subKey]) {
|
|
188
|
+
await adapter
|
|
189
|
+
.setObjectNotExistsAsync(path + "." + subKey, {
|
|
190
|
+
type: "state",
|
|
191
|
+
common: {
|
|
192
|
+
name: subName,
|
|
193
|
+
role: getRole(subValue, write),
|
|
194
|
+
type: typeof subValue,
|
|
195
|
+
write: write,
|
|
196
|
+
read: true,
|
|
197
|
+
},
|
|
198
|
+
native: {},
|
|
199
|
+
})
|
|
200
|
+
.then(() => {
|
|
201
|
+
alreadyCreatedOBjects[path + "." + subKey] = true;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
adapter.setState(path + "." + subKey, subValue, true);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
extractKeys(adapter, path + "." + arrayPath, arrayElement, preferedArrayName, forceIndex, write);
|
|
208
|
+
});
|
|
209
|
+
} catch (error) {
|
|
210
|
+
adapter.log.error("Cannot extract array " + path);
|
|
211
|
+
adapter.log.error(error);
|
|
212
|
+
}
|
|
213
213
|
}
|
|
214
214
|
function isJsonString(str) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
try {
|
|
216
|
+
JSON.parse(str);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
221
|
}
|
|
222
222
|
function getRole(element, write) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
223
|
+
if (typeof element === "boolean" && !write) {
|
|
224
|
+
return "indicator";
|
|
225
|
+
}
|
|
226
|
+
if (typeof element === "boolean" && write) {
|
|
227
|
+
return "switch";
|
|
228
|
+
}
|
|
229
|
+
if (typeof element === "number" && !write) {
|
|
230
|
+
return "value";
|
|
231
|
+
}
|
|
232
|
+
if (typeof element === "number" && write) {
|
|
233
|
+
return "level";
|
|
234
|
+
}
|
|
235
|
+
if (typeof element === "string") {
|
|
236
|
+
return "text";
|
|
237
|
+
}
|
|
238
|
+
return "state";
|
|
239
239
|
}
|
|
240
240
|
const description = {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
241
|
+
allTrips: "alle Fahrten des Autos",
|
|
242
|
+
avgCombinedConsumption: "Durchschnittlicher kombinierter Verbrauch",
|
|
243
|
+
communityAverage: "Gesamt Durchschnitt",
|
|
244
|
+
communityHigh: "Gesamt max.",
|
|
245
|
+
communityLow: "Gesamt min.",
|
|
246
|
+
userAverage: "Fahrer Durchschnitt",
|
|
247
|
+
avgElectricConsumption: "Durchschnittlicher elektrischer Verbrauch",
|
|
248
|
+
avgRecuperation: "Durchschnittliche Rekuperation",
|
|
249
|
+
chargecycleRange: "Ladezyklus Reichweite",
|
|
250
|
+
userCurrentChargeCycle: "aktueller Ladezyklus",
|
|
251
|
+
userHigh: "Fahrer max.",
|
|
252
|
+
totalElectricDistance: "gesamte elektrische Distanz",
|
|
253
|
+
batterySizeMax: "max. Batterie Ladeleistung in Wh",
|
|
254
|
+
resetDate: "Werte zur+ckgesetz am",
|
|
255
|
+
savedCO2: "Eingespartes CO2",
|
|
256
|
+
savedCO2greenEnergy: "Eingespartes CO2 grüne Energie",
|
|
257
|
+
totalSavedFuel: "Gesamt gesparter Kraftstoff",
|
|
258
|
+
apiV2: "limitierte v2 Api des Autos",
|
|
259
|
+
basicType: "Grundtyp",
|
|
260
|
+
bodyType: "Fahrzeugtyp",
|
|
261
|
+
brand: "Marke",
|
|
262
|
+
modelName: "Model Name",
|
|
263
|
+
series: "Serie",
|
|
264
|
+
vin: "Fahrzeugidentifikationsnummer",
|
|
265
|
+
chargingprofile: "Ladeprofil",
|
|
266
|
+
overrideTimer: "Einmalige Abfahrtszeit",
|
|
267
|
+
weekdays: "Wochentag",
|
|
268
|
+
departureTime: "Abfahrtszeit",
|
|
269
|
+
timerEnabled: "Timer Aktiviert",
|
|
270
|
+
preferredChargingWindow: "Tägliches Ladefenster",
|
|
271
|
+
endTime: "Ende Uhrzeit",
|
|
272
|
+
startTime: "Start Uhrzeit",
|
|
273
|
+
MONDAY: "Montag",
|
|
274
|
+
TUESDAY: "Dienstag",
|
|
275
|
+
WEDNESDAY: "Mittwoch",
|
|
276
|
+
THURSDAY: "Donnerstag",
|
|
277
|
+
FRIDAY: "Freitag",
|
|
278
|
+
SATURDAY: "Samstag",
|
|
279
|
+
SUNDAY: "Sonntag",
|
|
280
|
+
chargingMode: "Lademodus",
|
|
281
|
+
chargingPreferences: "Ladeeinstellungen",
|
|
282
|
+
climatizationEnabled: "Klimatisierung Aktiviert",
|
|
283
|
+
general: "Allgemeine Fahrzeuginformationen",
|
|
284
|
+
dealer: "Händler",
|
|
285
|
+
city: "Stadt",
|
|
286
|
+
country: "Land",
|
|
287
|
+
phone: "Telefon",
|
|
288
|
+
postalCode: "Postleitzahl",
|
|
289
|
+
street: "Straße",
|
|
290
|
+
supportedChargingModes: "unterstützte Lademodi",
|
|
291
|
+
accelerationValue: "Beschleunigungs Wert",
|
|
292
|
+
anticipationValue: "Erwartungswert",
|
|
293
|
+
auxiliaryConsumptionValue: "Hilfsverbrauchswert",
|
|
294
|
+
date: "Datum",
|
|
295
|
+
drivingModeValue: "Fahrmodus",
|
|
296
|
+
duration: "Dauer",
|
|
297
|
+
efficiencyValue: "Effizienz Wert",
|
|
298
|
+
electricDistance: "elektrische Distanz",
|
|
299
|
+
electricDistanceRatio: "elektrisches Distanzverhältnis in %",
|
|
300
|
+
savedFuel: "Eingesparter Kraftstoff",
|
|
301
|
+
totalConsumptionValue: "Gesamtverbrauchswert",
|
|
302
|
+
totalDistance: "Gesamtstrecke",
|
|
303
|
+
rangemap: "Reichweitenkarte",
|
|
304
|
+
center: "Mitte",
|
|
305
|
+
remote: "Fernbedienung",
|
|
306
|
+
CHARGE_NOW: "jetzt Aufladen",
|
|
307
|
+
CLIMATE_NOW: "Klimatisierung starten",
|
|
308
|
+
DOOR_LOCK: "Autotüren zusperren",
|
|
309
|
+
DOOR_UNLOCK: "Autotüren aufsperren",
|
|
310
|
+
GET_VEHICLES: "Fahrzeuginformationen abrufen",
|
|
311
|
+
GET_VEHICLE_STATUS: "Fahrzeug Status abrufen",
|
|
312
|
+
HORN_BLOW: "Hupe einschalten",
|
|
313
|
+
LIGHT_FLASH: "Lichthupe einschalten",
|
|
314
|
+
START_CHARGING: "Laden starten",
|
|
315
|
+
START_PRECONDITIONING: "Startvoraussetzung",
|
|
316
|
+
STOP_CHARGING: "Laden stoppen",
|
|
317
|
+
VEHICLE_FINDER: "Positionsdaten Fahrzeug abrufen",
|
|
318
|
+
serviceExecutionHistory: "Verlauf der Remote-Ausführung",
|
|
319
|
+
status: "Aktueller Status",
|
|
320
|
+
BRAKE_FLUID: "Bremsflüssigkeit",
|
|
321
|
+
cbsDescription: "Service Beschreibung",
|
|
322
|
+
cbsDueDate: "Service Fälligkeitsdatum",
|
|
323
|
+
cbsState: "Service Status",
|
|
324
|
+
cbsType: "Service Art",
|
|
325
|
+
VEHICLE_CHECK: "Fahrzeug Überprüfung",
|
|
326
|
+
position: "Position",
|
|
327
|
+
heading: "Richtung",
|
|
328
|
+
lat: "Latitude",
|
|
329
|
+
lon: "Longitude",
|
|
330
|
+
DCS_CCH_Activation: "DCS CCH Aktivierung",
|
|
331
|
+
DCS_CCH_Ongoing: "DCS CHH Laufend",
|
|
332
|
+
chargingConnectionType: "Ladeverbindungstyp",
|
|
333
|
+
chargingInductivePositioning: "Aufladen Induktive Positionierung",
|
|
334
|
+
chargingLevelHv: "Batterie SoC in %",
|
|
335
|
+
chargingStatus: "Ladestatus",
|
|
336
|
+
chargingTimeRemaining: "Verbleibende Ladezeit",
|
|
337
|
+
connectionStatus: "Verbindungsstatus Ladestecker",
|
|
338
|
+
doorDriverFront: "Fahrertüren",
|
|
339
|
+
driverFront: "Fahrertüren",
|
|
340
|
+
doorDriverRear: "Hintere Türe Fahrerseite",
|
|
341
|
+
doorLockState: "Fahrzeug Verriegelungszustand Türen und Fenster",
|
|
342
|
+
doorPassengerFront: "Beifahrertüre",
|
|
343
|
+
doorPassengerRear: "Hintere Türe Beifahrerseite",
|
|
344
|
+
hood: "Motorhaube",
|
|
345
|
+
internalDataTimeUTC: "Fahrzeugzeit UTC",
|
|
346
|
+
lastChargingEndReason: "letzter Grund für das Ende des Ladevorgangs",
|
|
347
|
+
lastChargingEndResult: "letztes Ladeendergebnis",
|
|
348
|
+
maxRangeElectric: "max. elektrische Reichweite in km",
|
|
349
|
+
maxRangeElectricMls: "max. elektrische Reichweite in mi",
|
|
350
|
+
mileage: "Kilometerstand",
|
|
351
|
+
remainingFuel: "Tankinhalt",
|
|
352
|
+
remainingRangeElectric: "restliche Reichweite Elektrisch in km",
|
|
353
|
+
remainingRangeElectricMls: "restliche Reichweite Elektrisch in mi",
|
|
354
|
+
remainingRangeFuel: "restliche Reichweite Kraftstoff in km",
|
|
355
|
+
remainingRangeFuelMls: "restliche Reichweite Kraftstoff in mi",
|
|
356
|
+
singleImmediateCharging: "einmalige Sofortaufladung",
|
|
357
|
+
trunk: "Kofferraum",
|
|
358
|
+
updateReason: "Aktualisierungsgrund",
|
|
359
|
+
updateTime: "Aktualisierungszeit",
|
|
360
|
+
vehicleCountry: "Fahrzeug Land",
|
|
361
|
+
windowDriverFront: "Fenster Fahrerseite",
|
|
362
|
+
windowPassengerFront: "Fenster Beifahrerseite",
|
|
363
363
|
};
|
|
364
364
|
module.exports = {
|
|
365
|
-
|
|
365
|
+
extractKeys,
|
|
366
366
|
};
|
package/main.js
CHANGED
|
@@ -463,6 +463,11 @@ class Bmw extends utils.Adapter {
|
|
|
463
463
|
})
|
|
464
464
|
.catch((error) => {
|
|
465
465
|
this.log.error("getvehicles v2 failed");
|
|
466
|
+
if (error.response && error.response.status === 429) {
|
|
467
|
+
this.log.error(error.response.data.message + " Please wait and restart the adapter");
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
466
471
|
this.log.error(error);
|
|
467
472
|
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
468
473
|
});
|
|
@@ -493,7 +498,7 @@ class Bmw extends utils.Adapter {
|
|
|
493
498
|
})
|
|
494
499
|
.catch(async (error) => {
|
|
495
500
|
if (error.response && error.response.status === 429) {
|
|
496
|
-
this.log.
|
|
501
|
+
this.log.debug(error.response.data.message + " Retry in 5 seconds");
|
|
497
502
|
await this.sleep(5000);
|
|
498
503
|
await this.updateDevices();
|
|
499
504
|
return;
|