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