iobroker.esphome 0.3.2 → 0.4.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/CHANGELOG_OLD.md CHANGED
@@ -1,4 +1,8 @@
1
1
  # Older changes
2
+ ## 0.2.3 (2021-06-29)
3
+ * (Jey-Cee) Bugfix : Light component state not changed [#74](https://github.com/DrozmotiX/ioBroker.esphome/issues/74)
4
+ * (DutchmanNL) Update compatibility to version 1.19.4 of ESPHome Dashboard
5
+
2
6
  ## 0.2.2 (2021-06-24)
3
7
  * (DutchmanNL) [!!! Breaking !!!] Make YAML file persistent, backup your configuration before updating ! solves [#57](https://github.com/DrozmotiX/ioBroker.esphome/issues/57)
4
8
  * (DutchmanNL) Update ESPHome Dashboard to 1.18.0, requires Python >=3.7 (and ensure <4.0!)
package/README.md CHANGED
@@ -112,29 +112,30 @@ If you like my work, please consider a personal donation
112
112
  ### __WORK IN PROGRESS__
113
113
  * (DutchmanNL)
114
114
  -->
115
+ ### 0.4.0 (2023-11-03)
116
+ * (DutchmanNL) Added cleanup capability for unused channels & states after initialisation of device, resolves #39
117
+ * (DutchmanNL) Added button to info channel which allows to delete all offline devices from adapter tree. resolves #39
118
+ * (DutchmanNL) [Breaking] Backup strategy changed, requires [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) and activate option for ESPHome, fixes #129
119
+
115
120
  ### 0.3.2 (2023-11-01)
116
121
  * (DutchmanNL) Improved error handling if devices are not reachable/disconnected
117
- * (DutchmanNL) Bugfix: Allow control of brightness and color for light component, fixes #173
122
+ * (DutchmanNL) Bugfix: Allow control of brightness and color for light component, resolves #173
118
123
 
119
124
  ### 0.3.1 (2023-10-31)
120
- * (DutchmanNL) Bugfix: Show online state of ESP Device correctly, Fixes #106
125
+ * (DutchmanNL) Bugfix: Show online state of ESP Device correctly, resolves #106
121
126
 
122
127
  ### 0.3.0 (2023-10-31) - Bugfixes & Improvements
123
128
  * (Dutchman & SimonFischer04) Several Bugfixes
124
129
  * (SimonFischer04) Support type "select device"
125
130
  * (DutchmanNL) ESPHome dashboard default disabled
126
131
  * (SimonFischer04) Migrate to @2colors/esphome-native-api
127
- * (DutchmanNL) Automatically create needed directories, Fixes #168
132
+ * (DutchmanNL) Automatically create needed directories, resolves #168
128
133
  * (SimonFischer04) Migrate usage of python to new structure, should solve all ESPHome Dashboard related installation issues
129
134
 
130
135
  ### 0.2.4 (2021-08-24)
131
136
  * (DutchmanNL) Version of ESPHome Dashboard updated to 2021.8
132
137
  * (DutchmanNL) Add option if config of ESPHome device should be shown as states (default = FALSE, safes 8 states for each sensor)
133
138
 
134
- ### 0.2.3 (2021-06-29)
135
- * (Jey-Cee) Bugfix : Light component state not changed [#74](https://github.com/DrozmotiX/ioBroker.esphome/issues/74)
136
- * (DutchmanNL) Update compatibility to version 1.19.4 of ESPHome Dashboard
137
-
138
139
  ## License
139
140
  MIT License
140
141
 
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "esphome",
4
- "version": "0.3.2",
4
+ "version": "0.4.0",
5
5
  "news": {
6
+ "0.4.0": {
7
+ "en": "Added cleanup capability for unused channels & states after initialisation of device, resolves #39\nAdded button to info channel which allows to delete all offline devices from adapter tree. resolves #39\n[Breaking] Backup strategy changed, requires [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) and activate option for ESPHome, fixes #129",
8
+ "de": "Zusätzliche Reinigungsfähigkeit für ungenutzte Kanäle & Zustände nach der Initialisierung des Geräts, löst #39\nZusätzlicher Button zum Info-Kanal, der alle Offline-Geräte aus dem Adapterbaum löschen kann. löst #39\n[Breaking] Backup-Strategie geändert, erfordert [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) und aktiviert Option für ESPHome, repariert #129",
9
+ "ru": "Добавлена возможность очистки неиспользуемых каналов и государств после инициализации устройства, решает #39\nДобавлена кнопка к информационному каналу, что позволяет удалить все оффлайн устройства из дерева адаптера. решает #39\n[Breaking] Стратегия резервного копирования изменена, требует [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) и активировать вариант для ESPHome, исправлений #129",
10
+ "pt": "Adicionado capacidade de limpeza para canais não utilizados & estados após a inicialização do dispositivo, resolve #39\nAdicionado botão para info canal que permite excluir todos os dispositivos off-line da árvore do adaptador. resolve #39\n[Breaking] Estratégia de backup alterada, requer [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) e opção ativa para ESPHome, correções #129",
11
+ "nl": "Vervoegde schoonmaak capaciteit voor onbruikbare kanalen apparaat na de initialisatie van 39\nKnop toegevoegd aan info kanaal dat alle offline apparaten van adapter boom laat verwijderen. 39\nOndersteuningsstrategie veranderde, vereist [Backitup v2.9.1, htps:com/simateioBroker, en tactiveer de optie van 12 uur",
12
+ "fr": "Ajout d'une capacité de nettoyage pour les canaux non utilisés & états après l'initialisation du dispositif, résout #39\nAjout du bouton sur le canal d'info qui permet de supprimer tous les périphériques hors ligne de l'arbre d'adaptateur. résolution #39\n[Breaking] La stratégie de sauvegarde a changé, nécessite [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) et l'option active pour ESPHome, corrige #129",
13
+ "it": "Aggiunta funzionalità di pulizia per canali e stati non utilizzati dopo l'inizializzazione del dispositivo, risolve #39\nPulsante aggiunto al canale info che consente di eliminare tutti i dispositivi offline dall'albero dell'adattatore. risolve #39\n[Breaking] La strategia di backup è cambiata, richiede [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) e attiva l'opzione per ESPHome, corregge #129",
14
+ "es": "Capacidad de limpieza agregada para canales no utilizados \" estados después de la inicialización del dispositivo, resuelve #39\nSe agregó botón a canal de información que permite eliminar todos los dispositivos fuera de línea del árbol del adaptador. resuelve #39\n[Breaking] La estrategia de respaldo cambió, requiere [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) y activar la opción para ESPHome, fija #129",
15
+ "pl": "Po zainicjowaniu możliwości usuwania nieużywanych kanałów i stanów po inicjalizacji urządzenia, rozwiązał #39\nNaciśnięty przycisk do kanału informacyjnego, który umożliwia usunięcie wszystkich urządzeń offline z drzewa adapterowego. Rozwiązanie #39\n(Po zmianie strategii Backupa, wymaga od BOATUTUp v2.9.1(https:/github.com/simatec/ioBroker.backitup) i aktywacji opcji dla ESPHome, naprawa #129",
16
+ "uk": "Додано можливість очищення каналів і станів після ініціалізації пристрою, вирішує #39\nДодано кнопку на інформаційний канал, який дозволяє видалити всі offline пристрої з дерева адаптера. розчини #39\n[Breaking] Стратегія резервного копіювання змінено, вимагає [BackitUp v2.9.1](https://github.com/simatec/ioBroker.backitup) і активувати варіант для ESPHome, фіксує #129",
17
+ "zh-cn": "在装置初始化后增加无用渠道和各州的清洁能力,第39号决定\n添加但道托顿以电器,使所有线装置能够从适应树中删除。 行动39\n[Breaking] Backup战略改变,要求[BackitUp v2.9.1](http://github.com/simatec/ioBroker.backitup)和“ESPHome”的主动选择,第129号行动。"
18
+ },
6
19
  "0.3.2": {
7
20
  "en": "Improved error handling if devices are not reachable/disconnected\nBugfix: Allow control of brightness and color for light component, fixes #173",
8
21
  "de": "Verbesserte Fehlerbehandlung, wenn Geräte nicht erreichbar/vernetzt sind\nBugfix: Erlauben Sie die Kontrolle von Helligkeit und Farbe für die Lichtkomponente, fixiert #173",
@@ -77,18 +90,6 @@
77
90
  "es": "[!!! ¡¡¡Rompiendo !!!] ¡Haga que el archivo YAML sea persistente, haga una copia de seguridad de su configuración antes de actualizar! resuelve [# 57] (https://github.com/DrozmotiX/ioBroker.esphome/issues/57)\nActualice ESPHome Dashboard a 1.18.0, requiere Python> = 3.7 (¡y asegúrese de <4.0!)\nCorrección de error: vuelva a conectarse a dispositivos sin detección automática / MDNS-Broadcast en la red, resuelve [# 66] (https://github.com/DrozmotiX/ioBroker.esphome/issues/66)",
78
91
  "pl": "[!!! Breaking !!!] Utrwal plik YAML, wykonaj kopię zapasową konfiguracji przed aktualizacją! rozwiązuje [#57](https://github.com/DrozmotiX/ioBroker.esphome/issues/57)\nZaktualizuj pulpit nawigacyjny ESPHome do wersji 1.18.0, wymaga Pythona >=3.7 (i upewnij się, że <4.0!)\nBugfix: Połącz się ponownie z urządzeniami bez automatycznego wykrywania / MDNS-Broadcast w sieci, rozwiązuje [#66](https://github.com/DrozmotiX/ioBroker.esphome/issues/66)",
79
92
  "zh-cn": "[!!!打破 !!!] 使 YAML 文件持久化,更新前备份您的配置!解决 [#57](https://github.com/DrozmotiX/ioBroker.esphome/issues/57)\n将 ESPHome Dashboard 更新到 1.18.0,需要 Python >=3.7(并确保 <4.0!)\n修正:在网络中没有自动发现/MDNS-Broadcast 的情况下重新连接到设备,解决[#66](https://github.com/DrozmotiX/ioBroker.esphome/issues/66)"
80
- },
81
- "0.2.1-1": {
82
- "en": "add cover component\nadd transitionLength for lights",
83
- "de": "Abdeckungskomponente hinzufügen\nÜbergangslänge für Lichter hinzufügen",
84
- "ru": "добавить компонент обложки\nдобавить transitionLength для огней",
85
- "pt": "adicionar componente de capa\nadicionar comprimento de transição para luzes",
86
- "nl": "voeg een omslagcomponent toe\nvoeg transitionLength toe voor lichten",
87
- "fr": "ajouter un composant de couverture\najouter une longueur de transition pour les lumières",
88
- "it": "aggiungi il componente di copertina\naggiungi TransitionLength per le luci",
89
- "es": "agregar componente de portada\nagregar transiciónLength para luces",
90
- "pl": "dodaj komponent okładki\ndodaj długość przejścia dla świateł",
91
- "zh-cn": "添加封面组件\n为灯光添加transitionLength"
92
93
  }
93
94
  },
94
95
  "title": "Control ESPHome managed devices",
@@ -145,7 +146,6 @@
145
146
  "dsn": "https://52227cfa250b49e99b1f28408273402c@sentry.iobroker.net/122"
146
147
  }
147
148
  },
148
- "dataFolder": "esphome.%INSTANCE%",
149
149
  "localLink": "http://%ESPHomeDashboardIP%:%ESPHomeDashboardPort%",
150
150
  "adminTab": {
151
151
  "link": "http://%ESPHomeDashboardIP%:%ESPHomeDashboardPort%",
package/main.js CHANGED
@@ -14,8 +14,10 @@ const stateAttr = require(__dirname + '/lib/stateAttr.js'); // Load attribute li
14
14
  const disableSentry = false; // Ensure to set to true during development!
15
15
  const warnMessages = {}; // Store warn messages to avoid multiple sending to sentry
16
16
  const fs = require('fs');
17
+ const {clearTimeout} = require('timers');
17
18
  const client = {};
18
- let reconnectTimer, reconnectInterval, apiPass, autodiscovery, dashboardProcess, createConfigStates;
19
+ const resetTimers = {}; // Memory allocation for all running timers
20
+ let reconnectInterval, apiPass, autodiscovery, dashboardProcess, createConfigStates;
19
21
 
20
22
  class Esphome extends utils.Adapter {
21
23
 
@@ -70,6 +72,21 @@ class Esphome extends utils.Adapter {
70
72
  this.log.info(`Native Integration of ESPHome Dashboard disabled `);
71
73
  }
72
74
 
75
+ // Create & Subscribe to button handling offline Device cleanup
76
+ this.extendObjectAsync('esphome.0.info.deviceCleanup',
77
+ {
78
+ 'type': 'state',
79
+ 'common': {
80
+ 'role': 'button',
81
+ 'name': 'Device or service connected',
82
+ 'type': 'boolean',
83
+ 'read': false,
84
+ 'write': true,
85
+ 'def': false
86
+ }
87
+ });
88
+ this.subscribeStates('esphome.0.info.deviceCleanup');
89
+
73
90
  } catch (e) {
74
91
  this.log.error(`[Adapter start] Fatal error occurred ${e}`);
75
92
  }
@@ -154,7 +171,7 @@ class Esphome extends utils.Adapter {
154
171
 
155
172
  // Get basic data of known devices and start reading data
156
173
  for (const i in knownDevices) {
157
- this.connectDevices(knownDevices[i].native.ip, this.decrypt(knownDevices[i].native.passWord));
174
+ this.connectDevices(knownDevices[i].native.ip);
158
175
  }
159
176
  } catch (e) {
160
177
  this.sendSentry(`[tryKnownDevices] ${e}`);
@@ -173,7 +190,7 @@ class Esphome extends utils.Adapter {
173
190
  this.log.debug(`Discovery message ${JSON.stringify(message)}`);
174
191
  if (this.deviceInfo[message.address] == null) {
175
192
  this.log.info(`[AutoDiscovery] New ESPHome device found at IP ${message.address}, trying to initialize`);
176
- this.connectDevices(`${message.address}`, `${apiPass}`);
193
+ this.connectDevices(`${message.address}`);
177
194
  }
178
195
  } catch (e) {
179
196
  this.log.error(`[deviceDiscovery handler] ${e}`);
@@ -188,9 +205,8 @@ class Esphome extends utils.Adapter {
188
205
  /**
189
206
  * Handle Socket connections
190
207
  * @param {string} host IP adress of device
191
- * @param {string | number | boolean} pass Password used for APU
192
208
  */
193
- connectDevices(host, pass) {
209
+ connectDevices(host) {
194
210
  try {
195
211
  // const host = espDevices[device].ip;
196
212
  this.log.info(`Try to connect to ${host}`);
@@ -237,6 +253,14 @@ class Esphome extends utils.Adapter {
237
253
  if (this.deviceInfo[host].deviceName != null) {
238
254
  this.setState(`${this.deviceInfo[host].deviceName}.info._online`, {val: false, ack: true});
239
255
 
256
+ // Check all created states in memory if their are related to this device
257
+ for (const state in this.createdStatesDetails) {
258
+ // Remove states from cache
259
+ if (state.split('.')[0] === this.deviceInfo[host].deviceName) {
260
+ delete this.createdStatesDetails[state];
261
+ }
262
+ }
263
+
240
264
  // Cache relevant data before clearing memory space of device
241
265
  const cacheDeviceInformation = {
242
266
  deviceName: this.deviceInfo[host].deviceName,
@@ -266,6 +290,12 @@ class Esphome extends utils.Adapter {
266
290
  client[host].on('initialized', () => {
267
291
  this.log.info(`ESPHome client ${this.deviceInfo[host].deviceInfoName} on ip ${host} initialized`);
268
292
  this.deviceInfo[host].initialized = true;
293
+
294
+ // Start timer to cleanup unneeded objects
295
+ if (resetTimers[host]) resetTimers[host] = clearTimeout(resetTimers[host]);
296
+ resetTimers[host] = setTimeout(async () => {
297
+ await this.objectCleanup(host);
298
+ }, (10000));
269
299
  });
270
300
 
271
301
  // Log message listener
@@ -286,7 +316,12 @@ class Esphome extends utils.Adapter {
286
316
  // Store device information into memory
287
317
  const deviceName = this.replaceAll(deviceInfo.macAddress, `:`, ``);
288
318
  this.deviceInfo[host] = {
319
+ adapterObjects : {
320
+ channels : []
321
+ },
289
322
  ip: host,
323
+ connectError : false,
324
+ connected : true,
290
325
  mac: deviceInfo.macAddress,
291
326
  deviceInfo: deviceInfo,
292
327
  deviceName: deviceName,
@@ -368,6 +403,11 @@ class Esphome extends utils.Adapter {
368
403
  native: {},
369
404
  });
370
405
 
406
+ // Cache created channel in device memory
407
+ if (!this.deviceInfo[host].adapterObjects.channels.includes(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}`)) {
408
+ this.deviceInfo[host].adapterObjects.channels.push(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}`);
409
+ }
410
+
371
411
  // Create state specific channel by id
372
412
  await this.extendObjectAsync(`${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}`, {
373
413
  type: 'channel',
@@ -377,6 +417,11 @@ class Esphome extends utils.Adapter {
377
417
  native: {},
378
418
  });
379
419
 
420
+ // Cache created channel in device memory
421
+ if (!this.deviceInfo[host].adapterObjects.channels.includes(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}`)) {
422
+ this.deviceInfo[host].adapterObjects.channels.push(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}`);
423
+ }
424
+
380
425
  //Check if config channel should be created
381
426
  if (!createConfigStates) {
382
427
  // Delete folder structure if already present
@@ -397,6 +442,12 @@ class Esphome extends utils.Adapter {
397
442
  },
398
443
  native: {},
399
444
  });
445
+
446
+ // Cache created channel in device memory
447
+ if (!this.deviceInfo[host].adapterObjects.channels.includes(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.config`)) {
448
+ this.deviceInfo[host].adapterObjects.channels.push(`${this.namespace}.${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.config`);
449
+ }
450
+
400
451
  // Handle Entity JSON structure and write related config channel data
401
452
  await this.TraverseJson(entity.config, `${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.config`);
402
453
  }
@@ -492,7 +543,7 @@ class Esphome extends utils.Adapter {
492
543
 
493
544
 
494
545
  } catch (e) {
495
- this.log.error(`Connection issue for ${entity.name} ${e}`);
546
+ this.log.error(`Connection issue for ${entity.name} ${e} | ${e.stack}`);
496
547
  }
497
548
 
498
549
  });
@@ -672,6 +723,8 @@ class Esphome extends utils.Adapter {
672
723
  // Check if state contains value
673
724
  if (transitionLength) {
674
725
  this.deviceInfo[host][entity.id].states.transitionLength = transitionLength.val;
726
+ // Run create state routine to ensure state is cached in memory
727
+ await this.stateSetCreate(`${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.transitionLength`, `${stateName} of ${entity.config.name}`, transitionLength.val, `s`, writable);
675
728
  } else { // Else just create it
676
729
  await this.stateSetCreate(`${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.transitionLength`, `${stateName} of ${entity.config.name}`, 0, `s`, writable);
677
730
  this.deviceInfo[host][entity.id].states.transitionLength = 0;
@@ -948,6 +1001,8 @@ class Esphome extends utils.Adapter {
948
1001
  onUnload(callback) {
949
1002
  try {
950
1003
  this.log.debug(JSON.stringify(this.deviceInfo));
1004
+
1005
+ // Set all online states to false
951
1006
  for (const device in this.deviceInfo) {
952
1007
 
953
1008
  // Ensure all known online states are set to false
@@ -962,9 +1017,12 @@ class Esphome extends utils.Adapter {
962
1017
  this.log.debug(`[onUnload] ${JSON.stringify(e)}`);
963
1018
  }
964
1019
  }
965
- if (reconnectTimer) {
966
- reconnectTimer = clearTimeout();
1020
+
1021
+ // Ensure all possible running timers are cleared
1022
+ for (const timer in resetTimers) {
1023
+ if (resetTimers[timer]) resetTimers[timer] = clearTimeout(resetTimers[timer]);
967
1024
  }
1025
+
968
1026
  try {
969
1027
  if (dashboardProcess) {
970
1028
  dashboardProcess.kill('SIGTERM', {
@@ -1029,7 +1087,7 @@ class Esphome extends utils.Adapter {
1029
1087
  this.log.info(`Valid IP address received`);
1030
1088
  this.messageResponse[obj.message['device-ip']] = obj;
1031
1089
  // const pass = this.decrypt(obj.message['device-pass']);
1032
- await this.connectDevices(obj.message['device-ip'], apiPass);
1090
+ await this.connectDevices(obj.message['device-ip']);
1033
1091
  }
1034
1092
  break;
1035
1093
  }
@@ -1079,6 +1137,17 @@ class Esphome extends utils.Adapter {
1079
1137
  try {
1080
1138
  if (state && state.ack === false) {
1081
1139
  const device = id.split('.');
1140
+
1141
+ try {
1142
+ // Verify if trigger is related to device-cleanup
1143
+ if (id.split('.')[3] === 'deviceCleanup'){
1144
+ await this.offlineDeviceCleanup();
1145
+ return;
1146
+ }
1147
+ } catch (e) {
1148
+ // Skip action
1149
+ }
1150
+
1082
1151
  const deviceIP = this.deviceStateRelation[device[2]].ip;
1083
1152
 
1084
1153
  // Handle Switch State
@@ -1233,6 +1302,77 @@ class Esphome extends utils.Adapter {
1233
1302
  this.log.error(`[resetOnlineState] ${e}`);
1234
1303
  }
1235
1304
  }
1305
+
1306
+ async objectCleanup(ip){
1307
+ try {
1308
+ this.log.debug(`[objectCleanup] Starting channel and state cleanup for ${this.deviceInfo[ip].deviceName} | ${ip} | ${this.deviceInfo[ip].ip}`);
1309
+
1310
+ // Cancel cleanup operation in case device is not connected anymore
1311
+ if (this.deviceInfo[ip].connectionError || !this.deviceInfo[ip].connected) return;
1312
+
1313
+ // Set parameters for object view to only include objects within adapter namespace
1314
+ const params = {
1315
+ startkey : `${this.namespace}.${this.deviceInfo[ip].deviceName}.`,
1316
+ endkey : `${this.namespace}.\u9999`,
1317
+ };
1318
+
1319
+ // Get all current channels
1320
+ const _channels = await this.getObjectViewAsync('system', 'channel', params);
1321
+ // List all found channels & compare with memory, delete unneeded channels
1322
+ for (const currDevice in _channels.rows) {
1323
+ // @ts-ignore
1324
+ if (!this.deviceInfo[ip].adapterObjects.channels.includes(_channels.rows[currDevice].id)
1325
+ && _channels.rows[currDevice].id.split('.')[2] === this.deviceInfo[ip].deviceName){
1326
+ this.log.debug(`[objectCleanup] Unknown Channel found, delete ${_channels.rows[currDevice].id}`);
1327
+ await this.delObjectAsync(_channels.rows[currDevice].id, {recursive: true});
1328
+ }
1329
+ }
1330
+
1331
+ // Get all current states in adapter tree
1332
+ const _states = await this.getObjectViewAsync('system', 'state', params);
1333
+ // List all found states & compare with memory, delete unneeded states
1334
+ for (const currDevice in _states.rows) {
1335
+ if (!this.createdStatesDetails[_states.rows[currDevice].id.replace(`esphome.0.`, ``)]
1336
+ && _states.rows[currDevice].id.split('.')[2] === this.deviceInfo[ip].deviceName){
1337
+ this.log.debug(`[objectCleanup] Unknown State found, delete ${_states.rows[currDevice].id}`);
1338
+ // await this.delObjectAsync(_states.rows[currDevice].id);
1339
+ }
1340
+ }
1341
+
1342
+ } catch (e) {
1343
+ this.log.error(`[objectCleanup] Fatal error ${e} | ${e.stack}`);
1344
+ }
1345
+ }
1346
+
1347
+ async offlineDeviceCleanup () {
1348
+ this.log.info(`Offline Device cleanup started`);
1349
+
1350
+ try {
1351
+
1352
+ // Get an overview of all current devices known by adapter
1353
+ const knownDevices = await this.getDevicesAsync();
1354
+ console.log(`KnownDevices: ${knownDevices}`);
1355
+
1356
+ // Loop to all devices, check if online state = TRUE otherwise delete device
1357
+ for (const device in knownDevices){
1358
+
1359
+ // Get online value
1360
+ const online = await this.getStateAsync(`${knownDevices[device]._id}.info._online`);
1361
+ if (!online || !online.val){
1362
+ this.log.info(`Offline device ${knownDevices[device]._id.split('.')[2]} expected on ip ${knownDevices[device].native.ip} removed`);
1363
+ await this.delObjectAsync(knownDevices[device]._id, {recursive: true});
1364
+ }
1365
+
1366
+ }
1367
+
1368
+ if (!knownDevices) return; // exit function if no known device are detected
1369
+ if (knownDevices.length > 0) this.log.info(`Try to contact ${knownDevices.length} known devices`);
1370
+ } catch (e) {
1371
+ this.log.error(`[offlineDeviceCleanup] Fatal error occurred, cannot cleanup offline devices ${e} | ${e.stack}`);
1372
+
1373
+ }
1374
+ }
1375
+
1236
1376
  }
1237
1377
 
1238
1378
  if (require.main !== module) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.esphome",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Control your ESP8266/ESP32 with simple yet powerful configuration files created and managed by ESPHome",
5
5
  "author": {
6
6
  "name": "DutchmanNL",