iobroker.esphome 0.3.1 → 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 +9 -0
- package/README.md +11 -11
- package/io-package.json +27 -26
- package/main.js +227 -52
- package/package.json +4 -1
package/CHANGELOG_OLD.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
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
|
+
|
|
6
|
+
## 0.2.2 (2021-06-24)
|
|
7
|
+
* (DutchmanNL) [!!! Breaking !!!] Make YAML file persistent, backup your configuration before updating ! solves [#57](https://github.com/DrozmotiX/ioBroker.esphome/issues/57)
|
|
8
|
+
* (DutchmanNL) Update ESPHome Dashboard to 1.18.0, requires Python >=3.7 (and ensure <4.0!)
|
|
9
|
+
* (DutchmanNL) Bugfix : Reconnect to devices without autodiscovery / MDNS-Broadcast in network, solves [#66](https://github.com/DrozmotiX/ioBroker.esphome/issues/66)
|
|
10
|
+
|
|
2
11
|
## 0.2.1-1 (2021-03-30)
|
|
3
12
|
* (DutchmanNL) add cover component
|
|
4
13
|
* (DutchmanNL) add transitionLength for lights
|
package/README.md
CHANGED
|
@@ -112,30 +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
|
+
|
|
120
|
+
### 0.3.2 (2023-11-01)
|
|
121
|
+
* (DutchmanNL) Improved error handling if devices are not reachable/disconnected
|
|
122
|
+
* (DutchmanNL) Bugfix: Allow control of brightness and color for light component, resolves #173
|
|
123
|
+
|
|
115
124
|
### 0.3.1 (2023-10-31)
|
|
116
|
-
* (DutchmanNL) Bugfix: Show online state of ESP Device correctly,
|
|
125
|
+
* (DutchmanNL) Bugfix: Show online state of ESP Device correctly, resolves #106
|
|
117
126
|
|
|
118
127
|
### 0.3.0 (2023-10-31) - Bugfixes & Improvements
|
|
119
128
|
* (Dutchman & SimonFischer04) Several Bugfixes
|
|
120
129
|
* (SimonFischer04) Support type "select device"
|
|
121
130
|
* (DutchmanNL) ESPHome dashboard default disabled
|
|
122
131
|
* (SimonFischer04) Migrate to @2colors/esphome-native-api
|
|
123
|
-
* (DutchmanNL) Automatically create needed directories,
|
|
132
|
+
* (DutchmanNL) Automatically create needed directories, resolves #168
|
|
124
133
|
* (SimonFischer04) Migrate usage of python to new structure, should solve all ESPHome Dashboard related installation issues
|
|
125
134
|
|
|
126
135
|
### 0.2.4 (2021-08-24)
|
|
127
136
|
* (DutchmanNL) Version of ESPHome Dashboard updated to 2021.8
|
|
128
137
|
* (DutchmanNL) Add option if config of ESPHome device should be shown as states (default = FALSE, safes 8 states for each sensor)
|
|
129
138
|
|
|
130
|
-
### 0.2.3 (2021-06-29)
|
|
131
|
-
* (Jey-Cee) Bugfix : Light component state not changed [#74](https://github.com/DrozmotiX/ioBroker.esphome/issues/74)
|
|
132
|
-
* (DutchmanNL) Update compatibility to version 1.19.4 of ESPHome Dashboard
|
|
133
|
-
|
|
134
|
-
### 0.2.2 (2021-06-24)
|
|
135
|
-
* (DutchmanNL) [!!! Breaking !!!] Make YAML file persistent, backup your configuration before updating ! solves [#57](https://github.com/DrozmotiX/ioBroker.esphome/issues/57)
|
|
136
|
-
* (DutchmanNL) Update ESPHome Dashboard to 1.18.0, requires Python >=3.7 (and ensure <4.0!)
|
|
137
|
-
* (DutchmanNL) Bugfix : Reconnect to devices without autodiscovery / MDNS-Broadcast in network, solves [#66](https://github.com/DrozmotiX/ioBroker.esphome/issues/66)
|
|
138
|
-
|
|
139
139
|
## License
|
|
140
140
|
MIT License
|
|
141
141
|
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
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
|
+
},
|
|
19
|
+
"0.3.2": {
|
|
20
|
+
"en": "Improved error handling if devices are not reachable/disconnected\nBugfix: Allow control of brightness and color for light component, fixes #173",
|
|
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",
|
|
22
|
+
"ru": "Улучшена обработка ошибок, если устройства не доступны / отключены\nBugfix: Разрешить контроль яркости и цвета для легкой составляющей, исправляет #173",
|
|
23
|
+
"pt": "Melhor manuseio de erros se os dispositivos não forem acessíveis/desconectados\nBugfix: Permitir controle de brilho e cor para componente de luz, correções #173",
|
|
24
|
+
"nl": "Improviserende fouten als de apparatuur niet bereikbaar is\nBugfix: Controle van helderheid en kleur voor lichtcomonent, reparatie #173",
|
|
25
|
+
"fr": "Amélioration de la manipulation des erreurs si les dispositifs ne sont pas accessibles/déconnectés\nBugfix: Permettre le contrôle de la luminosité et de la couleur pour le composant de lumière, corrige #173",
|
|
26
|
+
"it": "Miglioramento della gestione degli errori se i dispositivi non sono raggiungibili/disconnessi\nBugfix: Consentire il controllo di luminosità e colore per componenti leggeri, correzioni #173",
|
|
27
|
+
"es": "Mejor manejo de errores si los dispositivos no son accesibles/desconectados\nBugfix: Permitir el control del brillo y el color para el componente de luz, fija #173",
|
|
28
|
+
"pl": "Poprawiona obsługa błędów, jeśli urządzenia nie są dosyć dopasowalne i rozproszone\nBugfix: Allow kontrola jasności i koloru dla komponentów świetlnych naprawia numer #173",
|
|
29
|
+
"uk": "Поліпшення обробки помилок, якщо пристрої не досягаються / відключені\nПомилки: Дозволяє контролювати яскравість і колір для легкого компонента, закріплює #173",
|
|
30
|
+
"zh-cn": "如果装置无法达到/无联系,改进错误处理\nBugfix: 允许控制光明和颜色,确定第173号行动。"
|
|
31
|
+
},
|
|
6
32
|
"0.3.1": {
|
|
7
33
|
"en": "Bugfix: Show online state of ESP Device correctly, Fixes #106",
|
|
8
34
|
"de": "Bugfix: Online-Zustand von ESP Device korrekt anzeigen, Fixes #106",
|
|
@@ -64,30 +90,6 @@
|
|
|
64
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)",
|
|
65
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)",
|
|
66
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)"
|
|
67
|
-
},
|
|
68
|
-
"0.2.1-1": {
|
|
69
|
-
"en": "add cover component\nadd transitionLength for lights",
|
|
70
|
-
"de": "Abdeckungskomponente hinzufügen\nÜbergangslänge für Lichter hinzufügen",
|
|
71
|
-
"ru": "добавить компонент обложки\nдобавить transitionLength для огней",
|
|
72
|
-
"pt": "adicionar componente de capa\nadicionar comprimento de transição para luzes",
|
|
73
|
-
"nl": "voeg een omslagcomponent toe\nvoeg transitionLength toe voor lichten",
|
|
74
|
-
"fr": "ajouter un composant de couverture\najouter une longueur de transition pour les lumières",
|
|
75
|
-
"it": "aggiungi il componente di copertina\naggiungi TransitionLength per le luci",
|
|
76
|
-
"es": "agregar componente de portada\nagregar transiciónLength para luces",
|
|
77
|
-
"pl": "dodaj komponent okładki\ndodaj długość przejścia dla świateł",
|
|
78
|
-
"zh-cn": "添加封面组件\n为灯光添加transitionLength"
|
|
79
|
-
},
|
|
80
|
-
"0.2.1-0": {
|
|
81
|
-
"en": "Logging improved, solves [#48](https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nName of states changed, solves [#49](https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
82
|
-
"de": "Protokollierung verbessert, löst [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nName der Staaten geändert, löst [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
83
|
-
"ru": "Ведение журнала улучшено, решает [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nНазвание состояний изменено, решает [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
84
|
-
"pt": "Logging melhorado, resolve [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nNome dos estados alterados, resolve [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
85
|
-
"nl": "Logboekregistratie verbeterd, lost op [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nNaam van staten gewijzigd, lost [# 49] op (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
86
|
-
"fr": "Journalisation améliorée, résout [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nLe nom des états a changé, résout [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
87
|
-
"it": "Registrazione migliorata, risolve [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nIl nome degli stati è cambiato, risolve [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
88
|
-
"es": "Registro mejorado, resuelve [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nNombre de los estados cambiado, resuelve [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
89
|
-
"pl": "Logowanie poprawione, rozwiązuje [# 48] (https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\nZmiana nazwy stanów, rozwiązuje [# 49] (https://github.com/DrozmotiX/ioBroker.esphome/issues/49)",
|
|
90
|
-
"zh-cn": "日志记录得到改进,解决了[#48](https://github.com/DrozmotiX/ioBroker.esphome/issues/48)\n状态名称更改,解决[#49](https://github.com/DrozmotiX/ioBroker.esphome/issues/49)"
|
|
91
93
|
}
|
|
92
94
|
},
|
|
93
95
|
"title": "Control ESPHome managed devices",
|
|
@@ -144,7 +146,6 @@
|
|
|
144
146
|
"dsn": "https://52227cfa250b49e99b1f28408273402c@sentry.iobroker.net/122"
|
|
145
147
|
}
|
|
146
148
|
},
|
|
147
|
-
"dataFolder": "esphome.%INSTANCE%",
|
|
148
149
|
"localLink": "http://%ESPHomeDashboardIP%:%ESPHomeDashboardPort%",
|
|
149
150
|
"adminTab": {
|
|
150
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,8 +72,23 @@ 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
|
-
this.log.error(`
|
|
91
|
+
this.log.error(`[Adapter start] Fatal error occurred ${e}`);
|
|
75
92
|
}
|
|
76
93
|
}
|
|
77
94
|
|
|
@@ -154,11 +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.
|
|
158
|
-
ip: knownDevices[i].native.ip,
|
|
159
|
-
passWord: this.decrypt(knownDevices[i].native.passWord),
|
|
160
|
-
};
|
|
161
|
-
this.connectDevices(knownDevices[i].native.ip, this.deviceInfo[knownDevices[i].native.ip].passWord);
|
|
174
|
+
this.connectDevices(knownDevices[i].native.ip);
|
|
162
175
|
}
|
|
163
176
|
} catch (e) {
|
|
164
177
|
this.sendSentry(`[tryKnownDevices] ${e}`);
|
|
@@ -176,13 +189,8 @@ class Esphome extends utils.Adapter {
|
|
|
176
189
|
try {
|
|
177
190
|
this.log.debug(`Discovery message ${JSON.stringify(message)}`);
|
|
178
191
|
if (this.deviceInfo[message.address] == null) {
|
|
179
|
-
this.log.info(`[AutoDiscovery] New ESPHome device found at IP ${message.address}`);
|
|
180
|
-
|
|
181
|
-
this.deviceInfo[message.address] = {
|
|
182
|
-
ip: message.address,
|
|
183
|
-
passWord: apiPass
|
|
184
|
-
};
|
|
185
|
-
this.connectDevices(`${message.address}`, `${apiPass}`);
|
|
192
|
+
this.log.info(`[AutoDiscovery] New ESPHome device found at IP ${message.address}, trying to initialize`);
|
|
193
|
+
this.connectDevices(`${message.address}`);
|
|
186
194
|
}
|
|
187
195
|
} catch (e) {
|
|
188
196
|
this.log.error(`[deviceDiscovery handler] ${e}`);
|
|
@@ -197,16 +205,15 @@ class Esphome extends utils.Adapter {
|
|
|
197
205
|
/**
|
|
198
206
|
* Handle Socket connections
|
|
199
207
|
* @param {string} host IP adress of device
|
|
200
|
-
* @param {string | number | boolean} pass Password used for APU
|
|
201
208
|
*/
|
|
202
|
-
connectDevices(host
|
|
209
|
+
connectDevices(host) {
|
|
203
210
|
try {
|
|
204
211
|
// const host = espDevices[device].ip;
|
|
205
212
|
this.log.info(`Try to connect to ${host}`);
|
|
206
213
|
// Prepare connection attributes
|
|
207
214
|
client[host] = new Client({
|
|
208
215
|
host: host,
|
|
209
|
-
password:
|
|
216
|
+
password: apiPass,
|
|
210
217
|
clientInfo: `${this.host}`,
|
|
211
218
|
clearSession: true,
|
|
212
219
|
initializeDeviceInfo: true,
|
|
@@ -223,6 +230,16 @@ class Esphome extends utils.Adapter {
|
|
|
223
230
|
// Connection listener
|
|
224
231
|
client[host].on('connected', async () => {
|
|
225
232
|
try {
|
|
233
|
+
// Clear any existing memory information for this device
|
|
234
|
+
delete this.deviceInfo[host];
|
|
235
|
+
|
|
236
|
+
// Reserve basic memory information for this device
|
|
237
|
+
this.deviceInfo[host] = {
|
|
238
|
+
connected : true,
|
|
239
|
+
connectionError : false,
|
|
240
|
+
initialized: false,
|
|
241
|
+
ip : host
|
|
242
|
+
};
|
|
226
243
|
this.log.info(`ESPHome client ${host} connected`);
|
|
227
244
|
// Clear possible present warn messages for device from previous connection
|
|
228
245
|
delete warnMessages[host];
|
|
@@ -231,13 +248,39 @@ class Esphome extends utils.Adapter {
|
|
|
231
248
|
}
|
|
232
249
|
});
|
|
233
250
|
|
|
234
|
-
client[host].on('disconnected', () =>
|
|
251
|
+
client[host].on('disconnected', () => {
|
|
235
252
|
try {
|
|
236
253
|
if (this.deviceInfo[host].deviceName != null) {
|
|
237
254
|
this.setState(`${this.deviceInfo[host].deviceName}.info._online`, {val: false, ack: true});
|
|
238
|
-
|
|
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
|
+
|
|
264
|
+
// Cache relevant data before clearing memory space of device
|
|
265
|
+
const cacheDeviceInformation = {
|
|
266
|
+
deviceName: this.deviceInfo[host].deviceName,
|
|
267
|
+
deviceInfoName: this.deviceInfo[host].deviceInfoName,
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// Clear any existing memory information for this device
|
|
271
|
+
delete this.deviceInfo[host];
|
|
272
|
+
|
|
273
|
+
// Reserve basic memory information for this device
|
|
274
|
+
this.deviceInfo[host] = {
|
|
275
|
+
connected : false,
|
|
276
|
+
connectionError : true,
|
|
277
|
+
deviceName : cacheDeviceInformation.deviceName,
|
|
278
|
+
deviceInfoName : cacheDeviceInformation.deviceInfoName,
|
|
279
|
+
ip : host
|
|
280
|
+
};
|
|
281
|
+
this.log.warn(`ESPHome client ${this.deviceInfo[host].deviceInfoName} | ${this.deviceInfo[host].deviceName} | on ${host} disconnected`);
|
|
239
282
|
} else {
|
|
240
|
-
this.log.warn(`ESPHome
|
|
283
|
+
this.log.warn(`ESPHome client ${host} disconnected`);
|
|
241
284
|
}
|
|
242
285
|
} catch (e) {
|
|
243
286
|
this.log.debug(`ESPHome disconnect error : ${e}`);
|
|
@@ -245,20 +288,23 @@ class Esphome extends utils.Adapter {
|
|
|
245
288
|
});
|
|
246
289
|
|
|
247
290
|
client[host].on('initialized', () => {
|
|
248
|
-
this.log.info(`ESPHome client ${this.deviceInfo[host].
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
291
|
+
this.log.info(`ESPHome client ${this.deviceInfo[host].deviceInfoName} on ip ${host} initialized`);
|
|
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));
|
|
253
299
|
});
|
|
254
300
|
|
|
255
301
|
// Log message listener
|
|
256
302
|
client[host].connection.on('message', (/** @type {object} */ message) => {
|
|
257
|
-
this.log.debug(
|
|
303
|
+
this.log.debug(`[ESPHome Device Message] ${host} client log ${message}`);
|
|
258
304
|
});
|
|
259
305
|
|
|
260
306
|
client[host].connection.on('data', (/** @type {object} */ data) => {
|
|
261
|
-
this.log.debug(
|
|
307
|
+
this.log.debug(`[ESPHome Device Data] ${host} client data ${data}`);
|
|
262
308
|
});
|
|
263
309
|
|
|
264
310
|
// Handle device information when connected or information updated
|
|
@@ -270,15 +316,21 @@ class Esphome extends utils.Adapter {
|
|
|
270
316
|
// Store device information into memory
|
|
271
317
|
const deviceName = this.replaceAll(deviceInfo.macAddress, `:`, ``);
|
|
272
318
|
this.deviceInfo[host] = {
|
|
319
|
+
adapterObjects : {
|
|
320
|
+
channels : []
|
|
321
|
+
},
|
|
273
322
|
ip: host,
|
|
323
|
+
connectError : false,
|
|
324
|
+
connected : true,
|
|
274
325
|
mac: deviceInfo.macAddress,
|
|
275
326
|
deviceInfo: deviceInfo,
|
|
276
327
|
deviceName: deviceName,
|
|
277
328
|
deviceInfoName: deviceInfo.name,
|
|
278
|
-
passWord:
|
|
329
|
+
passWord: apiPass,
|
|
279
330
|
};
|
|
280
331
|
|
|
281
|
-
// Store MAC & IP relation
|
|
332
|
+
// Store MAC & IP relation, delete possible existing entry before
|
|
333
|
+
delete this.deviceStateRelation[deviceName];
|
|
282
334
|
this.deviceStateRelation[deviceName] = {'ip': host};
|
|
283
335
|
|
|
284
336
|
this.log.debug(`DeviceInfo ${this.deviceInfo[host].deviceInfo.name}: ${JSON.stringify(this.deviceInfo)}`);
|
|
@@ -297,7 +349,7 @@ class Esphome extends utils.Adapter {
|
|
|
297
349
|
name: this.deviceInfo[host].deviceInfoName,
|
|
298
350
|
mac: deviceInfo.macAddress,
|
|
299
351
|
deviceName: deviceName,
|
|
300
|
-
passWord: this.encrypt(
|
|
352
|
+
passWord: this.encrypt(apiPass),
|
|
301
353
|
},
|
|
302
354
|
});
|
|
303
355
|
|
|
@@ -351,6 +403,11 @@ class Esphome extends utils.Adapter {
|
|
|
351
403
|
native: {},
|
|
352
404
|
});
|
|
353
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
|
+
|
|
354
411
|
// Create state specific channel by id
|
|
355
412
|
await this.extendObjectAsync(`${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}`, {
|
|
356
413
|
type: 'channel',
|
|
@@ -360,6 +417,11 @@ class Esphome extends utils.Adapter {
|
|
|
360
417
|
native: {},
|
|
361
418
|
});
|
|
362
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
|
+
|
|
363
425
|
//Check if config channel should be created
|
|
364
426
|
if (!createConfigStates) {
|
|
365
427
|
// Delete folder structure if already present
|
|
@@ -380,6 +442,12 @@ class Esphome extends utils.Adapter {
|
|
|
380
442
|
},
|
|
381
443
|
native: {},
|
|
382
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
|
+
|
|
383
451
|
// Handle Entity JSON structure and write related config channel data
|
|
384
452
|
await this.TraverseJson(entity.config, `${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.config`);
|
|
385
453
|
}
|
|
@@ -390,7 +458,7 @@ class Esphome extends utils.Adapter {
|
|
|
390
458
|
await client[host].connection.subscribeStatesService();
|
|
391
459
|
this.log.debug(`[DeviceInfoData] ${this.deviceInfo[host].deviceInfo.name} ${JSON.stringify(this.deviceInfo[host])}`);
|
|
392
460
|
|
|
393
|
-
// Listen to state changes
|
|
461
|
+
// Listen to state changes and write values to states (create state if not yet exists)
|
|
394
462
|
entity.on(`state`, async (/** @type {object} */ state) => {
|
|
395
463
|
this.log.debug(`StateData: ${JSON.stringify(state)}`);
|
|
396
464
|
try {
|
|
@@ -475,7 +543,7 @@ class Esphome extends utils.Adapter {
|
|
|
475
543
|
|
|
476
544
|
|
|
477
545
|
} catch (e) {
|
|
478
|
-
this.log.error(`Connection issue for ${entity.name} ${e}`);
|
|
546
|
+
this.log.error(`Connection issue for ${entity.name} ${e} | ${e.stack}`);
|
|
479
547
|
}
|
|
480
548
|
|
|
481
549
|
});
|
|
@@ -483,23 +551,46 @@ class Esphome extends utils.Adapter {
|
|
|
483
551
|
// Connection data handler
|
|
484
552
|
client[host].on('error', (error) => {
|
|
485
553
|
try {
|
|
554
|
+
|
|
555
|
+
// Reserve memory space for connection error if not already exist
|
|
556
|
+
if (!this.deviceInfo[host]){
|
|
557
|
+
this.deviceInfo[host] = {
|
|
558
|
+
ip : host,
|
|
559
|
+
connectError : false,
|
|
560
|
+
connected : false
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
486
564
|
let optimisedError = error.message;
|
|
487
565
|
// Optimise error messages
|
|
488
|
-
if (error.
|
|
489
|
-
optimisedError = `Client ${
|
|
490
|
-
if (!
|
|
566
|
+
if (error.code === 'ETIMEDOUT') {
|
|
567
|
+
optimisedError = `Client ${host} not reachable !`;
|
|
568
|
+
if (!this.deviceInfo[host].connectError) {
|
|
491
569
|
this.log.error(optimisedError);
|
|
492
|
-
|
|
570
|
+
this.deviceInfo[host].connectError = true;
|
|
493
571
|
}
|
|
494
572
|
} else if (error.message.includes('Invalid password')) {
|
|
495
573
|
optimisedError = `Client ${host} incorrect password !`;
|
|
496
|
-
this.
|
|
574
|
+
if (!this.deviceInfo[host].connectError) {
|
|
575
|
+
this.log.error(optimisedError);
|
|
576
|
+
this.deviceInfo[host].connectError = true;
|
|
577
|
+
}
|
|
497
578
|
} else if (error.message.includes('ECONNRESET')) {
|
|
498
|
-
optimisedError = `Client ${
|
|
499
|
-
this.
|
|
579
|
+
optimisedError = `Client ${host} Connection Lost, will reconnect automatically when device is available!`;
|
|
580
|
+
if (!this.deviceInfo[host].connectError) {
|
|
581
|
+
this.log.warn(optimisedError);
|
|
582
|
+
this.deviceInfo[host].connectError = true;
|
|
583
|
+
}
|
|
500
584
|
} else if (error.message.includes('timeout')) {
|
|
501
|
-
optimisedError = `Client ${host} Timeout,
|
|
585
|
+
optimisedError = `Client ${host} Timeout, will reconnect automatically when device is available!`;
|
|
586
|
+
if (!this.deviceInfo[host].connectError) {
|
|
587
|
+
this.log.warn(optimisedError);
|
|
588
|
+
this.deviceInfo[host].connectError = true;
|
|
589
|
+
}
|
|
590
|
+
} else if (error.message.includes('ECONNREFUSED')) {
|
|
591
|
+
optimisedError = `Client ${host} not yet ready to connect, will try again!`;
|
|
502
592
|
this.log.warn(optimisedError);
|
|
593
|
+
|
|
503
594
|
} else if (error.message.includes('write after end')) {
|
|
504
595
|
// Ignore error
|
|
505
596
|
} else {
|
|
@@ -527,10 +618,6 @@ class Esphome extends utils.Adapter {
|
|
|
527
618
|
// connect to socket
|
|
528
619
|
try {
|
|
529
620
|
this.log.debug(`trying to connect to ${host}`);
|
|
530
|
-
// Reserve memory for warn messages
|
|
531
|
-
warnMessages[host] = {
|
|
532
|
-
connectError: false
|
|
533
|
-
};
|
|
534
621
|
client[host].connect();
|
|
535
622
|
} catch (e) {
|
|
536
623
|
this.log.error(`Client ${host} connect error ${e}`);
|
|
@@ -636,6 +723,8 @@ class Esphome extends utils.Adapter {
|
|
|
636
723
|
// Check if state contains value
|
|
637
724
|
if (transitionLength) {
|
|
638
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);
|
|
639
728
|
} else { // Else just create it
|
|
640
729
|
await this.stateSetCreate(`${this.deviceInfo[host].deviceName}.${entity.type}.${entity.id}.transitionLength`, `${stateName} of ${entity.config.name}`, 0, `s`, writable);
|
|
641
730
|
this.deviceInfo[host][entity.id].states.transitionLength = 0;
|
|
@@ -912,6 +1001,8 @@ class Esphome extends utils.Adapter {
|
|
|
912
1001
|
onUnload(callback) {
|
|
913
1002
|
try {
|
|
914
1003
|
this.log.debug(JSON.stringify(this.deviceInfo));
|
|
1004
|
+
|
|
1005
|
+
// Set all online states to false
|
|
915
1006
|
for (const device in this.deviceInfo) {
|
|
916
1007
|
|
|
917
1008
|
// Ensure all known online states are set to false
|
|
@@ -926,9 +1017,12 @@ class Esphome extends utils.Adapter {
|
|
|
926
1017
|
this.log.debug(`[onUnload] ${JSON.stringify(e)}`);
|
|
927
1018
|
}
|
|
928
1019
|
}
|
|
929
|
-
|
|
930
|
-
|
|
1020
|
+
|
|
1021
|
+
// Ensure all possible running timers are cleared
|
|
1022
|
+
for (const timer in resetTimers) {
|
|
1023
|
+
if (resetTimers[timer]) resetTimers[timer] = clearTimeout(resetTimers[timer]);
|
|
931
1024
|
}
|
|
1025
|
+
|
|
932
1026
|
try {
|
|
933
1027
|
if (dashboardProcess) {
|
|
934
1028
|
dashboardProcess.kill('SIGTERM', {
|
|
@@ -992,8 +1086,8 @@ class Esphome extends utils.Adapter {
|
|
|
992
1086
|
} else {
|
|
993
1087
|
this.log.info(`Valid IP address received`);
|
|
994
1088
|
this.messageResponse[obj.message['device-ip']] = obj;
|
|
995
|
-
const pass = this.decrypt(obj.message['device-pass']);
|
|
996
|
-
await this.connectDevices(obj.message['device-ip']
|
|
1089
|
+
// const pass = this.decrypt(obj.message['device-pass']);
|
|
1090
|
+
await this.connectDevices(obj.message['device-ip']);
|
|
997
1091
|
}
|
|
998
1092
|
break;
|
|
999
1093
|
}
|
|
@@ -1043,6 +1137,17 @@ class Esphome extends utils.Adapter {
|
|
|
1043
1137
|
try {
|
|
1044
1138
|
if (state && state.ack === false) {
|
|
1045
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
|
+
|
|
1046
1151
|
const deviceIP = this.deviceStateRelation[device[2]].ip;
|
|
1047
1152
|
|
|
1048
1153
|
// Handle Switch State
|
|
@@ -1126,18 +1231,18 @@ class Esphome extends utils.Adapter {
|
|
|
1126
1231
|
state: this.deviceInfo[deviceIP][device[4]].states.state,
|
|
1127
1232
|
transitionLength: this.deviceInfo[deviceIP][device[4]].states.transitionLength
|
|
1128
1233
|
};
|
|
1129
|
-
if (this.deviceInfo[deviceIP][device[4]].config.
|
|
1234
|
+
if (this.deviceInfo[deviceIP][device[4]].config.legacySupportsBrightness === true) {
|
|
1130
1235
|
data.brightness = this.deviceInfo[deviceIP][device[4]].states.brightness;
|
|
1131
1236
|
}
|
|
1132
|
-
if (this.deviceInfo[deviceIP][device[4]].config.
|
|
1237
|
+
if (this.deviceInfo[deviceIP][device[4]].config.legacySupportsRgb === true) {
|
|
1133
1238
|
data.red = this.deviceInfo[deviceIP][device[4]].states.red;
|
|
1134
1239
|
data.green = this.deviceInfo[deviceIP][device[4]].states.green;
|
|
1135
1240
|
data.blue = this.deviceInfo[deviceIP][device[4]].states.blue;
|
|
1136
1241
|
}
|
|
1137
|
-
if (this.deviceInfo[deviceIP][device[4]].config.
|
|
1242
|
+
if (this.deviceInfo[deviceIP][device[4]].config.legacySupportsWhiteValue === true) {
|
|
1138
1243
|
data.white = this.deviceInfo[deviceIP][device[4]].states.white;
|
|
1139
1244
|
}
|
|
1140
|
-
if (this.deviceInfo[deviceIP][device[4]].config.
|
|
1245
|
+
if (this.deviceInfo[deviceIP][device[4]].config.legacySupportsColorTemperature === true) {
|
|
1141
1246
|
data.colorTemperature = this.deviceInfo[deviceIP][device[4]].states.colorTemperature;
|
|
1142
1247
|
}
|
|
1143
1248
|
const effect = this.deviceInfo[deviceIP][device[4]].states.effect;
|
|
@@ -1198,6 +1303,76 @@ class Esphome extends utils.Adapter {
|
|
|
1198
1303
|
}
|
|
1199
1304
|
}
|
|
1200
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
|
+
|
|
1201
1376
|
}
|
|
1202
1377
|
|
|
1203
1378
|
if (require.main !== module) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.esphome",
|
|
3
|
-
"version": "0.
|
|
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",
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
"@alcalzone/release-script-plugin-iobroker": "^3.6.0",
|
|
29
29
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
30
30
|
"@alcalzone/release-script-plugin-manual-review": "^3.5.9",
|
|
31
|
+
"@iobroker/adapter-dev": "^1.2.0",
|
|
32
|
+
"@iobroker/dev-server": "^0.6.0",
|
|
31
33
|
"@iobroker/testing": "^4.1.0",
|
|
32
34
|
"@types/chai": "^4.3.6",
|
|
33
35
|
"@types/chai-as-promised": "^7.1.6",
|
|
@@ -52,6 +54,7 @@
|
|
|
52
54
|
"main": "main.js",
|
|
53
55
|
"scripts": {
|
|
54
56
|
"release": "release-script",
|
|
57
|
+
"dev-server": "dev-server",
|
|
55
58
|
"test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
|
|
56
59
|
"test:package": "mocha test/package --exit",
|
|
57
60
|
"test:unit": "mocha test/unit --exit",
|