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 +4 -0
- package/README.md +8 -7
- package/io-package.json +14 -14
- package/main.js +149 -9
- package/package.json +1 -1
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,
|
|
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,
|
|
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,
|
|
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.
|
|
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
|
-
|
|
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
|
|
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}
|
|
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
|
|
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
|
-
|
|
966
|
-
|
|
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']
|
|
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) {
|