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 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
  }
@@ -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.0",
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 ioBroker adapter instance
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).find(k => states[k] && states[k].val === true);
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 getAliveInstanceId(adapter, 'telegram');
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 alive telegram instance found.');
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 getAliveInstanceId(adapter, 'pushover');
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 alive pushover instance found.');
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 getAliveInstanceId(adapter, 'whatsapp-cmb');
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 alive whatsapp-cmb instance found.');
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 getAliveInstanceId(adapter, 'email');
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 alive email instance found.');
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 getAliveInstanceId(adapter, 'signal-cmb');
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 alive signal-cmb instance found.');
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 getAliveInstanceId(adapter, 'matrix-org');
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 alive matrix-org instance found.');
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 getAliveInstanceId(adapter, 'synochat');
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 alive synochat instance found.');
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
- `Cloud connection lost (${this.pollFailCount} failures). Last error: ${err?.message || err}`,
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, `Thermostat offline: ${gName} / ${thermostatName}`).catch(() => {});
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, `Thermostat online: ${gName} / ${thermostatName}`).catch(() => {});
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.0",
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.1.1",
32
- "@alcalzone/release-script-plugin-iobroker": "^5.1.2",
33
- "@alcalzone/release-script-plugin-license": "^5.1.1",
34
- "@alcalzone/release-script-plugin-manual-review": "^5.1.1",
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.2.0",
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.0",
41
+ "@types/node": "^25.6.2",
42
42
  "typescript": "~5.9.3"
43
43
  },
44
44
  "main": "main.js",