iobroker.schlueter-thermostat 0.7.0 → 0.7.2
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 +7 -13
- package/admin/i18n/de/translations.json +2 -1
- package/admin/i18n/en/translations.json +2 -1
- package/admin/i18n/es/translations.json +2 -1
- package/admin/i18n/fr/translations.json +2 -1
- package/admin/i18n/it/translations.json +2 -1
- package/admin/i18n/nl/translations.json +2 -1
- package/admin/i18n/pl/translations.json +2 -1
- package/admin/i18n/pt/translations.json +2 -1
- package/admin/i18n/ru/translations.json +2 -1
- package/admin/i18n/uk/translations.json +2 -1
- package/admin/i18n/zh-cn/translations.json +2 -1
- package/admin/jsonConfig.json +98 -0
- package/io-package.json +34 -27
- package/lib/notificationManager.js +48 -16
- package/main.js +4 -4
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -111,6 +111,13 @@ flowchart TB
|
|
|
111
111
|
Placeholder for the next version (at the beginning of the line):
|
|
112
112
|
### **WORK IN PROGRESS**
|
|
113
113
|
-->
|
|
114
|
+
### 0.7.2 (2026-05-23)
|
|
115
|
+
* (copilot) Add Icons for Notifications
|
|
116
|
+
|
|
117
|
+
### 0.7.1 (2026-05-21)
|
|
118
|
+
* (copilot) Modify notification manager to work with instances
|
|
119
|
+
* (copilot) Update Dependencies
|
|
120
|
+
|
|
114
121
|
### 0.7.0 (2026-05-14)
|
|
115
122
|
|
|
116
123
|
- (claude) Add Notification Manager
|
|
@@ -125,19 +132,6 @@ flowchart TB
|
|
|
125
132
|
- (patricknitsch) Add Icon and Online State on each Thermostat
|
|
126
133
|
- (patricknitsch) Update Readme and Doc
|
|
127
134
|
|
|
128
|
-
### 0.6.1 (2026-05-09)
|
|
129
|
-
|
|
130
|
-
- (patricknitsch) Add Measurement in DM Info
|
|
131
|
-
- (patricknitsch) Update Admin Dependency >= 7.6.23 for Device Manager
|
|
132
|
-
- First Important Note: From 0.5.3 to 0.6.X the Sensor Overview is removed but visible. Thats a Bug from js-controller and should be fixed with 7.1.3
|
|
133
|
-
- Second Important Note: If you come from 0.5.3 you'll need to re-enter your API key because of removed Encryption. Use from Doc.
|
|
134
|
-
|
|
135
|
-
### 0.6.0 (2026-05-08)
|
|
136
|
-
|
|
137
|
-
- (copilot) Integrate Adapter in ioBroker Device Manager
|
|
138
|
-
- (copilot) Remove Tab
|
|
139
|
-
- (patricknitsch) Removed Encryption and Protection from Api-Key because it's a global key --> fill in ApiKey again after Update
|
|
140
|
-
|
|
141
135
|
##
|
|
142
136
|
|
|
143
137
|
## License
|
|
@@ -31,5 +31,6 @@
|
|
|
31
31
|
"notifyPhoneSignalLabel": "Signal-Telefonnummer (optional)",
|
|
32
32
|
"notifyUseMatrixLabel": "Matrix verwenden",
|
|
33
33
|
"notifyUseSynoChatLabel": "Synology Chat verwenden",
|
|
34
|
-
"notifyChannelSynoChatLabel": "Synology-Chat-Kanal"
|
|
34
|
+
"notifyChannelSynoChatLabel": "Synology-Chat-Kanal",
|
|
35
|
+
"notifyInstanceLabel": "Instanz (automatisch wenn leer)"
|
|
35
36
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"notifyPhoneSignalLabel": "Signal phone number (optional)",
|
|
34
34
|
"notifyUseMatrixLabel": "Use Matrix",
|
|
35
35
|
"notifyUseSynoChatLabel": "Use Synology Chat",
|
|
36
|
-
"notifyChannelSynoChatLabel": "Synology Chat channel"
|
|
36
|
+
"notifyChannelSynoChatLabel": "Synology Chat channel",
|
|
37
|
+
"notifyInstanceLabel": "Instance (auto-detect if empty)"
|
|
37
38
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Número de teléfono Signal (opcional)",
|
|
33
33
|
"notifyUseMatrixLabel": "Usar Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Usar Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Canal de Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Canal de Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Instancia (automático si vacío)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Numéro de téléphone Signal (optionnel)",
|
|
33
33
|
"notifyUseMatrixLabel": "Utiliser Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Utiliser Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Canal Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Canal Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Instance (auto si vide)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Numero di telefono Signal (opzionale)",
|
|
33
33
|
"notifyUseMatrixLabel": "Usa Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Usa Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Canale Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Canale Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Istanza (automatica se vuota)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Signal-telefoonnummer (optioneel)",
|
|
33
33
|
"notifyUseMatrixLabel": "Matrix gebruiken",
|
|
34
34
|
"notifyUseSynoChatLabel": "Synology Chat gebruiken",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Synology Chat-kanaal"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Synology Chat-kanaal",
|
|
36
|
+
"notifyInstanceLabel": "Instantie (auto als leeg)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Numer telefonu Signal (opcjonalnie)",
|
|
33
33
|
"notifyUseMatrixLabel": "Użyj Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Użyj Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Kanał Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Kanał Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Instancja (auto jeśli pusta)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Número de telefone Signal (opcional)",
|
|
33
33
|
"notifyUseMatrixLabel": "Usar Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Usar Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Canal do Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Canal do Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Instância (automático se vazio)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Номер телефона Signal (необязательно)",
|
|
33
33
|
"notifyUseMatrixLabel": "Использовать Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Использовать Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Канал Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Канал Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Экземпляр (авто если пусто)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Номер телефону Signal (необов'язково)",
|
|
33
33
|
"notifyUseMatrixLabel": "Використовувати Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "Використовувати Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Канал Synology Chat"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Канал Synology Chat",
|
|
36
|
+
"notifyInstanceLabel": "Екземпляр (авто якщо порожньо)"
|
|
36
37
|
}
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"notifyPhoneSignalLabel": "Signal 电话号码(可选)",
|
|
33
33
|
"notifyUseMatrixLabel": "使用 Matrix",
|
|
34
34
|
"notifyUseSynoChatLabel": "使用 Synology Chat",
|
|
35
|
-
"notifyChannelSynoChatLabel": "Synology Chat 频道"
|
|
35
|
+
"notifyChannelSynoChatLabel": "Synology Chat 频道",
|
|
36
|
+
"notifyInstanceLabel": "实例(空则自动检测)"
|
|
36
37
|
}
|
package/admin/jsonConfig.json
CHANGED
|
@@ -242,6 +242,20 @@
|
|
|
242
242
|
"lg": 12,
|
|
243
243
|
"xl": 12
|
|
244
244
|
},
|
|
245
|
+
"notifyInstanceTelegram": {
|
|
246
|
+
"type": "instance",
|
|
247
|
+
"adapter": "telegram",
|
|
248
|
+
"label": "notifyInstanceLabel",
|
|
249
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseTelegram",
|
|
250
|
+
"allowDeactivate": true,
|
|
251
|
+
"onlyEnabled": true,
|
|
252
|
+
"newLine": false,
|
|
253
|
+
"xs": 12,
|
|
254
|
+
"sm": 12,
|
|
255
|
+
"md": 6,
|
|
256
|
+
"lg": 4,
|
|
257
|
+
"xl": 4
|
|
258
|
+
},
|
|
245
259
|
"notifyUserTelegram": {
|
|
246
260
|
"type": "text",
|
|
247
261
|
"label": "notifyUserTelegramLabel",
|
|
@@ -280,6 +294,20 @@
|
|
|
280
294
|
"lg": 12,
|
|
281
295
|
"xl": 12
|
|
282
296
|
},
|
|
297
|
+
"notifyInstancePushover": {
|
|
298
|
+
"type": "instance",
|
|
299
|
+
"adapter": "pushover",
|
|
300
|
+
"label": "notifyInstanceLabel",
|
|
301
|
+
"hidden": "!data.notifyEnabled || !data.notifyUsePushover",
|
|
302
|
+
"allowDeactivate": true,
|
|
303
|
+
"onlyEnabled": true,
|
|
304
|
+
"newLine": false,
|
|
305
|
+
"xs": 12,
|
|
306
|
+
"sm": 12,
|
|
307
|
+
"md": 6,
|
|
308
|
+
"lg": 4,
|
|
309
|
+
"xl": 4
|
|
310
|
+
},
|
|
283
311
|
"notifyTitlePushover": {
|
|
284
312
|
"type": "text",
|
|
285
313
|
"label": "notifyTitlePushoverLabel",
|
|
@@ -329,6 +357,20 @@
|
|
|
329
357
|
"lg": 12,
|
|
330
358
|
"xl": 12
|
|
331
359
|
},
|
|
360
|
+
"notifyInstanceWhatsapp": {
|
|
361
|
+
"type": "instance",
|
|
362
|
+
"adapter": "whatsapp-cmb",
|
|
363
|
+
"label": "notifyInstanceLabel",
|
|
364
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseWhatsapp",
|
|
365
|
+
"allowDeactivate": true,
|
|
366
|
+
"onlyEnabled": true,
|
|
367
|
+
"newLine": false,
|
|
368
|
+
"xs": 12,
|
|
369
|
+
"sm": 12,
|
|
370
|
+
"md": 6,
|
|
371
|
+
"lg": 4,
|
|
372
|
+
"xl": 4
|
|
373
|
+
},
|
|
332
374
|
"notifyPhoneWhatsapp": {
|
|
333
375
|
"type": "text",
|
|
334
376
|
"label": "notifyPhoneWhatsappLabel",
|
|
@@ -367,6 +409,20 @@
|
|
|
367
409
|
"lg": 12,
|
|
368
410
|
"xl": 12
|
|
369
411
|
},
|
|
412
|
+
"notifyInstanceEmail": {
|
|
413
|
+
"type": "instance",
|
|
414
|
+
"adapter": "email",
|
|
415
|
+
"label": "notifyInstanceLabel",
|
|
416
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseEmail",
|
|
417
|
+
"allowDeactivate": true,
|
|
418
|
+
"onlyEnabled": true,
|
|
419
|
+
"newLine": false,
|
|
420
|
+
"xs": 12,
|
|
421
|
+
"sm": 12,
|
|
422
|
+
"md": 6,
|
|
423
|
+
"lg": 4,
|
|
424
|
+
"xl": 4
|
|
425
|
+
},
|
|
370
426
|
"notifyEmailTo": {
|
|
371
427
|
"type": "text",
|
|
372
428
|
"label": "notifyEmailToLabel",
|
|
@@ -416,6 +472,20 @@
|
|
|
416
472
|
"lg": 12,
|
|
417
473
|
"xl": 12
|
|
418
474
|
},
|
|
475
|
+
"notifyInstanceSignal": {
|
|
476
|
+
"type": "instance",
|
|
477
|
+
"adapter": "signal-cmb",
|
|
478
|
+
"label": "notifyInstanceLabel",
|
|
479
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseSignal",
|
|
480
|
+
"allowDeactivate": true,
|
|
481
|
+
"onlyEnabled": true,
|
|
482
|
+
"newLine": false,
|
|
483
|
+
"xs": 12,
|
|
484
|
+
"sm": 12,
|
|
485
|
+
"md": 6,
|
|
486
|
+
"lg": 4,
|
|
487
|
+
"xl": 4
|
|
488
|
+
},
|
|
419
489
|
"notifyPhoneSignal": {
|
|
420
490
|
"type": "text",
|
|
421
491
|
"label": "notifyPhoneSignalLabel",
|
|
@@ -454,6 +524,20 @@
|
|
|
454
524
|
"lg": 12,
|
|
455
525
|
"xl": 12
|
|
456
526
|
},
|
|
527
|
+
"notifyInstanceMatrix": {
|
|
528
|
+
"type": "instance",
|
|
529
|
+
"adapter": "matrix-org",
|
|
530
|
+
"label": "notifyInstanceLabel",
|
|
531
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseMatrix",
|
|
532
|
+
"allowDeactivate": true,
|
|
533
|
+
"onlyEnabled": true,
|
|
534
|
+
"newLine": false,
|
|
535
|
+
"xs": 12,
|
|
536
|
+
"sm": 12,
|
|
537
|
+
"md": 6,
|
|
538
|
+
"lg": 4,
|
|
539
|
+
"xl": 4
|
|
540
|
+
},
|
|
457
541
|
"_notifySynoChatHeader": {
|
|
458
542
|
"type": "staticText",
|
|
459
543
|
"text": "─── Synology Chat ───",
|
|
@@ -481,6 +565,20 @@
|
|
|
481
565
|
"lg": 12,
|
|
482
566
|
"xl": 12
|
|
483
567
|
},
|
|
568
|
+
"notifyInstanceSynoChat": {
|
|
569
|
+
"type": "instance",
|
|
570
|
+
"adapter": "synochat",
|
|
571
|
+
"label": "notifyInstanceLabel",
|
|
572
|
+
"hidden": "!data.notifyEnabled || !data.notifyUseSynoChat",
|
|
573
|
+
"allowDeactivate": true,
|
|
574
|
+
"onlyEnabled": true,
|
|
575
|
+
"newLine": false,
|
|
576
|
+
"xs": 12,
|
|
577
|
+
"sm": 12,
|
|
578
|
+
"md": 6,
|
|
579
|
+
"lg": 4,
|
|
580
|
+
"xl": 4
|
|
581
|
+
},
|
|
484
582
|
"notifyChannelSynoChat": {
|
|
485
583
|
"type": "text",
|
|
486
584
|
"label": "notifyChannelSynoChatLabel",
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "schlueter-thermostat",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.2",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.7.2": {
|
|
7
|
+
"en": "Add Icons for Notifications",
|
|
8
|
+
"de": "Icons for Notifications hinzufügen",
|
|
9
|
+
"ru": "Добавить иконки для уведомлений",
|
|
10
|
+
"pt": "Adicionar Ícones para Notificações",
|
|
11
|
+
"nl": "Pictogrammen voor meldingen toevoegen",
|
|
12
|
+
"fr": "Ajouter des icônes pour les notifications",
|
|
13
|
+
"it": "Aggiungi icone per le notifiche",
|
|
14
|
+
"es": "Add Icons for Notifications",
|
|
15
|
+
"pl": "Dodaj ikony powiadomień",
|
|
16
|
+
"uk": "Додати іконки для повідомлень",
|
|
17
|
+
"zh-cn": "添加通知图标"
|
|
18
|
+
},
|
|
19
|
+
"0.7.1": {
|
|
20
|
+
"en": "Modify notification manager to work with instances\nUpdate Dependencies",
|
|
21
|
+
"de": "Benachrichtigungsmanager ändern, um mit Instanzen zu arbeiten\nAnpassungsabhängigkeiten",
|
|
22
|
+
"ru": "Изменить менеджер уведомлений для работы с экземплярами\nОбновление зависимостей",
|
|
23
|
+
"pt": "Modificar o gerenciador de notificações para trabalhar com instâncias\nAtualizar dependências",
|
|
24
|
+
"nl": "Notificatiebeheer aanpassen om met instanties te werken\nAfhankelijkheden bijwerken",
|
|
25
|
+
"fr": "Modifier le gestionnaire de notification pour travailler avec les instances\nMettre à jour les dépendances",
|
|
26
|
+
"it": "Modificare il gestore di notifiche per lavorare con le istanze\nDipendenze di aggiornamento",
|
|
27
|
+
"es": "Modificar el administrador de notificación para trabajar con casos\nDependencias de actualización",
|
|
28
|
+
"pl": "Zmień menedżera powiadomień do pracy z instancjami\nAktualizuj zależności",
|
|
29
|
+
"uk": "Зміна диспетчера повідомлень для роботи з екземплярами\nОновлення залежності",
|
|
30
|
+
"zh-cn": "修改通知管理器以配合实例\n更新依赖关系"
|
|
31
|
+
},
|
|
6
32
|
"0.7.0": {
|
|
7
33
|
"en": "Add Notification Manager",
|
|
8
34
|
"de": "Notification Manager hinzufügen",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Zintegruj adapter w menedżerze urządzeń joBroker\nUsuń kartę\nUsunięto szyfrowanie i ochronę z Api- Key, ponieważ jest to klucz globalny -- > wypełnić ApiKey ponownie po aktualizacji",
|
|
68
94
|
"uk": "Інтеграція адаптера в ioBroker Manager\nВидалити вкладку\nВилучено шифрування та захист від Api-Key, оскільки це глобальний ключ --> заповніть ApiKey знову після оновлення",
|
|
69
95
|
"zh-cn": "在 ioBroker 设备管理器中整合适配器\n删除标签\n从 Api- Key 中删除加密和保护, 因为它是一个全局密钥 -- > 在更新后再次填写 ApiKey"
|
|
70
|
-
},
|
|
71
|
-
"0.5.3": {
|
|
72
|
-
"en": "Adapter requires node.js >= 22 now\nUpdate Dependencies",
|
|
73
|
-
"de": "Adapter benötigt node.js >= 22 jetzt\nAnpassungsabhängigkeiten",
|
|
74
|
-
"ru": "Адаптер требует node.js >= 22 сейчас\nОбновление зависимостей",
|
|
75
|
-
"pt": "Adaptador requer nod.js >= 22 agora\nAtualizar dependências",
|
|
76
|
-
"nl": "Voor de adapter zijn node.js < 22 nu nodig\nAfhankelijkheden bijwerken",
|
|
77
|
-
"fr": "Adaptateur nécessite node.js >= 22 maintenant\nMettre à jour les dépendances",
|
|
78
|
-
"it": "Adattatore richiede node.js >= 22 ora\nDipendenze di aggiornamento",
|
|
79
|
-
"es": "Adaptador requiere node.js ю= 22 ahora\nDependencias de actualización",
|
|
80
|
-
"pl": "Adapter wymaga node.js > = 22\nAktualizuj zależności",
|
|
81
|
-
"uk": "Адаптер вимагає node.js >= 22 тепер\nОновлення залежності",
|
|
82
|
-
"zh-cn": "适配器需要节点.js 现在22\n更新依赖关系"
|
|
83
|
-
},
|
|
84
|
-
"0.5.2": {
|
|
85
|
-
"en": "Update Readme\nFix Issues from RepoChecker",
|
|
86
|
-
"de": "Update Reader\nProbleme von RepoChecker beheben",
|
|
87
|
-
"ru": "Обновление Readme\nОбсуждение RepoChecker",
|
|
88
|
-
"pt": "Actualizar a Leitura\nCorrigir os Problemas do RepoChecker",
|
|
89
|
-
"nl": "Readme bijwerken\nProblemen van repochecker oplossen",
|
|
90
|
-
"fr": "Mettre à jour Readme\nCorrection des problèmes de RepoChecker",
|
|
91
|
-
"it": "Aggiornamento\nRisolvi problemi da RepoChecker",
|
|
92
|
-
"es": "Actualización Readme\nProblemas de reparación de RepoChecker",
|
|
93
|
-
"pl": "Aktualizacja Readme\nNapraw problemy z RepoChecker",
|
|
94
|
-
"uk": "Оновлення Readme\nВиправлення питань від RepoChecker",
|
|
95
|
-
"zh-cn": "更新读取器\n从 Repo检查器修正问题"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
|
@@ -180,19 +180,26 @@
|
|
|
180
180
|
"notifyOnCloudOffline": true,
|
|
181
181
|
"notifyOnCloudRecovered": true,
|
|
182
182
|
"notifyUseTelegram": false,
|
|
183
|
+
"notifyInstanceTelegram": "",
|
|
183
184
|
"notifyUserTelegram": "",
|
|
184
185
|
"notifyUsePushover": false,
|
|
186
|
+
"notifyInstancePushover": "",
|
|
185
187
|
"notifyDevicePushover": "",
|
|
186
188
|
"notifyTitlePushover": "Schlüter Thermostat",
|
|
187
189
|
"notifyUseWhatsapp": false,
|
|
190
|
+
"notifyInstanceWhatsapp": "",
|
|
188
191
|
"notifyPhoneWhatsapp": "",
|
|
189
192
|
"notifyUseEmail": false,
|
|
193
|
+
"notifyInstanceEmail": "",
|
|
190
194
|
"notifyEmailTo": "",
|
|
191
195
|
"notifyEmailSubject": "Schlüter Thermostat",
|
|
192
196
|
"notifyUseSignal": false,
|
|
197
|
+
"notifyInstanceSignal": "",
|
|
193
198
|
"notifyPhoneSignal": "",
|
|
194
199
|
"notifyUseMatrix": false,
|
|
200
|
+
"notifyInstanceMatrix": "",
|
|
195
201
|
"notifyUseSynoChat": false,
|
|
202
|
+
"notifyInstanceSynoChat": "",
|
|
196
203
|
"notifyChannelSynoChat": ""
|
|
197
204
|
},
|
|
198
205
|
"protectedNative": [
|
|
@@ -4,20 +4,35 @@
|
|
|
4
4
|
// Notification Manager
|
|
5
5
|
// Dispatches messages to configured providers (Telegram, Pushover, WhatsApp,
|
|
6
6
|
// Email, Signal, Matrix, Synology Chat) via adapter.sendToAsync / setForeignStateAsync.
|
|
7
|
+
//
|
|
8
|
+
// Instance resolution:
|
|
9
|
+
// 1. If the user configured a specific instance via the admin UI, use it.
|
|
10
|
+
// 2. Otherwise fall back to auto-detecting the first alive instance.
|
|
7
11
|
// ============================================================================
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Returns the instance ID (e.g. "telegram.0") of the first alive instance of
|
|
11
15
|
* the given adapter name, or null if none found.
|
|
12
16
|
*
|
|
13
|
-
* @param {object} adapter
|
|
17
|
+
* @param {object} adapter
|
|
14
18
|
* @param {string} adapterName e.g. "telegram"
|
|
15
19
|
* @returns {Promise<string|null>} Instance ID when found; otherwise null.
|
|
16
20
|
*/
|
|
17
21
|
async function getAliveInstanceId(adapter, adapterName) {
|
|
18
22
|
try {
|
|
19
23
|
const states = await adapter.getForeignStatesAsync(`system.adapter.${adapterName}.*.alive`);
|
|
20
|
-
const aliveKey = Object.keys(states)
|
|
24
|
+
const aliveKey = Object.keys(states)
|
|
25
|
+
.filter(k => states[k] && states[k].val === true)
|
|
26
|
+
.sort((a, b) => {
|
|
27
|
+
const aMatch = a.match(/\.(\d+)\.alive$/);
|
|
28
|
+
const bMatch = b.match(/\.(\d+)\.alive$/);
|
|
29
|
+
const aNum = aMatch ? Number(aMatch[1]) : Number.MAX_SAFE_INTEGER;
|
|
30
|
+
const bNum = bMatch ? Number(bMatch[1]) : Number.MAX_SAFE_INTEGER;
|
|
31
|
+
if (aNum !== bNum) {
|
|
32
|
+
return aNum - bNum;
|
|
33
|
+
}
|
|
34
|
+
return a.localeCompare(b);
|
|
35
|
+
})[0];
|
|
21
36
|
if (!aliveKey) {
|
|
22
37
|
return null;
|
|
23
38
|
}
|
|
@@ -28,6 +43,23 @@ async function getAliveInstanceId(adapter, adapterName) {
|
|
|
28
43
|
}
|
|
29
44
|
}
|
|
30
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Resolves the instance ID to use for the given provider:
|
|
48
|
+
* - If `configuredId` is a non-empty string (set via instance selector), use it.
|
|
49
|
+
* - Otherwise auto-detect the first alive instance.
|
|
50
|
+
*
|
|
51
|
+
* @param {object} adapter
|
|
52
|
+
* @param {string} adapterName e.g. "telegram"
|
|
53
|
+
* @param {string} configuredId value from config (e.g. "telegram.0" or "")
|
|
54
|
+
* @returns {Promise<string|null>}
|
|
55
|
+
*/
|
|
56
|
+
async function resolveInstance(adapter, adapterName, configuredId) {
|
|
57
|
+
if (configuredId && typeof configuredId === 'string' && configuredId.trim() !== '') {
|
|
58
|
+
return configuredId.trim();
|
|
59
|
+
}
|
|
60
|
+
return getAliveInstanceId(adapter, adapterName);
|
|
61
|
+
}
|
|
62
|
+
|
|
31
63
|
/**
|
|
32
64
|
* Sends a text notification to all enabled providers.
|
|
33
65
|
*
|
|
@@ -44,7 +76,7 @@ async function sendNotification(adapter, text) {
|
|
|
44
76
|
// ── Telegram ──────────────────────────────────────────────────────────────
|
|
45
77
|
if (cfg.notifyUseTelegram) {
|
|
46
78
|
try {
|
|
47
|
-
const instanceId = await
|
|
79
|
+
const instanceId = await resolveInstance(adapter, 'telegram', cfg.notifyInstanceTelegram);
|
|
48
80
|
if (instanceId) {
|
|
49
81
|
const payload = { text };
|
|
50
82
|
if (cfg.notifyUserTelegram) {
|
|
@@ -53,7 +85,7 @@ async function sendNotification(adapter, text) {
|
|
|
53
85
|
await adapter.sendToAsync(instanceId, 'send', payload);
|
|
54
86
|
adapter.log.debug(`Notification sent via Telegram (${instanceId})`);
|
|
55
87
|
} else {
|
|
56
|
-
adapter.log.warn('sendNotification: no
|
|
88
|
+
adapter.log.warn('sendNotification: no telegram instance found/configured.');
|
|
57
89
|
}
|
|
58
90
|
} catch (e) {
|
|
59
91
|
adapter.log.warn(`sendNotification Telegram error: ${e?.message || e}`);
|
|
@@ -63,7 +95,7 @@ async function sendNotification(adapter, text) {
|
|
|
63
95
|
// ── Pushover ──────────────────────────────────────────────────────────────
|
|
64
96
|
if (cfg.notifyUsePushover) {
|
|
65
97
|
try {
|
|
66
|
-
const instanceId = await
|
|
98
|
+
const instanceId = await resolveInstance(adapter, 'pushover', cfg.notifyInstancePushover);
|
|
67
99
|
if (instanceId) {
|
|
68
100
|
const payload = {
|
|
69
101
|
message: text,
|
|
@@ -75,7 +107,7 @@ async function sendNotification(adapter, text) {
|
|
|
75
107
|
await adapter.sendToAsync(instanceId, 'send', payload);
|
|
76
108
|
adapter.log.debug(`Notification sent via Pushover (${instanceId})`);
|
|
77
109
|
} else {
|
|
78
|
-
adapter.log.warn('sendNotification: no
|
|
110
|
+
adapter.log.warn('sendNotification: no pushover instance found/configured.');
|
|
79
111
|
}
|
|
80
112
|
} catch (e) {
|
|
81
113
|
adapter.log.warn(`sendNotification Pushover error: ${e?.message || e}`);
|
|
@@ -85,7 +117,7 @@ async function sendNotification(adapter, text) {
|
|
|
85
117
|
// ── WhatsApp (whatsapp-cmb) ───────────────────────────────────────────────
|
|
86
118
|
if (cfg.notifyUseWhatsapp) {
|
|
87
119
|
try {
|
|
88
|
-
const instanceId = await
|
|
120
|
+
const instanceId = await resolveInstance(adapter, 'whatsapp-cmb', cfg.notifyInstanceWhatsapp);
|
|
89
121
|
if (instanceId) {
|
|
90
122
|
const payload = { text };
|
|
91
123
|
if (cfg.notifyPhoneWhatsapp) {
|
|
@@ -94,7 +126,7 @@ async function sendNotification(adapter, text) {
|
|
|
94
126
|
await adapter.sendToAsync(instanceId, 'send', payload);
|
|
95
127
|
adapter.log.debug(`Notification sent via WhatsApp (${instanceId})`);
|
|
96
128
|
} else {
|
|
97
|
-
adapter.log.warn('sendNotification: no
|
|
129
|
+
adapter.log.warn('sendNotification: no whatsapp-cmb instance found/configured.');
|
|
98
130
|
}
|
|
99
131
|
} catch (e) {
|
|
100
132
|
adapter.log.warn(`sendNotification WhatsApp error: ${e?.message || e}`);
|
|
@@ -104,7 +136,7 @@ async function sendNotification(adapter, text) {
|
|
|
104
136
|
// ── Email ─────────────────────────────────────────────────────────────────
|
|
105
137
|
if (cfg.notifyUseEmail) {
|
|
106
138
|
try {
|
|
107
|
-
const instanceId = await
|
|
139
|
+
const instanceId = await resolveInstance(adapter, 'email', cfg.notifyInstanceEmail);
|
|
108
140
|
if (instanceId) {
|
|
109
141
|
const payload = {
|
|
110
142
|
text,
|
|
@@ -116,7 +148,7 @@ async function sendNotification(adapter, text) {
|
|
|
116
148
|
await adapter.sendToAsync(instanceId, 'send', payload);
|
|
117
149
|
adapter.log.debug(`Notification sent via Email (${instanceId})`);
|
|
118
150
|
} else {
|
|
119
|
-
adapter.log.warn('sendNotification: no
|
|
151
|
+
adapter.log.warn('sendNotification: no email instance found/configured.');
|
|
120
152
|
}
|
|
121
153
|
} catch (e) {
|
|
122
154
|
adapter.log.warn(`sendNotification Email error: ${e?.message || e}`);
|
|
@@ -126,7 +158,7 @@ async function sendNotification(adapter, text) {
|
|
|
126
158
|
// ── Signal (signal-cmb) ───────────────────────────────────────────────────
|
|
127
159
|
if (cfg.notifyUseSignal) {
|
|
128
160
|
try {
|
|
129
|
-
const instanceId = await
|
|
161
|
+
const instanceId = await resolveInstance(adapter, 'signal-cmb', cfg.notifyInstanceSignal);
|
|
130
162
|
if (instanceId) {
|
|
131
163
|
const payload = { text };
|
|
132
164
|
if (cfg.notifyPhoneSignal) {
|
|
@@ -135,7 +167,7 @@ async function sendNotification(adapter, text) {
|
|
|
135
167
|
await adapter.sendToAsync(instanceId, 'send', payload);
|
|
136
168
|
adapter.log.debug(`Notification sent via Signal (${instanceId})`);
|
|
137
169
|
} else {
|
|
138
|
-
adapter.log.warn('sendNotification: no
|
|
170
|
+
adapter.log.warn('sendNotification: no signal-cmb instance found/configured.');
|
|
139
171
|
}
|
|
140
172
|
} catch (e) {
|
|
141
173
|
adapter.log.warn(`sendNotification Signal error: ${e?.message || e}`);
|
|
@@ -145,12 +177,12 @@ async function sendNotification(adapter, text) {
|
|
|
145
177
|
// ── Matrix (matrix-org) ───────────────────────────────────────────────────
|
|
146
178
|
if (cfg.notifyUseMatrix) {
|
|
147
179
|
try {
|
|
148
|
-
const instanceId = await
|
|
180
|
+
const instanceId = await resolveInstance(adapter, 'matrix-org', cfg.notifyInstanceMatrix);
|
|
149
181
|
if (instanceId) {
|
|
150
182
|
await adapter.sendToAsync(instanceId, 'send', { text });
|
|
151
183
|
adapter.log.debug(`Notification sent via Matrix (${instanceId})`);
|
|
152
184
|
} else {
|
|
153
|
-
adapter.log.warn('sendNotification: no
|
|
185
|
+
adapter.log.warn('sendNotification: no matrix-org instance found/configured.');
|
|
154
186
|
}
|
|
155
187
|
} catch (e) {
|
|
156
188
|
adapter.log.warn(`sendNotification Matrix error: ${e?.message || e}`);
|
|
@@ -160,7 +192,7 @@ async function sendNotification(adapter, text) {
|
|
|
160
192
|
// ── Synology Chat (synochat) ──────────────────────────────────────────────
|
|
161
193
|
if (cfg.notifyUseSynoChat) {
|
|
162
194
|
try {
|
|
163
|
-
const instanceId = await
|
|
195
|
+
const instanceId = await resolveInstance(adapter, 'synochat', cfg.notifyInstanceSynoChat);
|
|
164
196
|
if (instanceId) {
|
|
165
197
|
const channel = cfg.notifyChannelSynoChat;
|
|
166
198
|
if (channel) {
|
|
@@ -170,7 +202,7 @@ async function sendNotification(adapter, text) {
|
|
|
170
202
|
}
|
|
171
203
|
adapter.log.debug(`Notification sent via Synology Chat (${instanceId})`);
|
|
172
204
|
} else {
|
|
173
|
-
adapter.log.warn('sendNotification: no
|
|
205
|
+
adapter.log.warn('sendNotification: no synochat instance found/configured.');
|
|
174
206
|
}
|
|
175
207
|
} catch (e) {
|
|
176
208
|
adapter.log.warn(`sendNotification Synology Chat error: ${e?.message || e}`);
|
package/main.js
CHANGED
|
@@ -502,7 +502,7 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
502
502
|
this.pollFailCount = 0;
|
|
503
503
|
this.warnedNoCloud = false;
|
|
504
504
|
if (wasDisconnected && this.config.notifyOnCloudRecovered !== false) {
|
|
505
|
-
sendNotification(this, 'Cloud connection recovered.').catch(() => {});
|
|
505
|
+
sendNotification(this, '✅ Cloud connection recovered.').catch(() => {});
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
for (const group of groups) {
|
|
@@ -550,7 +550,7 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
550
550
|
if (this.config.notifyOnCloudOffline !== false) {
|
|
551
551
|
sendNotification(
|
|
552
552
|
this,
|
|
553
|
-
|
|
553
|
+
`⚠️ Cloud connection lost (${this.pollFailCount} failures). Last error: ${err?.message || err}`,
|
|
554
554
|
).catch(() => {});
|
|
555
555
|
}
|
|
556
556
|
} else {
|
|
@@ -622,13 +622,13 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
622
622
|
this.log.warn(`Thermostat OFFLINE: ${gName} / ${thermostatName} (ThermostatId=${thermostatId})`);
|
|
623
623
|
this.warnedOffline[thermostatId] = true;
|
|
624
624
|
if (this.config.notifyOnThermostatOffline !== false) {
|
|
625
|
-
sendNotification(this,
|
|
625
|
+
sendNotification(this, `⚠️ Thermostat offline: ${gName} / ${thermostatName}`).catch(() => {});
|
|
626
626
|
}
|
|
627
627
|
}
|
|
628
628
|
if (onlineNow === true && prevOnline === false) {
|
|
629
629
|
if (this.config.notifyOnThermostatOnline !== false) {
|
|
630
630
|
const gName = this.groupNameCache[groupId] || `Group ${groupId}`;
|
|
631
|
-
sendNotification(this,
|
|
631
|
+
sendNotification(this, `✅ Thermostat online: ${gName} / ${thermostatName}`).catch(() => {});
|
|
632
632
|
}
|
|
633
633
|
}
|
|
634
634
|
if (onlineNow === true) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.schlueter-thermostat",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Floor heating controlled with Ditra Heat Thermostat",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "patricknitsch",
|
|
@@ -28,17 +28,17 @@
|
|
|
28
28
|
"axios": "^1.16.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@alcalzone/release-script": "^5.
|
|
32
|
-
"@alcalzone/release-script-plugin-iobroker": "^5.
|
|
33
|
-
"@alcalzone/release-script-plugin-license": "^5.
|
|
34
|
-
"@alcalzone/release-script-plugin-manual-review": "^5.
|
|
31
|
+
"@alcalzone/release-script": "^5.2.0",
|
|
32
|
+
"@alcalzone/release-script-plugin-iobroker": "^5.2.0",
|
|
33
|
+
"@alcalzone/release-script-plugin-license": "^5.2.0",
|
|
34
|
+
"@alcalzone/release-script-plugin-manual-review": "^5.2.0",
|
|
35
35
|
"@iobroker/adapter-dev": "^1.5.0",
|
|
36
36
|
"@iobroker/dev-server": "^0.8.0",
|
|
37
|
-
"@iobroker/eslint-config": "^2.
|
|
37
|
+
"@iobroker/eslint-config": "^2.3.4",
|
|
38
38
|
"@iobroker/testing": "^5.2.2",
|
|
39
39
|
"@tsconfig/node20": "^20.1.8",
|
|
40
40
|
"@types/iobroker": "npm:@iobroker/types@^7.1.0",
|
|
41
|
-
"@types/node": "^25.6.
|
|
41
|
+
"@types/node": "^25.6.2",
|
|
42
42
|
"typescript": "~5.9.3"
|
|
43
43
|
},
|
|
44
44
|
"main": "main.js",
|