iobroker.beszel 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
7
7
  [![npm downloads](https://img.shields.io/npm/dt/iobroker.beszel)](https://www.npmjs.com/package/iobroker.beszel)
8
8
  ![Installations](https://iobroker.live/badges/beszel-installed.svg)
9
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-ff5e5b?logo=ko-fi)](https://ko-fi.com/krobipd)
9
10
  [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/krobipd)
10
11
 
11
12
  <img src="https://raw.githubusercontent.com/krobipd/ioBroker.beszel/main/admin/beszel.svg" width="100" />
@@ -121,6 +122,12 @@ beszel.0.
121
122
 
122
123
  ## Changelog
123
124
 
125
+ ### 0.2.1 (2026-03-28)
126
+ - Error deduplication, auth backoff, protect against empty system list deletion
127
+
128
+ ### 0.2.0 (2026-03-28)
129
+ - Adapter timer methods, synchronous onUnload, merge About tab, Windows/macOS CI, full MIT license
130
+
124
131
  ### 0.1.9 (2026-03-19)
125
132
  - Logging cleanup: stale system removal moved to debug level
126
133
 
@@ -136,9 +143,6 @@ beszel.0.
136
143
  ### 0.1.5 (2026-03-17)
137
144
  - Migrate to @alcalzone/release-script, enable npm Trusted Publishing
138
145
 
139
- ### 0.1.4 (2026-03-17)
140
- - Fix all repochecker issues; rename repo to ioBroker.beszel; add responsive grid sizes
141
-
142
146
  Older changelog: [CHANGELOG.md](CHANGELOG.md)
143
147
 
144
148
  ---
@@ -148,16 +152,39 @@ Older changelog: [CHANGELOG.md](CHANGELOG.md)
148
152
  - [ioBroker Forum](https://forum.iobroker.net/)
149
153
  - [GitHub Issues](https://github.com/krobipd/ioBroker.beszel/issues)
150
154
 
151
- If this adapter is useful to you, consider supporting its development via the PayPal badge at the top of this page.
155
+ ### Support Development
156
+
157
+ This adapter is free and open source. If you find it useful, consider buying me a coffee:
158
+
159
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-ff5e5b?style=for-the-badge&logo=ko-fi)](https://ko-fi.com/krobipd)
160
+ [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=for-the-badge)](https://paypal.me/krobipd)
152
161
 
153
162
  ---
154
163
 
155
164
  ## License
156
165
 
157
- MIT License - see [LICENSE](LICENSE)
166
+ MIT License
158
167
 
159
168
  Copyright (c) 2026 krobi <krobi@power-dreams.com>
160
169
 
170
+ Permission is hereby granted, free of charge, to any person obtaining a copy
171
+ of this software and associated documentation files (the "Software"), to deal
172
+ in the Software without restriction, including without limitation the rights
173
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
174
+ copies of the Software, and to permit persons to whom the Software is
175
+ furnished to do so, subject to the following conditions:
176
+
177
+ The above copyright notice and this permission notice shall be included in all
178
+ copies or substantial portions of the Software.
179
+
180
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
182
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
183
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
184
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
185
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
186
+ SOFTWARE.
187
+
161
188
  ---
162
189
 
163
190
  *Developed with assistance from Claude.ai*
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Verbindung",
3
3
  "tab_metrics": "Metriken",
4
-
5
4
  "label_url": "Beszel Hub URL",
6
5
  "help_url": "URL des Beszel Hubs (z.B. http://192.168.1.100:8090)",
7
6
  "label_username": "Benutzername",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Verbindung testen",
12
11
  "msg_connectionOk": "Verbindung erfolgreich",
13
12
  "msg_connectionFailed": "Verbindung fehlgeschlagen",
14
-
15
13
  "header_system": "System",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Arbeitsspeicher",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Container",
23
21
  "header_battery": "Akku",
24
-
25
22
  "metric_uptime": "Betriebszeit",
26
23
  "metric_agentVersion": "Agent-Version",
27
24
  "metric_services": "Systemd-Dienste (gesamt / fehlgeschlagen)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Einzelne Temperatursensoren",
40
37
  "metric_gpu": "GPU-Metriken (Auslastung, Speicher, Leistung)",
41
38
  "metric_containers": "Container-Überwachung (Docker / Podman)",
42
- "metric_battery": "Akkustatus"
39
+ "metric_battery": "Akkustatus",
40
+ "aboutInfo": "Dieser Adapter ist kostenlos und Open Source. Wenn er dir nützlich ist, unterstütze die Entwicklung gerne mit einer kleinen Spende.",
41
+ "donateKofi": "Unterstützen auf Ko-fi",
42
+ "donatePaypal": "Über PayPal spenden",
43
+ "supportHeader": "Unterstützung"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Connection",
3
3
  "tab_metrics": "Metrics",
4
-
5
4
  "label_url": "Beszel Hub URL",
6
5
  "help_url": "URL of your Beszel Hub (e.g. http://192.168.1.100:8090)",
7
6
  "label_username": "Username",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Test Connection",
12
11
  "msg_connectionOk": "Connection successful",
13
12
  "msg_connectionFailed": "Connection failed",
14
-
15
13
  "header_system": "System",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Memory",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Containers",
23
21
  "header_battery": "Battery",
24
-
25
22
  "metric_uptime": "Uptime",
26
23
  "metric_agentVersion": "Agent Version",
27
24
  "metric_services": "Systemd Services (total / failed)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Individual Temperature Sensors",
40
37
  "metric_gpu": "GPU Metrics (Usage, Memory, Power)",
41
38
  "metric_containers": "Container Monitoring (Docker / Podman)",
42
- "metric_battery": "Battery Status"
39
+ "metric_battery": "Battery Status",
40
+ "aboutInfo": "This adapter is free and open source. If you find it useful, please consider supporting its development with a small donation.",
41
+ "donateKofi": "Support on Ko-fi",
42
+ "donatePaypal": "Donate via PayPal",
43
+ "supportHeader": "Support"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Conexión",
3
3
  "tab_metrics": "Métricas",
4
-
5
4
  "label_url": "URL de Beszel Hub",
6
5
  "help_url": "URL de su Beszel Hub (p. ej. http://192.168.1.100:8090)",
7
6
  "label_username": "Nombre de usuario",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Probar conexión",
12
11
  "msg_connectionOk": "Conexión exitosa",
13
12
  "msg_connectionFailed": "Error de conexión",
14
-
15
13
  "header_system": "Sistema",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Memoria",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Contenedores",
23
21
  "header_battery": "Batería",
24
-
25
22
  "metric_uptime": "Tiempo de actividad",
26
23
  "metric_agentVersion": "Versión del agente",
27
24
  "metric_services": "Servicios Systemd (total / fallidos)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Sensores de temperatura individuales",
40
37
  "metric_gpu": "Métricas GPU (uso, memoria, potencia)",
41
38
  "metric_containers": "Monitorización de contenedores (Docker / Podman)",
42
- "metric_battery": "Estado de la batería"
39
+ "metric_battery": "Estado de la batería",
40
+ "aboutInfo": "Este adaptador es gratuito y de código abierto. Si te resulta útil, considera apoyar su desarrollo con una pequeña donación.",
41
+ "donateKofi": "Apoyar en Ko-fi",
42
+ "donatePaypal": "Donar vía PayPal",
43
+ "supportHeader": "Apoyo"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Connexion",
3
3
  "tab_metrics": "Métriques",
4
-
5
4
  "label_url": "URL du Beszel Hub",
6
5
  "help_url": "URL de votre Beszel Hub (ex. http://192.168.1.100:8090)",
7
6
  "label_username": "Nom d'utilisateur",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Tester la connexion",
12
11
  "msg_connectionOk": "Connexion réussie",
13
12
  "msg_connectionFailed": "Échec de la connexion",
14
-
15
13
  "header_system": "Système",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Mémoire",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Conteneurs",
23
21
  "header_battery": "Batterie",
24
-
25
22
  "metric_uptime": "Temps de fonctionnement",
26
23
  "metric_agentVersion": "Version de l'agent",
27
24
  "metric_services": "Services Systemd (total / échoués)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Capteurs de température individuels",
40
37
  "metric_gpu": "Métriques GPU (usage, mémoire, puissance)",
41
38
  "metric_containers": "Surveillance des conteneurs (Docker / Podman)",
42
- "metric_battery": "État de la batterie"
39
+ "metric_battery": "État de la batterie",
40
+ "aboutInfo": "Cet adaptateur est gratuit et open source. Si vous le trouvez utile, soutenez son développement par un petit don.",
41
+ "donateKofi": "Soutenir sur Ko-fi",
42
+ "donatePaypal": "Faire un don via PayPal",
43
+ "supportHeader": "Soutien"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Connessione",
3
3
  "tab_metrics": "Metriche",
4
-
5
4
  "label_url": "URL Beszel Hub",
6
5
  "help_url": "URL del tuo Beszel Hub (es. http://192.168.1.100:8090)",
7
6
  "label_username": "Nome utente",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Testa connessione",
12
11
  "msg_connectionOk": "Connessione riuscita",
13
12
  "msg_connectionFailed": "Connessione fallita",
14
-
15
13
  "header_system": "Sistema",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Memoria",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Contenitori",
23
21
  "header_battery": "Batteria",
24
-
25
22
  "metric_uptime": "Tempo di attività",
26
23
  "metric_agentVersion": "Versione agente",
27
24
  "metric_services": "Servizi Systemd (totale / falliti)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Sensori di temperatura individuali",
40
37
  "metric_gpu": "Metriche GPU (utilizzo, memoria, potenza)",
41
38
  "metric_containers": "Monitoraggio contenitori (Docker / Podman)",
42
- "metric_battery": "Stato batteria"
39
+ "metric_battery": "Stato batteria",
40
+ "aboutInfo": "Questo adapter è gratuito e open source. Se lo trovi utile, considera di supportare lo sviluppo con una piccola donazione.",
41
+ "donateKofi": "Supporta su Ko-fi",
42
+ "donatePaypal": "Dona tramite PayPal",
43
+ "supportHeader": "Supporto"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Verbinding",
3
3
  "tab_metrics": "Meetwaarden",
4
-
5
4
  "label_url": "Beszel Hub URL",
6
5
  "help_url": "URL van uw Beszel Hub (bijv. http://192.168.1.100:8090)",
7
6
  "label_username": "Gebruikersnaam",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Verbinding testen",
12
11
  "msg_connectionOk": "Verbinding geslaagd",
13
12
  "msg_connectionFailed": "Verbinding mislukt",
14
-
15
13
  "header_system": "Systeem",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Geheugen",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Containers",
23
21
  "header_battery": "Batterij",
24
-
25
22
  "metric_uptime": "Bedrijfstijd",
26
23
  "metric_agentVersion": "Agentversie",
27
24
  "metric_services": "Systemd-services (totaal / mislukt)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Afzonderlijke temperatuursensoren",
40
37
  "metric_gpu": "GPU-meetwaarden (gebruik, geheugen, vermogen)",
41
38
  "metric_containers": "Containermonitoring (Docker / Podman)",
42
- "metric_battery": "Batterijstatus"
39
+ "metric_battery": "Batterijstatus",
40
+ "aboutInfo": "Deze adapter is gratis en open source. Als je hem nuttig vindt, overweeg dan de ontwikkeling te steunen met een kleine donatie.",
41
+ "donateKofi": "Steunen op Ko-fi",
42
+ "donatePaypal": "Doneer via PayPal",
43
+ "supportHeader": "Ondersteuning"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Połączenie",
3
3
  "tab_metrics": "Metryki",
4
-
5
4
  "label_url": "URL Beszel Hub",
6
5
  "help_url": "URL Twojego Beszel Hub (np. http://192.168.1.100:8090)",
7
6
  "label_username": "Nazwa użytkownika",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Testuj połączenie",
12
11
  "msg_connectionOk": "Połączenie udane",
13
12
  "msg_connectionFailed": "Połączenie nieudane",
14
-
15
13
  "header_system": "System",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Pamięć",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Kontenery",
23
21
  "header_battery": "Bateria",
24
-
25
22
  "metric_uptime": "Czas działania",
26
23
  "metric_agentVersion": "Wersja agenta",
27
24
  "metric_services": "Usługi Systemd (łącznie / nieudane)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Poszczególne czujniki temperatury",
40
37
  "metric_gpu": "Metryki GPU (użycie, pamięć, moc)",
41
38
  "metric_containers": "Monitorowanie kontenerów (Docker / Podman)",
42
- "metric_battery": "Stan baterii"
39
+ "metric_battery": "Stan baterii",
40
+ "aboutInfo": "Ten adapter jest darmowy i otwartoźródłowy. Jeśli jest dla ciebie przydatny, rozważ wsparcie rozwoju małą darowizną.",
41
+ "donateKofi": "Wesprzyj na Ko-fi",
42
+ "donatePaypal": "Przekaż darowiznę przez PayPal",
43
+ "supportHeader": "Wsparcie"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Conexão",
3
3
  "tab_metrics": "Métricas",
4
-
5
4
  "label_url": "URL do Beszel Hub",
6
5
  "help_url": "URL do seu Beszel Hub (ex.: http://192.168.1.100:8090)",
7
6
  "label_username": "Nome de utilizador",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Testar ligação",
12
11
  "msg_connectionOk": "Ligação bem-sucedida",
13
12
  "msg_connectionFailed": "Falha na ligação",
14
-
15
13
  "header_system": "Sistema",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "Memória",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Contentores",
23
21
  "header_battery": "Bateria",
24
-
25
22
  "metric_uptime": "Tempo de atividade",
26
23
  "metric_agentVersion": "Versão do agente",
27
24
  "metric_services": "Serviços Systemd (total / falhados)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Sensores de temperatura individuais",
40
37
  "metric_gpu": "Métricas de GPU (uso, memória, potência)",
41
38
  "metric_containers": "Monitorização de contentores (Docker / Podman)",
42
- "metric_battery": "Estado da bateria"
39
+ "metric_battery": "Estado da bateria",
40
+ "aboutInfo": "Este adaptador é gratuito e de código aberto. Se o achar útil, considere apoiar o desenvolvimento com uma pequena doação.",
41
+ "donateKofi": "Apoiar no Ko-fi",
42
+ "donatePaypal": "Doar via PayPal",
43
+ "supportHeader": "Apoio"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Подключение",
3
3
  "tab_metrics": "Метрики",
4
-
5
4
  "label_url": "URL Beszel Hub",
6
5
  "help_url": "URL вашего Beszel Hub (например http://192.168.1.100:8090)",
7
6
  "label_username": "Имя пользователя",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Проверить подключение",
12
11
  "msg_connectionOk": "Подключение успешно",
13
12
  "msg_connectionFailed": "Ошибка подключения",
14
-
15
13
  "header_system": "Система",
16
14
  "header_cpu": "ЦПУ",
17
15
  "header_memory": "Память",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Контейнеры",
23
21
  "header_battery": "Аккумулятор",
24
-
25
22
  "metric_uptime": "Время работы",
26
23
  "metric_agentVersion": "Версия агента",
27
24
  "metric_services": "Службы Systemd (всего / сбоев)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Отдельные датчики температуры",
40
37
  "metric_gpu": "Метрики GPU (загрузка, память, мощность)",
41
38
  "metric_containers": "Мониторинг контейнеров (Docker / Podman)",
42
- "metric_battery": "Состояние аккумулятора"
39
+ "metric_battery": "Состояние аккумулятора",
40
+ "aboutInfo": "Этот адаптер бесплатный и с открытым исходным кодом. Если он вам полезен, поддержите разработку небольшим пожертвованием.",
41
+ "donateKofi": "Поддержать на Ko-fi",
42
+ "donatePaypal": "Пожертвовать через PayPal",
43
+ "supportHeader": "Поддержка"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "Підключення",
3
3
  "tab_metrics": "Метрики",
4
-
5
4
  "label_url": "URL Beszel Hub",
6
5
  "help_url": "URL вашого Beszel Hub (наприклад http://192.168.1.100:8090)",
7
6
  "label_username": "Ім'я користувача",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "Перевірити підключення",
12
11
  "msg_connectionOk": "Підключення успішне",
13
12
  "msg_connectionFailed": "Помилка підключення",
14
-
15
13
  "header_system": "Система",
16
14
  "header_cpu": "ЦПП",
17
15
  "header_memory": "Пам'ять",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "Контейнери",
23
21
  "header_battery": "Акумулятор",
24
-
25
22
  "metric_uptime": "Час роботи",
26
23
  "metric_agentVersion": "Версія агента",
27
24
  "metric_services": "Служби Systemd (всього / збоїв)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "Окремі датчики температури",
40
37
  "metric_gpu": "Метрики GPU (завантаження, пам'ять, потужність)",
41
38
  "metric_containers": "Моніторинг контейнерів (Docker / Podman)",
42
- "metric_battery": "Стан акумулятора"
39
+ "metric_battery": "Стан акумулятора",
40
+ "aboutInfo": "Цей адаптер безкоштовний і з відкритим кодом. Якщо він вам корисний, підтримайте розробку невеликою пожертвою.",
41
+ "donateKofi": "Підтримати на Ko-fi",
42
+ "donatePaypal": "Пожертвувати через PayPal",
43
+ "supportHeader": "Підтримка"
43
44
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "tab_connection": "连接",
3
3
  "tab_metrics": "指标",
4
-
5
4
  "label_url": "Beszel Hub URL",
6
5
  "help_url": "您的 Beszel Hub 的 URL(例如 http://192.168.1.100:8090)",
7
6
  "label_username": "用户名",
@@ -11,7 +10,6 @@
11
10
  "btn_checkConnection": "测试连接",
12
11
  "msg_connectionOk": "连接成功",
13
12
  "msg_connectionFailed": "连接失败",
14
-
15
13
  "header_system": "系统",
16
14
  "header_cpu": "CPU",
17
15
  "header_memory": "内存",
@@ -21,7 +19,6 @@
21
19
  "header_gpu": "GPU",
22
20
  "header_containers": "容器",
23
21
  "header_battery": "电池",
24
-
25
22
  "metric_uptime": "运行时间",
26
23
  "metric_agentVersion": "Agent 版本",
27
24
  "metric_services": "Systemd 服务(总计 / 失败)",
@@ -39,5 +36,9 @@
39
36
  "metric_temperatureDetails": "单独温度传感器",
40
37
  "metric_gpu": "GPU 指标(使用率、内存、功耗)",
41
38
  "metric_containers": "容器监控(Docker / Podman)",
42
- "metric_battery": "电池状态"
39
+ "metric_battery": "电池状态",
40
+ "aboutInfo": "此适配器免费且开源。如果您觉得有用,请考虑通过小额捐款支持开发。",
41
+ "donateKofi": "在Ko-fi上支持",
42
+ "donatePaypal": "通过PayPal捐赠",
43
+ "supportHeader": "支持"
43
44
  }
@@ -62,6 +62,51 @@
62
62
  "md": 4,
63
63
  "lg": 4,
64
64
  "xl": 4
65
+ },
66
+ "_supportHeader": {
67
+ "newLine": true,
68
+ "type": "header",
69
+ "text": "supportHeader",
70
+ "size": 5
71
+ },
72
+ "_aboutInfo": {
73
+ "type": "staticText",
74
+ "text": "aboutInfo",
75
+ "xs": 12,
76
+ "sm": 12,
77
+ "md": 12,
78
+ "lg": 12,
79
+ "xl": 12,
80
+ "style": {
81
+ "fontSize": 14,
82
+ "marginBottom": 16
83
+ }
84
+ },
85
+ "_kofiLink": {
86
+ "type": "staticLink",
87
+ "href": "https://ko-fi.com/krobipd",
88
+ "label": "donateKofi",
89
+ "button": true,
90
+ "variant": "outlined",
91
+ "color": "primary",
92
+ "xs": 12,
93
+ "sm": 6,
94
+ "md": 4,
95
+ "lg": 4,
96
+ "xl": 4
97
+ },
98
+ "_paypalLink": {
99
+ "type": "staticLink",
100
+ "href": "https://paypal.me/krobipd",
101
+ "label": "donatePaypal",
102
+ "button": true,
103
+ "variant": "outlined",
104
+ "color": "primary",
105
+ "xs": 12,
106
+ "sm": 6,
107
+ "md": 4,
108
+ "lg": 4,
109
+ "xl": 4
65
110
  }
66
111
  }
