iobroker.bluelink
Advanced tools
| const globals = require('globals'); | ||
| const js = require('@eslint/js'); | ||
| const { FlatCompat } = require('@eslint/eslintrc'); | ||
| const compat = new FlatCompat({ | ||
| baseDirectory: __dirname, | ||
| recommendedConfig: js.configs.recommended, | ||
| allConfig: js.configs.all, | ||
| }); | ||
| module.exports = [ | ||
| { | ||
| ignores: ['.dev-server/**'], | ||
| }, | ||
| ...compat.extends('eslint:recommended', 'plugin:prettier/recommended'), | ||
| { | ||
| languageOptions: { | ||
| globals: { | ||
| ...globals.node, | ||
| ...globals.mocha, | ||
| }, | ||
| ecmaVersion: 2022, | ||
| sourceType: 'commonjs', | ||
| parserOptions: { | ||
| ecmaFeatures: { | ||
| jsx: true, | ||
| }, | ||
| }, | ||
| }, | ||
| rules: { | ||
| indent: ['error', 4, { SwitchCase: 1 }], | ||
| 'prettier/prettier': ['off', { endOfLine: 'auto' }], | ||
| 'no-unused-vars': 'off', | ||
| 'no-console': 'off', | ||
| 'no-var': 'error', | ||
| 'no-trailing-spaces': 'error', | ||
| 'prefer-const': 'warn', | ||
| 'no-prototype-builtins': 'warn', | ||
| 'no-case-declarations': 'warn', | ||
| 'no-useless-escape': 'warn', | ||
| quotes: [ | ||
| 'error', | ||
| 'single', | ||
| { | ||
| avoidEscape: true, | ||
| allowTemplateLiterals: true, | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| ]; |
+13
-13
@@ -1,2 +0,14 @@ | ||
| { | ||
| { | ||
| 'Username': { | ||
| 'en': 'Username', | ||
| 'de': 'Nutzername', | ||
| 'ru': 'Имя пользователя', | ||
| 'pt': 'Nome de usuário', | ||
| 'nl': 'Gebruikersnaam', | ||
| 'fr': "Nom d'utilisateur", | ||
| 'it': 'Nome utente', | ||
| 'es': 'Nombre de usuario', | ||
| 'pl': 'Nazwa Użytkownika', | ||
| 'zh-cn': '用户名' | ||
| }, | ||
| 'bluelink adapter settings': { | ||
@@ -14,14 +26,2 @@ 'en': 'Adapter settings for bluelink', | ||
| }, | ||
| 'Username': { | ||
| 'en': 'Username', | ||
| 'de': 'Nutzername', | ||
| 'ru': 'Имя пользователя', | ||
| 'pt': 'Nome de usuário', | ||
| 'nl': 'Gebruikersnaam', | ||
| 'fr': "Nom d'utilisateur", | ||
| 'it': 'Nome utente', | ||
| 'es': 'Nombre de usuario', | ||
| 'pl': 'Nazwa Użytkownika', | ||
| 'zh-cn': '用户名' | ||
| }, | ||
| 'Password': { | ||
@@ -28,0 +28,0 @@ 'en': 'Password', |
+27
-27
| { | ||
| "common": { | ||
| "name": "bluelink", | ||
| "version": "3.0.3", | ||
| "version": "3.1.0", | ||
| "news": { | ||
| "3.1.0": { | ||
| "en": "SOC corr \ndependency update", | ||
| "de": "SOC corr\naktualisierung der abhängigkeit", | ||
| "ru": "SOC corr\nобновление", | ||
| "pt": "Corantes SOC\natualização de dependência", | ||
| "nl": "SOC corr\nafhankelijkheidsupdate", | ||
| "fr": "SOC corr\nmise à jour de la dépendance", | ||
| "it": "Corpo SOC\naggiornamento della dipendenza", | ||
| "es": "SOC corr\nactualización de la dependencia", | ||
| "pl": "SOC corr\naktualizacja zależności", | ||
| "uk": "СОК кор\nоновлення залежності", | ||
| "zh-cn": "SOC 缩写\n依赖性更新" | ||
| }, | ||
| "3.0.4": { | ||
| "en": "typo", | ||
| "de": "typo", | ||
| "ru": "typo", | ||
| "pt": "tipo:", | ||
| "nl": "type", | ||
| "fr": "typo", | ||
| "it": "tipo", | ||
| "es": "typo", | ||
| "pl": "typo", | ||
| "uk": "типи", | ||
| "zh-cn": "类型" | ||
| }, | ||
| "3.0.3": { | ||
@@ -70,28 +96,2 @@ "en": "add city to position text", | ||
| "zh-cn": "重新设计" | ||
| }, | ||
| "2.3.10": { | ||
| "en": "add address as text using openstreetmap", | ||
| "de": "adresse als text hinzufügen mit opentreetmap", | ||
| "ru": "добавить адрес как текст с помощью opentreetmap", | ||
| "pt": "adicionar endereço como texto usando o opentreetmap", | ||
| "nl": "adres toevoegen als tekst met openstreetmap", | ||
| "fr": "ajouter l'adresse comme texte en utilisant openstreetmap", | ||
| "it": "aggiungere l'indirizzo come testo usando openstreetmap", | ||
| "es": "añadir dirección como texto usando openstreetmap", | ||
| "pl": "dodaj adres jako tekst używając openstreetmap", | ||
| "uk": "додати адресу як текст за допомогою openstreetmap", | ||
| "zh-cn": "使用 opentreetmap 添加地址为文本" | ||
| }, | ||
| "2.3.9": { | ||
| "en": "add ccs2 car status", | ||
| "de": "ccs2 autostatus hinzufügen", | ||
| "ru": "добавить статус автомобиля ccs2", | ||
| "pt": "adicionar status do carro ccs2", | ||
| "nl": "ccs2 autostatus toevoegen", | ||
| "fr": "ajouter ccs2 statut de voiture", | ||
| "it": "aggiungere ccs2 auto stato", | ||
| "es": "añadir ccs2 estado del coche", | ||
| "pl": "dodaj status samochodu ccs2", | ||
| "uk": "додати стан автомобіля ccs2", | ||
| "zh-cn": "添加 ccs2 车位" | ||
| } | ||
@@ -98,0 +98,0 @@ }, |
+11
-11
@@ -65,13 +65,13 @@ | ||
| await this.adapter.setObjectNotExistsAsync(vin + '.control.force_checkDriveInfo', { | ||
| type: 'state', | ||
| common: { | ||
| name: 'Force load Drive Infos', | ||
| type: 'boolean', | ||
| role: 'button', | ||
| read: true, | ||
| write: true, | ||
| def: true, | ||
| }, | ||
| native: {}, | ||
| }); | ||
| type: 'state', | ||
| common: { | ||
| name: 'Force load Drive Infos', | ||
| type: 'boolean', | ||
| role: 'button', | ||
| read: true, | ||
| write: true, | ||
| def: true, | ||
| }, | ||
| native: {}, | ||
| }); | ||
@@ -78,0 +78,0 @@ this.adapter.subscribeStates(vin + '.control.force_checkDriveInfo'); |
+89
-89
@@ -18,47 +18,22 @@ //v1.5b | ||
| async parse(path, element, options) { | ||
| if (element === null || element === undefined) { | ||
| this.adapter.log.debug('Cannot extract empty: ' + path); | ||
| return; | ||
| } | ||
| const objectKeys = Object.keys(element); | ||
| if (element === null || element === undefined) { | ||
| this.adapter.log.debug('Cannot extract empty: ' + path); | ||
| return; | ||
| } | ||
| if (!options || !options.write) { | ||
| if (!options) { | ||
| options = { write: false }; | ||
| } else { | ||
| options['write'] = false; | ||
| } | ||
| const objectKeys = Object.keys(element); | ||
| if (!options || !options.write) { | ||
| if (!options) { | ||
| options = { write: false }; | ||
| } else { | ||
| options['write'] = false; | ||
| } | ||
| } | ||
| if (typeof element === 'string' || typeof element === 'number') { | ||
| let name = element; | ||
| if (typeof element === 'number') { | ||
| name = element.toString(); | ||
| } | ||
| if (!this.alreadyCreatedObjects[path]) { | ||
| await this.adapter | ||
| .setObjectNotExistsAsync(path, { | ||
| type: 'state', | ||
| common: { | ||
| name: name, | ||
| role: this.getRole(element, options.write), | ||
| type: element !== null ? typeof element : 'mixed', | ||
| write: options.write, | ||
| read: true, | ||
| }, | ||
| native: {}, | ||
| }) | ||
| .then(() => { | ||
| this.alreadyCreatedObjects[path] = true; | ||
| }) | ||
| .catch((error) => { | ||
| this.adapter.log.error(error); | ||
| }); | ||
| } | ||
| this.adapter.setState(path, element, true); | ||
| return; | ||
| if (typeof element === 'string' || typeof element === 'number') { | ||
| let name = element; | ||
| if (typeof element === 'number') { | ||
| name = element.toString(); | ||
| } | ||
@@ -68,6 +43,8 @@ if (!this.alreadyCreatedObjects[path]) { | ||
| .setObjectNotExistsAsync(path, { | ||
| type: 'channel', | ||
| type: 'state', | ||
| common: { | ||
| name: options.channelName || '', | ||
| write: false, | ||
| name: name, | ||
| role: this.getRole(element, options.write), | ||
| type: element !== null ? typeof element : 'mixed', | ||
| write: options.write, | ||
| read: true, | ||
@@ -79,3 +56,2 @@ }, | ||
| this.alreadyCreatedObjects[path] = true; | ||
| options.channelName = undefined; | ||
| }) | ||
@@ -86,51 +62,75 @@ .catch((error) => { | ||
| } | ||
| if (Array.isArray(element)) { | ||
| await this.extractArray(element, '', path, options); | ||
| return; | ||
| } | ||
| for (const key of objectKeys) { | ||
| try { | ||
| if (Array.isArray(element[key])) { | ||
| await this.extractArray(element, key, path, options); | ||
| } else if (element[key] !== null && element[key] !== undefined && typeof element[key] === 'object') { | ||
| await this.parse(path + '.' + key, element[key], options); | ||
| } else { | ||
| if (!this.alreadyCreatedObjects[path + '.' + key]) { | ||
| let objectName = key; | ||
| if (options.descriptions && options.descriptions[key]) { | ||
| objectName = options.descriptions[key]; | ||
| } | ||
| const type = element[key] !== null && element[key] !== undefined ? typeof element[key] : 'mixed'; | ||
| const common = { | ||
| name: objectName, | ||
| role: this.getRole(element[key], options.write), | ||
| type: type, | ||
| write: options.write, | ||
| read: true, | ||
| }; | ||
| await this.adapter | ||
| .setObjectNotExistsAsync(path + '.' + key, { | ||
| type: 'state', | ||
| common: common, | ||
| native: {}, | ||
| }) | ||
| .then(() => { | ||
| this.alreadyCreatedObjects[path + '.' + key] = true; | ||
| }) | ||
| .catch((error) => { | ||
| this.adapter.log.error(error); | ||
| }); | ||
| this.adapter.setState(path, element, true); | ||
| return; | ||
| } | ||
| if (!this.alreadyCreatedObjects[path]) { | ||
| await this.adapter | ||
| .setObjectNotExistsAsync(path, { | ||
| type: 'channel', | ||
| common: { | ||
| name: options.channelName || '', | ||
| write: false, | ||
| read: true, | ||
| }, | ||
| native: {}, | ||
| }) | ||
| .then(() => { | ||
| this.alreadyCreatedObjects[path] = true; | ||
| options.channelName = undefined; | ||
| }) | ||
| .catch((error) => { | ||
| this.adapter.log.error(error); | ||
| }); | ||
| } | ||
| if (Array.isArray(element)) { | ||
| await this.extractArray(element, '', path, options); | ||
| return; | ||
| } | ||
| for (const key of objectKeys) { | ||
| try { | ||
| if (Array.isArray(element[key])) { | ||
| await this.extractArray(element, key, path, options); | ||
| } else if (element[key] !== null && element[key] !== undefined && typeof element[key] === 'object') { | ||
| await this.parse(path + '.' + key, element[key], options); | ||
| } else { | ||
| if (!this.alreadyCreatedObjects[path + '.' + key]) { | ||
| let objectName = key; | ||
| if (options.descriptions && options.descriptions[key]) { | ||
| objectName = options.descriptions[key]; | ||
| } | ||
| if (element[key] !== undefined) { | ||
| this.adapter.setState(path + '.' + key, element[key], true); | ||
| } | ||
| const type = element[key] !== null && element[key] !== undefined ? typeof element[key] : 'mixed'; | ||
| const common = { | ||
| name: objectName, | ||
| role: this.getRole(element[key], options.write), | ||
| type: type, | ||
| write: options.write, | ||
| read: true, | ||
| }; | ||
| await this.adapter | ||
| .setObjectNotExistsAsync(path + '.' + key, { | ||
| type: 'state', | ||
| common: common, | ||
| native: {}, | ||
| }) | ||
| .then(() => { | ||
| this.alreadyCreatedObjects[path + '.' + key] = true; | ||
| }) | ||
| .catch((error) => { | ||
| this.adapter.log.error(error); | ||
| }); | ||
| } | ||
| } catch (error) { | ||
| this.adapter.log.error('Error extract objectKeys: ' + path + '.' + element); | ||
| this.adapter.log.error(error); | ||
| if (element[key] !== undefined) { | ||
| this.adapter.setState(path + '.' + key, element[key], true); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| this.adapter.log.error('Error extract objectKeys: ' + path + '.' + element); | ||
| this.adapter.log.error(error); | ||
| } | ||
| } | ||
| } | ||
@@ -137,0 +137,0 @@ async extractArray(element, key, path, options) { |
+22
-20
@@ -46,23 +46,3 @@ const axios = require('axios').default; | ||
| /** | ||
| * Translates text with Yandex API | ||
| * @param {string} text The text to translate | ||
| * @param {string} targetLang The target languate | ||
| * @param {string} apiKey The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
| * @returns {Promise<string>} | ||
| */ | ||
| async function getResolvedAddress(latitude,longitude) { | ||
| try { | ||
| const url = `https://nominatim.openstreetmap.org/reverse.php?format=json&lat=${latitude}&lon==${longitude}&zoom=18`; | ||
| const response = await axios({url, timeout: 5000}); | ||
| if (response.data) { | ||
| const addr = ([strasse ? strasse : null,hausnummer ? [' ',hausnummer,''].join('') : null,strasse ? ', ' : null,plz ? String(plz) + ' ' : null,stadt ? String(stadt) + '' : null,stadtteil ? [' (',stadtteil,')'].join('') : null,kreis ? ', ' + String(kreis) : null,bundesland ? ', ' + String(bundesland) : null,land ? ', ' + String(land) : null,!land ? 'not found.' : null].join('')); | ||
| return addr; | ||
| } | ||
| } catch (err) { | ||
| throw new Error(`Could not find address: ${err}`); | ||
| } | ||
| } | ||
| async function getResolveAddress(latitude,longitude) { | ||
@@ -84,2 +64,24 @@ try { | ||
| } | ||
| /** | ||
| * Translates text with Yandex API | ||
| * @param {string} text The text to translate | ||
| * @param {string} targetLang The target languate | ||
| * @param {string} apiKey The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
| * @returns {Promise<string>} | ||
| */ | ||
| async function translateYandex(text, targetLang, apiKey) { | ||
| if (targetLang === 'zh-cn') { | ||
| targetLang = 'zh'; | ||
| } | ||
| try { | ||
| const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`; | ||
| const response = await axios({url, timeout: 15000}); | ||
| if (response.data && response.data.text && isArray(response.data.text)) { | ||
| return response.data.text[0]; | ||
| } | ||
| throw new Error('Invalid response for translate request'); | ||
| } catch (e) { | ||
| throw new Error(`Could not translate to "${targetLang}": ${e}`); | ||
| } | ||
| } | ||
@@ -86,0 +88,0 @@ /** |
+141
-139
@@ -50,3 +50,3 @@ 'use strict'; | ||
| adapterIntervals.evHistoryInterval = null; | ||
| this.countError = 0; | ||
| this.countError = 0; | ||
| } | ||
@@ -117,3 +117,3 @@ | ||
| let force_update_obj = await this.getStateAsync(`${vin}.control.force_update`); | ||
| const force_update_obj = await this.getStateAsync(`${vin}.control.force_update`); | ||
| try { | ||
@@ -124,3 +124,3 @@ switch (tmpControl) { | ||
| await this.readStatusVin(vehicle, force_update_obj.val); | ||
| this.driveHistory(vehicle); | ||
| this.driveHistory(vehicle); | ||
| break; | ||
@@ -139,5 +139,5 @@ case 'lock': | ||
| this.log.info('Starting clima for vehicle'); | ||
| let airTempC = await this.getStateAsync(`${vin}.control.clima.set.airTemp`); | ||
| let defrost = await this.getStateAsync(`${vin}.control.clima.set.defrost`); | ||
| let heating = await this.getStateAsync(`${vin}.control.clima.set.heating`); | ||
| const airTempC = await this.getStateAsync(`${vin}.control.clima.set.airTemp`); | ||
| const defrost = await this.getStateAsync(`${vin}.control.clima.set.defrost`); | ||
| const heating = await this.getStateAsync(`${vin}.control.clima.set.heating`); | ||
| try { | ||
@@ -153,4 +153,4 @@ response = await vehicle.start({ | ||
| vin: vin, | ||
| }); | ||
| }); | ||
| this.log.debug(JSON.stringify(response)); | ||
@@ -211,10 +211,10 @@ } catch (err) { | ||
| //set fast charging | ||
| let charge_limit_slow = await this.getStateAsync(`${vin}.control.charge_limit_slow`); | ||
| const charge_limit_slow = await this.getStateAsync(`${vin}.control.charge_limit_slow`); | ||
| charge_option.fast = state.val; | ||
| charge_option.slow = charge_limit_slow.val; | ||
| } | ||
| } | ||
| if (tmpControl == 'charge_limit_slow') { | ||
| this.log.info('Set new charging options charge_limit_slow'); | ||
| //set slow charging | ||
| let charge_limit_fast = await this.getStateAsync(`${vin}.control.charge_limit_fast`); | ||
| const charge_limit_fast = await this.getStateAsync(`${vin}.control.charge_limit_fast`); | ||
| charge_option.slow = state.val; | ||
@@ -309,3 +309,3 @@ charge_option.fast = charge_limit_fast.val; | ||
| let requestTimeout = setTimeout(async () => { | ||
| const requestTimeout = setTimeout(async () => { | ||
| this.login(); | ||
@@ -328,15 +328,15 @@ }, 1000 * 60 * 60); // warte 1 stunde | ||
| for (const vehicle of this.vehicles) { | ||
| const vin = vehicle.vehicleConfig.vin; | ||
| let force_update_obj = await this.getStateAsync(`${vin}.control.force_update`); | ||
| this.log.debug('Read new status from api for ' + vin); | ||
| let batteryControlState12V = await this.getStateAsync(`${vin}.control.batteryControlState12V`); | ||
| const vin = vehicle.vehicleConfig.vin; | ||
| const force_update_obj = await this.getStateAsync(`${vin}.control.force_update`); | ||
| this.log.debug('Read new status from api for ' + vin); | ||
| const batteryControlState12V = await this.getStateAsync(`${vin}.control.batteryControlState12V`); | ||
| if (this.batteryState12V[vin] && this.batteryState12V[vin] < batteryControlState12V.val && force_update_obj.val) { | ||
| this.log.warn('12V Battery state is low: ' + this.batteryState12V[vin] + '%. Recharge to prevent damage!'); | ||
| if (this.config.protectAgainstDeepDischarge && !force) { | ||
| this.log.warn('Auto Refresh is disabled, only use force refresh to reenable refresh if you are willing to risk your battery'); | ||
| continue; | ||
| } | ||
| } | ||
| await this.readStatusVin(vehicle,force_update_obj.val); | ||
| if (this.batteryState12V[vin] && this.batteryState12V[vin] < batteryControlState12V.val && force_update_obj.val) { | ||
| this.log.warn('12V Battery state is low: ' + this.batteryState12V[vin] + '%. Recharge to prevent damage!'); | ||
| if (this.config.protectAgainstDeepDischarge && !force) { | ||
| this.log.warn('Auto Refresh is disabled, only use force refresh to reenable refresh if you are willing to risk your battery'); | ||
| continue; | ||
| } | ||
| } | ||
| await this.readStatusVin(vehicle,force_update_obj.val); | ||
| } | ||
@@ -355,72 +355,72 @@ | ||
| async readStatusVin(vehicle, force_update) { | ||
| const vin = vehicle.vehicleConfig.vin; | ||
| try { | ||
| let newStatus; | ||
| const vin = vehicle.vehicleConfig.vin; | ||
| try { | ||
| let newStatus; | ||
| if(force_update) { | ||
| this.log.info('Read new update for ' + vin + ' directly from the car'); | ||
| } else { | ||
| this.log.info('Read new update for ' + vin + ' from the server'); | ||
| } | ||
| if(force_update) { | ||
| this.log.info('Read new update for ' + vin + ' directly from the car'); | ||
| } else { | ||
| this.log.info('Read new update for ' + vin + ' from the server'); | ||
| } | ||
| try { | ||
| try { | ||
| newStatus = await vehicle.fullStatus({ | ||
| refresh: force_update, | ||
| parsed: true, | ||
| }); | ||
| newStatus = await vehicle.fullStatus({ | ||
| refresh: force_update, | ||
| parsed: true, | ||
| }); | ||
| //set all values | ||
| this.log.debug('Set new full status for ' + vin); | ||
| this.log.debug('RAW ' + JSON.stringify(newStatus)); | ||
| //set all values | ||
| this.log.debug('Set new full status for ' + vin); | ||
| this.log.debug('RAW ' + JSON.stringify(newStatus)); | ||
| // raw data | ||
| await this.json2iob.parse(vin + '.vehicleStatusRaw', newStatus); | ||
| await this.setNewFullStatus(newStatus, vin); | ||
| // raw data | ||
| await this.json2iob.parse(vin + '.vehicleStatusRaw', newStatus); | ||
| await this.setNewFullStatus(newStatus, vin); | ||
| } catch (error) { | ||
| if (typeof error === 'string') { | ||
| this.log.error('Error on API-Request GetFullStatus'); | ||
| this.log.error(error); | ||
| } else { | ||
| //if(error.source.statusCode == 503) { | ||
| this.log.info('Error on API-Full-Status - Fallback GetStatusFromCar'); | ||
| } catch (error) { | ||
| if (typeof error === 'string') { | ||
| this.log.error('Error on API-Request GetFullStatus'); | ||
| this.log.error(error); | ||
| } else { | ||
| //if(error.source.statusCode == 503) { | ||
| this.log.info('Error on API-Full-Status - Fallback GetStatusFromCar'); | ||
| //Abfrage Full hat nicht geklappt. Haben wir einen Fallback? | ||
| newStatus = await vehicle.status({ | ||
| refresh: force_update, | ||
| parsed: true, | ||
| }); | ||
| this.log.debug('Set new GetNormalStatus for ' + vin); | ||
| this.log.debug(JSON.stringify(newStatus)); | ||
| //Abfrage Full hat nicht geklappt. Haben wir einen Fallback? | ||
| newStatus = await vehicle.status({ | ||
| refresh: force_update, | ||
| parsed: true, | ||
| }); | ||
| this.log.debug('Set new GetNormalStatus for ' + vin); | ||
| this.log.debug(JSON.stringify(newStatus)); | ||
| await this.json2iob.parse(vin + '.vehicleStatusRaw', newStatus); | ||
| await this.setShortStatus(newStatus, vin); | ||
| } | ||
| } | ||
| await this.json2iob.parse(vin + '.vehicleStatusRaw', newStatus); | ||
| await this.setShortStatus(newStatus, vin); | ||
| } | ||
| } | ||
| //Abfrage war erfolgreich, lösche ErrorCounter | ||
| this.countError = 0; | ||
| await this.setStateAsync(`${vin}.error_counter`, this.countError, true); | ||
| this.log.info('Update for ' + vin + ' successfull'); | ||
| // last update | ||
| await this.setStateAsync(`${vin}.lastInfoUpdate`, Number(Date.now()), true); | ||
| //Abfrage war erfolgreich, lösche ErrorCounter | ||
| this.countError = 0; | ||
| await this.setStateAsync(`${vin}.error_counter`, this.countError, true); | ||
| this.log.info('Update for ' + vin + ' successfull'); | ||
| // last update | ||
| await this.setStateAsync(`${vin}.lastInfoUpdate`, Number(Date.now()), true); | ||
| } catch (error) { | ||
| this.countError += 1; // add 1 | ||
| } catch (error) { | ||
| this.countError += 1; // add 1 | ||
| this.log.error('Error on API-Request Status, ErrorCount:' + this.countError); | ||
| if (typeof error === 'string') { | ||
| this.log.error(error); | ||
| } else if (error instanceof Error) { | ||
| this.log.error(error.message); | ||
| } | ||
| } | ||
| this.log.error('Error on API-Request Status, ErrorCount:' + this.countError); | ||
| if (typeof error === 'string') { | ||
| this.log.error(error); | ||
| } else if (error instanceof Error) { | ||
| this.log.error(error.message); | ||
| } | ||
| } | ||
| await this.setStateAsync(`${vin}.error_counter`, this.countError, true); | ||
| await this.setStateAsync(`${vin}.error_counter`, this.countError, true); | ||
| if (this.countError > this.config.errorCounter) { | ||
| //Error counter over x erros, restart Adapter to fix te API Token | ||
| this.restart(); | ||
| } | ||
| if (this.countError > this.config.errorCounter) { | ||
| //Error counter over x erros, restart Adapter to fix te API Token | ||
| this.restart(); | ||
| } | ||
| } | ||
@@ -434,5 +434,5 @@ | ||
| this.driveHistory(vehicle); | ||
| } | ||
| } | ||
| } | ||
| async driveHistory(vehicle) { | ||
@@ -443,3 +443,3 @@ try { | ||
| const vin = vehicle.vehicleConfig.vin; | ||
| if (driveHistory.hasOwnProperty('cumulated[0]')) { | ||
@@ -454,7 +454,7 @@ this.log.debug('driveHistory-Data: ' + JSON.stringify(driveHistory)); | ||
| }); | ||
| await this.json2iob.parse(vin + '.driveHistory', driveHistory, { preferedArrayName: 'rawDate' }); | ||
| this.todayOnly(vin, driveHistory); | ||
| const monthlyReport = await vehicle.monthlyReport(); | ||
@@ -488,9 +488,9 @@ await this.setObjectNotExistsAsync(vin + '.monthlyReport', { | ||
| } | ||
| async todayOnly(vin, driveHistory) { | ||
| let onlyHistory = driveHistory.history; | ||
| const onlyHistory = driveHistory.history; | ||
| const today = this.getToday(); | ||
| for (const lpEntry in onlyHistory) { | ||
| let res = onlyHistory[lpEntry]; | ||
| const res = onlyHistory[lpEntry]; | ||
| this.log.debug('check Today ' + today + ' ' + res.rawDate); | ||
@@ -511,5 +511,5 @@ if (today == res.rawDate) { // suche heutiges Datum | ||
| } | ||
| getToday() { | ||
| var today = new Date(); | ||
| const today = new Date(); | ||
| const yyyy = today.getFullYear(); | ||
@@ -524,3 +524,3 @@ let mm = today.getMonth() + 1; | ||
| } | ||
| //short status | ||
@@ -587,3 +587,3 @@ async setShortStatus(newStatus, vin) { | ||
| if (newStatus.vehicleStatus.hasOwnProperty("airTemp")) { | ||
| if (newStatus.vehicleStatus.hasOwnProperty('airTemp')) { | ||
| await this.setStateAsync(vin + '.vehicleStatus.airTemp', { | ||
@@ -603,30 +603,32 @@ val: this.getCelsiusFromTempcode(newStatus.vehicleStatus.airTemp.value), | ||
| if (newStatus.vehicleStatus.hasOwnProperty('evStatus')) { | ||
| if (newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].plugType == 1) { | ||
| //Slow = 1 -> Index 0 ist slow | ||
| slow_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| if (newStatus.vehicleStatus.evStatus.reservChargeInfos.hasOwnProperty('targetSOClist[0]')) { | ||
| if (newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].plugType == 1) { | ||
| //Slow = 1 -> Index 0 ist slow | ||
| slow_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[1].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| } else { | ||
| //fast = 0 -> Index 0 ist fast | ||
| slow_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[1].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[1].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| } | ||
| } else { | ||
| //fast = 0 -> Index 0 ist fast | ||
| slow_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[1].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.vehicleStatus.evStatus.reservChargeInfos.targetSOClist[0].targetSOClevel; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| } | ||
| } | ||
@@ -682,11 +684,11 @@ //Nur für Elektro Fahrzeuge - Battery | ||
| if (newStatus.ccs2Status.state.Vehicle.Green.BatteryManagement.hasOwnProperty('BatteryRemain')) { | ||
| await this.setStateAsync(vin + '.vehicleStatus.battery.soc', { | ||
| val: newStatus.ccs2Status.state.Vehicle.Green.BatteryManagement.BatteryRemain.Ratio, | ||
| ack: true | ||
| }); | ||
| } | ||
| if (newStatus.ccs2Status.state.hasOwnProperty('Vehicle') && newStatus.ccs2Status.state.Vehicle.Green.BatteryManagement.hasOwnProperty('BatteryRemain')) { | ||
| await this.setStateAsync(vin + '.vehicleStatus.battery.soc', { | ||
| val: newStatus.ccs2Status.state.Vehicle.Green.BatteryManagement.BatteryRemain.Ratio, | ||
| ack: true | ||
| }); | ||
| } | ||
| // hier nachschauen welcher DP | ||
| /* await this.setStateAsync(vin + '.vehicleStatus.battery.charge', { | ||
| /* await this.setStateAsync(vin + '.vehicleStatus.battery.charge', { | ||
| val: newStatus.vehicleStatus.?????, | ||
@@ -707,15 +709,15 @@ ack: true | ||
| //fast = 0 -> Index 0 ist fast | ||
| if (newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.hasOwnProperty('TargetSoC')) { | ||
| slow_charging = newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.TargetSoC.Standard; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.TargetSoC.Quick; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| } | ||
| if (newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.hasOwnProperty('TargetSoC')) { | ||
| slow_charging = newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.TargetSoC.Standard; | ||
| await this.setStateAsync(vin + '.control.charge_limit_slow', { | ||
| val: slow_charging, | ||
| ack: true, | ||
| }); | ||
| fast_charging = newStatus.ccs2Status.state.Vehicle.Green.ChargingInformation.TargetSoC.Quick; | ||
| await this.setStateAsync(vin + '.control.charge_limit_fast', { | ||
| val: fast_charging, | ||
| ack: true, | ||
| }); | ||
| } | ||
| } else { | ||
@@ -722,0 +724,0 @@ if (newStatus.vehicleStatus.hasOwnProperty('battery')) { |
+10
-8
| { | ||
| "name": "iobroker.bluelink", | ||
| "version": "3.0.3", | ||
| "version": "3.1.0", | ||
| "description": "Adapter to control Hyundai or Kia vehicle", | ||
@@ -40,8 +40,8 @@ "author": { | ||
| "dependencies": { | ||
| "@iobroker/adapter-core": "^3.1.3", | ||
| "@iobroker/adapter-core": "^3.1.6", | ||
| "bluelinky": "https://github.com/Hacksore/bluelinky/tarball/abdedb456ea792307a7429a503f8737d66b1beb8", | ||
| "axios": "^1.6.8" | ||
| "axios": "^1.7.7" | ||
| }, | ||
| "devDependencies": { | ||
| "@alcalzone/release-script": "^3.7.0", | ||
| "@alcalzone/release-script": "^3.8.0", | ||
| "@alcalzone/release-script-plugin-iobroker": "^3.7.2", | ||
@@ -51,3 +51,3 @@ "@alcalzone/release-script-plugin-license": "^3.7.0", | ||
| "@iobroker/testing": "^4.1.0", | ||
| "@types/node": "^20.12.7", | ||
| "@types/node": "^22.7.4", | ||
| "@types/chai": "^4.3.6", | ||
@@ -61,6 +61,8 @@ "@types/chai-as-promised": "^7.1.5", | ||
| "chai-as-promised": "^7.1.1", | ||
| "eslint": "^8.52.0", | ||
| "mocha": "^10.2.0", | ||
| "eslint": "^9.11.1", | ||
| "eslint-config-prettier": "^9.1.0", | ||
| "eslint-plugin-prettier": "^5.2.1", | ||
| "mocha": "^10.7.3", | ||
| "proxyquire": "^2.1.3", | ||
| "sinon": "^17.0.1", | ||
| "sinon": "^19.0.2", | ||
| "sinon-chai": "^3.7.0", | ||
@@ -67,0 +69,0 @@ "typescript": "^5.5.3" |
+7
-0
@@ -39,2 +39,9 @@  | ||
| ## Changelog | ||
| ### 3.1.0 (2024-10-05) | ||
| * (arteck) SOC corr | ||
| * (arteck) dependency update | ||
| ### 3.0.4 (2024-10-03) | ||
| * (arteck) typo | ||
| ### 3.0.3 (2024-10-02) | ||
@@ -41,0 +48,0 @@ * (arteck) add city to position text |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
118956
1.53%14
7.69%2203
2.47%173
4.22%22
10%Updated