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 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.5.6
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.0",
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>"],
@@ -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
- try {
6
- if (element === null || element === undefined) {
7
- adapter.log.debug("Cannot extract empty: " + path);
8
- return;
9
- }
5
+ try {
6
+ if (element === null || element === undefined) {
7
+ adapter.log.debug("Cannot extract empty: " + path);
8
+ return;
9
+ }
10
10
 
11
- const objectKeys = Object.keys(element);
11
+ const objectKeys = Object.keys(element);
12
12
 
13
- if (!write) {
14
- write = false;
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
- 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);
62
- });
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
- }
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
- 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
- }
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
- try {
121
- if (key) {
122
- element = element[key];
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
- 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, "");
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
- if (arrayElement.id) {
153
- if (arrayElement.id.replace) {
154
- arrayPath = arrayElement.id.replace(/\./g, "");
155
- } else {
156
- arrayPath = arrayElement.id;
157
- }
158
- }
159
- if (arrayElement.name) {
160
- arrayPath = arrayElement.name.replace(/\./g, "");
161
- }
162
- if (arrayElement.start_date_time) {
163
- arrayPath = arrayElement.start_date_time.replace(/\./g, "");
164
- }
165
- if (preferedArrayName && arrayElement[preferedArrayName]) {
166
- arrayPath = arrayElement[preferedArrayName].replace(/\./g, "");
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
- 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
- }
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
- try {
216
- JSON.parse(str);
217
- } catch (e) {
218
- return false;
219
- }
220
- return true;
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
- 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";
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
- 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",
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
- extractKeys,
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.info(error.response.data.message + " Retry in 5 seconds");
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.bmw",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
4
4
  "description": "Adapter for BMW",
5
5
  "author": {
6
6
  "name": "TA2k",