67
112
  },
package/build/main.js CHANGED
@@ -39,9 +39,11 @@ const state_manager_js_1 = require("./lib/state-manager.js");
39
39
  class BeszelAdapter extends utils.Adapter {
40
40
  client = null;
41
41
  stateManager = null;
42
- pollTimer = null;
42
+ pollTimer = undefined;
43
43
  isPolling = false;
44
44
  lastSystemCount = 0;
45
+ lastErrorCode = "";
46
+ authFailCount = 0;
45
47
  constructor(options = {}) {
46
48
  super({
47
49
  ...options,
@@ -99,18 +101,18 @@ class BeszelAdapter extends utils.Adapter {
99
101
  await this.poll();
100
102
  // Set up recurring poll
101
103
  const intervalMs = Math.max(10, config.pollInterval ?? 60) * 1000;
102
- this.pollTimer = setInterval(() => {
104
+ this.pollTimer = this.setInterval(() => {
103
105
  void this.poll();
104
106
  }, intervalMs);
105
107
  this.log.info(`Beszel adapter started — ${this.lastSystemCount} system(s), polling every ${config.pollInterval ?? 60}s`);
106
108
  }
107
- async onUnload(callback) {
109
+ onUnload(callback) {
108
110
  try {
109
111
  if (this.pollTimer) {
110
- clearInterval(this.pollTimer);
111
- this.pollTimer = null;
112
+ this.clearInterval(this.pollTimer);
113
+ this.pollTimer = undefined;
112
114
  }
113
- await this.setStateAsync("info.connection", { val: false, ack: true });
115
+ void this.setState("info.connection", { val: false, ack: true });
114
116
  }
115
117
  catch {
116
118
  // ignore
@@ -135,6 +137,31 @@ class BeszelAdapter extends utils.Adapter {
135
137
  this.sendTo(obj.from, obj.command, result, obj.callback);
136
138
  }
137
139
  }
140
+ /**
141
+ * Classify an error for deduplication and log-level decisions.
142
+ *
143
+ * @param err The error to classify
144
+ */
145
+ classifyError(err) {
146
+ if (!(err instanceof Error)) {
147
+ return "UNKNOWN";
148
+ }
149
+ const code = err.code;
150
+ if (code === "UNAUTHORIZED") {
151
+ return "UNAUTHORIZED";
152
+ }
153
+ if (code === "ENOTFOUND" ||
154
+ code === "ECONNREFUSED" ||
155
+ code === "ECONNRESET" ||
156
+ code === "ENETUNREACH" ||
157
+ code === "EAI_AGAIN") {
158
+ return "NETWORK";
159
+ }
160
+ if (code === "ETIMEDOUT" || err.message.includes("timed out")) {
161
+ return "TIMEOUT";
162
+ }
163
+ return code || "UNKNOWN";
164
+ }
138
165
  async poll() {
139
166
  if (this.isPolling) {
140
167
  this.log.debug("Skipping poll — previous poll still running");
@@ -162,18 +189,46 @@ class BeszelAdapter extends utils.Adapter {
162
189
  const stats = statsMap.get(system.id);
163
190
  await this.stateManager.updateSystem(system, stats, containers, config);
164
191
  }
165
- // Cleanup stale systems
166
- await this.stateManager.cleanupSystems(systems.map((s) => s.name));
192
+ // Cleanup stale systems — but only if we actually got results.
193
+ // An empty list during a transient API issue must NOT wipe all devices.
194
+ if (systems.length > 0 || this.lastSystemCount === 0) {
195
+ await this.stateManager.cleanupSystems(systems.map((s) => s.name));
196
+ }
167
197
  this.lastSystemCount = systems.length;
198
+ this.authFailCount = 0;
199
+ // Clear error state on success
200
+ if (this.lastErrorCode) {
201
+ this.log.info("Connection restored");
202
+ this.lastErrorCode = "";
203
+ }
168
204
  this.log.debug(`Polled ${systems.length} systems successfully`);
169
205
  }
170
206
  catch (err) {
171
207
  const errMsg = err instanceof Error ? err.message : String(err);
172
- this.log.error(`Poll failed: ${errMsg}`);
173
- // On 401, invalidate token so next poll re-authenticates
174
- if (err instanceof Error &&
175
- err.code === "UNAUTHORIZED") {
208
+ const errorCode = this.classifyError(err);
209
+ const isRepeat = errorCode === this.lastErrorCode;
210
+ this.lastErrorCode = errorCode;
211
+ if (errorCode === "UNAUTHORIZED") {
176
212
  this.client?.invalidateToken();
213
+ this.authFailCount++;
214
+ if (this.authFailCount <= 3) {
215
+ this.log.error("Authentication failed — check username and password");
216
+ }
217
+ else if (this.authFailCount === 4) {
218
+ this.log.error("Authentication keeps failing — suppressing further auth errors");
219
+ }
220
+ else {
221
+ this.log.debug(`Auth still failing (attempt ${this.authFailCount})`);
222
+ }
223
+ }
224
+ else if (isRepeat) {
225
+ this.log.debug(`Poll failed (ongoing): ${errMsg}`);
226
+ }
227
+ else if (errorCode === "NETWORK") {
228
+ this.log.warn("Cannot reach Beszel Hub — will keep retrying");
229
+ }
230
+ else {
231
+ this.log.error(`Poll failed: ${errMsg}`);
177
232
  }
178
233
  await this.setStateAsync("info.connection", { val: false, ack: true });
179
234
  }
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "beszel",
4
- "version": "0.1.9",
4
+ "version": "0.2.1",
5
5
  "news": {
6
+ "0.2.1": {
7
+ "en": "Error handling: dedup repeated errors, auth backoff, protect against empty system list deletion",
8
+ "de": "Fehlerbehandlung: Doppelte Fehler unterdrücken, Auth-Backoff, Schutz gegen Löschung bei leerer Systemliste",
9
+ "ru": "Обработка ошибок: дедупликация повторяющихся ошибок, откат аутентификации, защита от удаления при пустом списке систем",
10
+ "pt": "Tratamento de erros: deduplicação de erros repetidos, backoff de autenticação, proteção contra exclusão com lista vazia",
11
+ "nl": "Foutafhandeling: deduplicatie van herhaalde fouten, auth-backoff, bescherming tegen verwijdering bij lege systeemlijst",
12
+ "fr": "Gestion des erreurs: dédoublonnage des erreurs répétées, backoff d'authentification, protection contre la suppression avec liste vide",
13
+ "it": "Gestione errori: deduplicazione errori ripetuti, backoff autenticazione, protezione contro cancellazione con lista vuota",
14
+ "es": "Manejo de errores: deduplicación de errores repetidos, backoff de autenticación, protección contra eliminación con lista vacía",
15
+ "pl": "Obsługa błędów: deduplikacja powtarzających się błędów, backoff uwierzytelniania, ochrona przed usunięciem przy pustej liście",
16
+ "uk": "Обробка помилок: дедуплікація повторюваних помилок, відкат автентифікації, захист від видалення при порожньому списку",
17
+ "zh-cn": "错误处理:重复错误去重、认证退避、防止空系统列表删除"
18
+ },
19
+ "0.2.0": {
20
+ "en": "Use adapter timer methods, synchronous onUnload, merge About into Connection tab, add Windows/macOS CI, full MIT license in README",
21
+ "de": "Adapter-Timer-Methoden, synchrones onUnload, About-Tab in Verbindung integriert, Windows/macOS CI, vollständiger MIT-Lizenztext in README",
22
+ "ru": "Методы таймера адаптера, синхронный onUnload, вкладка О программе объединена с Подключение, CI для Windows/macOS, полный текст лицензии MIT в README",
23
+ "pt": "Métodos de timer do adaptador, onUnload síncrono, aba Sobre integrada em Conexão, CI Windows/macOS, texto completo da licença MIT no README",
24
+ "nl": "Adapter-timermethoden, synchrone onUnload, Over-tab samengevoegd met Verbinding, Windows/macOS CI, volledige MIT-licentietekst in README",
25
+ "fr": "Méthodes de timer adaptateur, onUnload synchrone, onglet À propos fusionné dans Connexion, CI Windows/macOS, texte complet de licence MIT dans README",
26
+ "it": "Metodi timer adattatore, onUnload sincrono, scheda Info integrata in Connessione, CI Windows/macOS, testo completo licenza MIT nel README",
27
+ "es": "Métodos de temporizador del adaptador, onUnload síncrono, pestaña Acerca de integrada en Conexión, CI Windows/macOS, texto completo de licencia MIT en README",
28
+ "pl": "Metody timera adaptera, synchroniczne onUnload, zakładka O nas zintegrowana z Połączenie, CI Windows/macOS, pełny tekst licencji MIT w README",
29
+ "uk": "Методи таймера адаптера, синхронний onUnload, вкладка Про програму об'єднана з Підключення, CI для Windows/macOS, повний текст ліцензії MIT в README",
30
+ "zh-cn": "使用适配器定时器方法,同步onUnload,将关于标签合并到连接标签,添加Windows/macOS CI,README中完整MIT许可证文本"
31
+ },
6
32
  "0.1.9": {
7
33
  "en": "Logging cleanup: stale system removal moved to debug level",
8
34
  "de": "Logging-Bereinigung: Entfernung veralteter Systeme auf Debug-Level verschoben",
@@ -29,19 +55,6 @@
29
55
  "uk": "Додано індикатор онлайн/офлайн до папок системних пристроїв",
30
56
  "zh-cn": "为系统设备文件夹添加在线/离线指示器"
31
57
  },
32
- "0.1.7": {
33
- "en": "Add system count to startup log message",
34
- "de": "Systemanzahl zur Startprotokollmeldung hinzugefügt",
35
- "ru": "Добавлено количество систем в сообщение журнала запуска",
36
- "pt": "Adicionar contagem de sistemas à mensagem de log de inicialização",
37
- "nl": "Systeemaantal toegevoegd aan opstartlogboekbericht",
38
- "fr": "Ajout du nombre de systèmes au message de journal de démarrage",
39
- "it": "Aggiunto conteggio sistemi al messaggio di log di avvio",
40
- "es": "Agregar recuento de sistemas al mensaje de registro de inicio",
41
- "pl": "Dodano liczbę systemów do komunikatu dziennika startowego",
42
- "uk": "Додано кількість систем до повідомлення журналу запуску",
43
- "zh-cn": "在启动日志消息中添加系统数量"
44
- },
45
58
  "0.1.6": {
46
59
  "en": "Code cleanup: remove unused type aliases, dead `_config` parameter, redundant setState call\nFix duplicate container filter (was filtered in main.ts and again in updateContainers)\nExtract load avg state creation into helper to eliminate code duplication",
47
60
  "de": "Code-Reinigung: entfernen Sie ungenutzte Typ-Aliase, tot `_config` Parameter, redundantes Set Mitgliedstaat\nBefestigen Sie doppelten Behälterfilter (in main.ts und wieder in updateContainers gefiltert)\nExtrahieren Sie die Last avg Zustand Kreation in Helfer, um Code-Dualplikation zu beseitigen",
@@ -80,32 +93,6 @@
80
93
  "pl": "Poprawiono wszystkie błędy repochecker; repozytorium zmieniono na ioBroker.beszel",
81
94
  "uk": "Виправлено всі помилки репочекера; репозиторій перейменовано на ioBroker.beszel",
82
95
  "zh-cn": "修复所有 repochecker 问题;仓库重命名为 ioBroker.beszel"
83
- },
84
- "0.1.3": {
85
- "en": "Fix all JSDoc warnings; update dependencies",
86
- "de": "Alle JSDoc-Warnungen behoben; Abhängigkeiten aktualisiert",
87
- "ru": "Исправлены все предупреждения JSDoc; обновлены зависимости",
88
- "pt": "Corrigidos todos os avisos JSDoc; dependências atualizadas",
89
- "nl": "Alle JSDoc-waarschuwingen opgelost; afhankelijkheden bijgewerkt",
90
- "fr": "Correction de tous les avertissements JSDoc; dépendances mises à jour",
91
- "it": "Corretti tutti gli avvisi JSDoc; dipendenze aggiornate",
92
- "es": "Corregidas todas las advertencias JSDoc; dependencias actualizadas",
93
- "pl": "Poprawiono wszystkie ostrzeżenia JSDoc; zaktualizowano zależności",
94
- "uk": "Виправлено всі попередження JSDoc; оновлено залежності",
95
- "zh-cn": "修复所有 JSDoc 警告;更新依赖项"
96
- },
97
- "0.1.2": {
98
- "en": "Fix: add missing cpu_steal state to CPU breakdown metric",
99
- "de": "Fix: fehlender cpu_steal Datenpunkt bei CPU Breakdown ergänzt",
100
- "ru": "Исправление: добавлено отсутствующее состояние cpu_steal в разбивке CPU",
101
- "pt": "Correção: adicionado estado cpu_steal ausente na métrica de detalhamento da CPU",
102
- "nl": "Fix: ontbrekende cpu_steal staat toegevoegd aan CPU breakdown metric",
103
- "fr": "Correction: état cpu_steal manquant ajouté à la métrique de détail CPU",
104
- "it": "Fix: aggiunto lo stato cpu_steal mancante nella metrica di dettaglio CPU",
105
- "es": "Corrección: agregado el estado cpu_steal faltante en la métrica de desglose CPU",
106
- "pl": "Poprawka: dodano brakujący stan cpu_steal w metryce szczegółów CPU",
107
- "uk": "Виправлення: додано відсутній стан cpu_steal у деталізації CPU",
108
- "zh-cn": "修复:在 CPU 详细指标中添加缺失的 cpu_steal 状态"
109
96
  }
110
97
  },
111
98
  "titleLang": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.beszel",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
4
4
  "description": "ioBroker adapter for Beszel server monitoring",
5
5
  "author": {
6
6
  "name": "krobi",