iobroker.device-watcher 2.15.14 → 2.15.17

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/lib/crud.js CHANGED
@@ -1,2082 +1,2057 @@
1
- const translations = require('./translations');
2
- const tools = require('./tools');
3
-
4
- /**
5
- * @param adaptr
6
- * @param {object} adptName - Adaptername of devices
7
- */
8
- async function createDPsForEachAdapter(adaptr, adptName) {
9
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}`, {
10
- type: 'channel',
11
- common: {
12
- name: adptName,
13
- },
14
- native: {},
15
- });
16
-
17
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.offlineCount`, {
18
- type: 'state',
19
- common: {
20
- name: {
21
- en: 'Number of devices offline',
22
- de: 'Anzahl der Geräte offline',
23
- ru: 'Количество устройств оффлайн',
24
- pt: 'Número de dispositivos offline',
25
- nl: 'Aantal offline apparaten',
26
- fr: 'Nombre de dispositifs hors ligne',
27
- it: 'Numero di dispositivi offline',
28
- es: 'Número de dispositivos sin conexión',
29
- pl: 'Liczba urządzeń offline',
30
- 'zh-cn': '离线设备数量',
31
- },
32
- type: 'number',
33
- role: 'value',
34
- read: true,
35
- write: false,
36
- },
37
- native: {},
38
- });
39
-
40
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.offlineList`, {
41
- type: 'state',
42
- common: {
43
- name: {
44
- en: 'List of offline devices',
45
- de: 'Liste der Offline-Geräte',
46
- ru: 'Список оффлайн устройств',
47
- pt: 'Lista de dispositivos offline',
48
- nl: 'Lijst van offline apparaten',
49
- fr: 'Liste des dispositifs hors ligne',
50
- it: 'Elenco dei dispositivi offline',
51
- es: 'Lista de dispositivos sin conexión',
52
- pl: 'Lista urządzeń offline',
53
- 'zh-cn': '离线设备列表',
54
- },
55
- type: 'array',
56
- role: 'json',
57
- read: true,
58
- write: false,
59
- },
60
- native: {},
61
- });
62
-
63
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceOffline`, {
64
- type: 'state',
65
- common: {
66
- name: {
67
- en: 'Is one device offline',
68
- de: 'Ist ein Gerät offline',
69
- ru: 'Есть ли одно устройство оффлайн',
70
- pt: ' um dispositivo offline',
71
- nl: 'Is er een apparaat offline',
72
- fr: 'Y a-t-il un appareil hors ligne',
73
- it: "C'è un dispositivo offline",
74
- es: '¿Hay un dispositivo sin conexión?',
75
- pl: 'Czy jedno urządzenie jest offline',
76
- uk: 'Чи є один пристрій офлайн',
77
- 'zh-cn': '是否有一台设备离线',
78
- },
79
- type: 'boolean',
80
- role: 'state',
81
- read: true,
82
- write: false,
83
- def: false,
84
- },
85
- native: {},
86
- });
87
-
88
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.listAllRawJSON`, {
89
- type: 'state',
90
- common: {
91
- name: {
92
- en: 'JSON RAW List of all devices',
93
- de: 'JSON RAW Liste aller Geräte',
94
- ru: 'JSON RAW Список всех устройств',
95
- pt: 'JSON RAW Lista de todos os dispositivos',
96
- nl: 'JSON RAW Lijst van alle apparaten',
97
- fr: 'JSON RAW Liste de tous les dispositifs',
98
- it: 'JSON RAW Elenco di tutti i dispositivi',
99
- es: 'JSON RAW Lista de todos los dispositivos',
100
- pl: 'JSON RAW Lista wszystkich urządzeń',
101
- uk: 'JSON RAW Список усіх пристроїв',
102
- 'zh-cn': 'JSON RAW 所有设备列表',
103
- },
104
- type: 'array',
105
- role: 'json',
106
- read: true,
107
- write: false,
108
- },
109
- native: {},
110
- });
111
-
112
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.listAll`, {
113
- type: 'state',
114
- common: {
115
- name: {
116
- en: 'List of all devices',
117
- de: 'Liste aller Geräte',
118
- ru: 'Список всех устройств',
119
- pt: 'Lista de todos os dispositivos',
120
- nl: 'Lijst van alle apparaten',
121
- fr: 'Liste de tous les dispositifs',
122
- it: 'Elenco di tutti i dispositivi',
123
- es: 'Lista de todos los dispositivos',
124
- pl: 'Lista wszystkich urządzeń',
125
- 'zh-cn': '所有设备的列表',
126
- },
127
- type: 'array',
128
- role: 'json',
129
- read: true,
130
- write: false,
131
- },
132
- native: {},
133
- });
134
-
135
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.linkQualityList`, {
136
- type: 'state',
137
- common: {
138
- name: {
139
- en: 'List of devices with signal strength',
140
- de: 'Liste der Geräte mit Signalstärke',
141
- ru: 'Список устройств с уровнем сигнала',
142
- pt: 'Lista de dispositivos com força de sinal',
143
- nl: 'Lijst van apparaten met signaalkracht',
144
- fr: 'Liste des dispositifs avec force de signal',
145
- it: 'Elenco dei dispositivi con forza del segnale',
146
- es: 'Lista de dispositivos con fuerza de señal',
147
- pl: 'Lista urządzeń z siłą sygnału',
148
- 'zh-cn': '具有信号强度的设备列表',
149
- },
150
- type: 'array',
151
- role: 'json',
152
- read: true,
153
- write: false,
154
- },
155
- native: {},
156
- });
157
-
158
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.countAll`, {
159
- type: 'state',
160
- common: {
161
- name: {
162
- en: 'Number of all devices',
163
- de: 'Anzahl aller Geräte',
164
- ru: 'Количество всех устройств',
165
- pt: 'Número de todos os dispositivos',
166
- nl: 'Aantal van alle apparaten',
167
- fr: 'Nombre de tous les appareils',
168
- it: 'Numero di tutti i dispositivi',
169
- es: 'Número de todos los dispositivos',
170
- pl: 'Liczba wszystkich urządzeń',
171
- 'zh-cn': '所有设备的数量',
172
- },
173
- type: 'number',
174
- role: 'value',
175
- read: true,
176
- write: false,
177
- },
178
- native: {},
179
- });
180
-
181
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.batteryList`, {
182
- type: 'state',
183
- common: {
184
- name: {
185
- en: 'List of devices with battery state',
186
- de: 'Liste der Geräte mit Batteriezustand',
187
- ru: 'Список устройств с состоянием батареи',
188
- pt: 'Lista de dispositivos com estado da bateria',
189
- nl: 'Lijst van apparaten met batterijstatus',
190
- fr: 'Liste des appareils avec état de batterie',
191
- it: 'Elenco dei dispositivi con stato della batteria',
192
- es: 'Lista de dispositivos con estado de batería',
193
- pl: 'Lista urządzeń ze stanem baterii',
194
- 'zh-cn': '具有电池状态的设备列表',
195
- },
196
- type: 'array',
197
- role: 'json',
198
- read: true,
199
- write: false,
200
- },
201
- native: {},
202
- });
203
-
204
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryList`, {
205
- type: 'state',
206
- common: {
207
- name: {
208
- en: 'List of devices with low battery state',
209
- de: 'Liste der Geräte mit niedrigem Batteriezustand',
210
- ru: 'Список устройств с низким уровнем заряда батареи',
211
- pt: 'Lista de dispositivos com baixo estado da bateria',
212
- nl: 'Lijst van apparaten met lage batterijstatus',
213
- fr: 'Liste des appareils à faible état de batterie',
214
- it: 'Elenco di dispositivi con stato di batteria basso',
215
- es: 'Lista de dispositivos con estado de batería bajo',
216
- pl: 'Lista urządzeń o niskim stanie baterii',
217
- 'zh-cn': '低电量设备列表',
218
- },
219
- type: 'array',
220
- role: 'json',
221
- read: true,
222
- write: false,
223
- },
224
- native: {},
225
- });
226
-
227
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryCount`, {
228
- type: 'state',
229
- common: {
230
- name: {
231
- en: 'Number of devices with low battery',
232
- de: 'Anzahl der Geräte mit niedriger Batterie',
233
- ru: 'Количество устройств с низким зарядом батареи',
234
- pt: 'Número de dispositivos com bateria baixa',
235
- nl: 'Aantal apparaten met lage batterij',
236
- fr: 'Nombre de dispositifs avec batterie faible',
237
- it: 'Numero di dispositivi con batteria scarica',
238
- es: 'Número de dispositivos con batería baja',
239
- pl: 'Liczba urządzeń z niskim poziomem baterii',
240
- 'zh-cn': '低电量设备的数量',
241
- },
242
- type: 'number',
243
- role: 'value',
244
- read: true,
245
- write: false,
246
- },
247
- native: {},
248
- });
249
-
250
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceLowBat`, {
251
- type: 'state',
252
- common: {
253
- name: {
254
- en: 'Is one device with low battery',
255
- de: 'Ist ein Gerät mit niedrigem Akku',
256
- ru: 'Есть ли устройство с низким зарядом батареи',
257
- pt: 'É um dispositivo com bateria baixa',
258
- nl: 'Is er een apparaat met lage batterij',
259
- fr: 'Y a-t-il un appareil avec batterie faible',
260
- it: "C'è un dispositivo con batteria scarica",
261
- es: '¿Hay un dispositivo con batería baja?',
262
- pl: 'Czy jest jedno urządzenie z niskim poziomem baterii',
263
- uk: 'Чи є пристрій з низьким зарядом батареї',
264
- 'zh-cn': '是否有设备电量低',
265
- },
266
- type: 'boolean',
267
- role: 'state',
268
- read: true,
269
- write: false,
270
- def: false,
271
- },
272
- native: {},
273
- });
274
-
275
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.batteryCount`, {
276
- type: 'state',
277
- common: {
278
- name: {
279
- en: 'Number of devices with battery',
280
- de: 'Anzahl der Geräte mit Batterie',
281
- ru: 'Количество устройств с батареей',
282
- pt: 'Número de dispositivos com bateria',
283
- nl: 'Aantal apparaten met batterij',
284
- fr: 'Nombre de dispositifs avec batterie',
285
- it: 'Numero di dispositivi con batteria',
286
- es: 'Número de dispositivos con batería',
287
- pl: 'Liczba urządzeń z baterią',
288
- 'zh-cn': '带电池的设备数量',
289
- },
290
- type: 'number',
291
- role: 'value',
292
- read: true,
293
- write: false,
294
- },
295
- native: {},
296
- });
297
-
298
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.upgradableCount`, {
299
- type: 'state',
300
- common: {
301
- name: {
302
- en: 'Number of devices with available updates',
303
- de: 'Anzahl der Geräte mit verfügbaren Updates',
304
- ru: 'Количество устройств с доступными обновлениями',
305
- pt: 'Número de dispositivos com atualizações disponíveis',
306
- nl: 'Aantal apparaten met beschikbare updates',
307
- fr: 'Nombre de dispositifs avec mises à jour disponibles',
308
- it: 'Numero di dispositivi con aggiornamenti disponibili',
309
- es: 'Número de dispositivos con actualizaciones disponibles',
310
- pl: 'Liczba urządzeń z dostępnymi aktualizacjami',
311
- uk: 'Кількість пристроїв з доступними оновленнями',
312
- 'zh-cn': '具有可用更新的设备数量',
313
- },
314
- type: 'number',
315
- role: 'value',
316
- read: true,
317
- write: false,
318
- },
319
- native: {},
320
- });
321
-
322
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.upgradableList`, {
323
- type: 'state',
324
- common: {
325
- name: {
326
- en: 'JSON List of devices with available updates',
327
- de: 'JSON Liste der Geräte mit verfügbaren Updates',
328
- ru: 'JSON список устройств с доступными обновлениями',
329
- pt: 'JSON Lista de dispositivos com atualizações disponíveis',
330
- nl: 'JSON Lijst van apparaten met beschikbare updates',
331
- fr: 'JSON Liste des appareils avec mises à jour disponibles',
332
- it: 'JSON Elenco dei dispositivi con aggiornamenti disponibili',
333
- es: 'JSON Lista de dispositivos con actualizaciones disponibles',
334
- pl: 'JSON Lista urządzeń z dostępnymi aktualizacjami',
335
- uk: 'JSON список пристроїв з доступними оновленнями',
336
- 'zh-cn': '具有可用更新的设备的 JSON 列表',
337
- },
338
- type: 'array',
339
- role: 'json',
340
- read: true,
341
- write: false,
342
- },
343
- native: {},
344
- });
345
-
346
- await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceUpdatable`, {
347
- type: 'state',
348
- common: {
349
- name: {
350
- en: 'Is one device updatable',
351
- de: 'Ist ein Gerät aktualisierbar',
352
- ru: 'Можно ли обновить одно устройство',
353
- pt: 'É um dispositivo atualizável',
354
- nl: 'Is er een apparaat dat kan worden bijgewerkt',
355
- fr: 'Y a-t-il un appareil qui peut être mis à jour',
356
- it: "C'è un dispositivo aggiornabile",
357
- es: '¿Hay un dispositivo actualizable?',
358
- pl: 'Czy jest jedno urządzenie do zaktualizowania',
359
- uk: 'Чи є пристрій, який можна оновити',
360
- 'zh-cn': '是否有设备可更新',
361
- },
362
- type: 'boolean',
363
- role: 'state',
364
- read: true,
365
- write: false,
366
- def: false,
367
- },
368
- native: {},
369
- });
370
- }
371
-
372
- /**
373
- * delete datapoints for each adapter
374
- *
375
- * @param adaptr
376
- * @param {object} adptName - Adaptername of devices
377
- */
378
- async function deleteDPsForEachAdapter(adaptr, adptName) {
379
- await adaptr.delObjectAsync(`devices.${adptName}`);
380
- await adaptr.delObjectAsync(`devices.${adptName}.offlineCount`);
381
- await adaptr.delObjectAsync(`devices.${adptName}.offlineList`);
382
- await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
383
- await adaptr.delObjectAsync(`devices.${adptName}.listAllRawJSON`);
384
- await adaptr.delObjectAsync(`devices.${adptName}.listAll`);
385
- await adaptr.delObjectAsync(`devices.${adptName}.linkQualityList`);
386
- await adaptr.delObjectAsync(`devices.${adptName}.countAll`);
387
- await adaptr.delObjectAsync(`devices.${adptName}.batteryList`);
388
- await adaptr.delObjectAsync(`devices.${adptName}.lowBatteryList`);
389
- await adaptr.delObjectAsync(`devices.${adptName}.lowBatteryCount`);
390
- await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceLowBat`);
391
- await adaptr.delObjectAsync(`devices.${adptName}.batteryCount`);
392
- await adaptr.delObjectAsync(`devices.${adptName}.upgradableCount`);
393
- await adaptr.delObjectAsync(`devices.${adptName}.upgradableList`);
394
- await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceUpdatable`);
395
- }
396
-
397
- /**
398
- * create HTML list datapoints
399
- *
400
- * @param adaptr
401
- * @param {object} [adptName] - Adaptername of devices
402
- */
403
- async function createHtmlListDatapoints(adaptr, adptName) {
404
- let dpSubFolder;
405
- //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
406
- if (adptName) {
407
- dpSubFolder = `${adptName}.`;
408
- } else {
409
- dpSubFolder = '';
410
- }
411
-
412
- await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}offlineListHTML`, {
413
- type: 'state',
414
- common: {
415
- name: {
416
- en: 'HTML List of offline devices',
417
- de: 'HTML Liste der Offline-Geräte',
418
- ru: 'HTML список оффлайн устройств',
419
- pt: 'HTML Lista de dispositivos offline',
420
- nl: 'HTML Lijst van offline apparaten',
421
- fr: 'HTML Liste des dispositifs hors ligne',
422
- it: 'HTML Elenco dei dispositivi offline',
423
- es: 'HTML Lista de dispositivos sin conexión',
424
- pl: 'HTML Lista urządzeń offline',
425
- 'zh-cn': 'HTML 离线设备列表',
426
- },
427
- type: 'string',
428
- role: 'html',
429
- read: true,
430
- write: false,
431
- },
432
- native: {},
433
- });
434
-
435
- await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
436
- type: 'state',
437
- common: {
438
- name: {
439
- en: 'HTML List of devices with signal strength',
440
- de: 'HTML Liste der Geräte mit Signalstärke',
441
- ru: 'HTML список устройств с уровнем сигнала',
442
- pt: 'HTML Lista de dispositivos com força de sinal',
443
- nl: 'HTML Lijst van apparaten met signaalkracht',
444
- fr: 'HTML Liste des dispositifs avec force de signal',
445
- it: 'HTML Elenco dei dispositivi con forza del segnale',
446
- es: 'HTML Lista de dispositivos con fuerza de señal',
447
- pl: 'HTML Lista urządzeń z siłą sygnału',
448
- 'zh-cn': 'HTML 具有信号强度的设备列表',
449
- },
450
- type: 'string',
451
- role: 'value',
452
- read: true,
453
- write: false,
454
- },
455
- native: {},
456
- });
457
-
458
- await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}batteryListHTML`, {
459
- type: 'state',
460
- common: {
461
- name: {
462
- en: 'HTML List of devices with battery state',
463
- de: 'HTML Liste der Geräte mit Batteriezustand',
464
- ru: 'HTML список устройств с состоянием батареи',
465
- pt: 'HTML Lista de dispositivos com estado da bateria',
466
- nl: 'HTML Lijst van apparaten met batterijstatus',
467
- fr: 'HTML Liste des appareils avec état de batterie',
468
- it: 'HTML Elenco dei dispositivi con stato della batteria',
469
- es: 'HTML Lista de dispositivos con estado de batería',
470
- pl: 'HTML Lista urządzeń ze stanem baterii',
471
- 'zh-cn': 'HTML 具有电池状态的设备列表',
472
- },
473
- type: 'string',
474
- role: 'html',
475
- read: true,
476
- write: false,
477
- },
478
- native: {},
479
- });
480
-
481
- await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
482
- type: 'state',
483
- common: {
484
- name: {
485
- en: 'HTML List of devices with low battery state',
486
- de: 'HTML Liste der Geräte mit niedrigem Batteriezustand',
487
- ru: 'HTML список устройств с низким уровнем заряда батареи',
488
- pt: 'HTML Lista de dispositivos com baixo estado da bateria',
489
- nl: 'HTML Lijst van apparaten met lage batterijstatus',
490
- fr: 'HTML Liste des appareils à faible état de batterie',
491
- it: 'HTML Elenco di dispositivi con stato di batteria basso',
492
- es: 'HTML Lista de dispositivos con estado de batería bajo',
493
- pl: 'HTML Lista urządzeń o niskim stanie baterii',
494
- 'zh-cn': 'HTML 低电量设备列表',
495
- },
496
- type: 'string',
497
- role: 'html',
498
- read: true,
499
- write: false,
500
- },
501
- native: {},
502
- });
503
- }
504
-
505
- /**
506
- * delete html datapoints
507
- *
508
- * @param adaptr
509
- * @param {object} [adptName] - Adaptername of devices
510
- */
511
- async function deleteHtmlListDatapoints(adaptr, adptName) {
512
- // delete the datapoints in subfolders with the adaptername otherwise delete the dP's in the root folder
513
- let dpSubFolder;
514
- if (adptName) {
515
- dpSubFolder = `${adptName}.`;
516
- } else {
517
- dpSubFolder = '';
518
- }
519
-
520
- await adaptr.delObjectAsync(`devices.${dpSubFolder}offlineListHTML`);
521
- await adaptr.delObjectAsync(`devices.${dpSubFolder}linkQualityListHTML`);
522
- await adaptr.delObjectAsync(`devices.${dpSubFolder}batteryListHTML`);
523
- await adaptr.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
524
- }
525
-
526
- /**
527
- * create HTML list datapoints for instances
528
- *
529
- * @param adaptr
530
- */
531
- async function createHtmlListDatapointsInstances(adaptr) {
532
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists`, {
533
- type: 'channel',
534
- common: {
535
- name: {
536
- en: 'HTML lists for adapter and instances',
537
- de: 'HTML-Listen für Adapter und Instanzen',
538
- ru: 'HTML списки для адаптера и экземпляров',
539
- pt: 'Listas HTML para adaptador e instâncias',
540
- nl: 'HTML lijsten voor adapter en instanties',
541
- fr: "Listes HTML pour l'adaptateur et les instances",
542
- it: 'Elenchi HTML per adattatore e istanze',
543
- es: 'Listas HTML para adaptador e instancias',
544
- pl: 'Listy HTML dla adaptera i instancji',
545
- uk: 'HTML списки для адаптера та екземплярів',
546
- 'zh-cn': '适配器和实例的 HTML 列表',
547
- },
548
- },
549
- native: {},
550
- });
551
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
552
- type: 'state',
553
- common: {
554
- name: {
555
- en: 'HTML List of all instances',
556
- de: 'HTML Liste aller Instanzen',
557
- ru: 'HTML список всех экземпляров',
558
- pt: 'HTML Lista de todas as instâncias',
559
- nl: 'HTML Lijst van alle instanties',
560
- fr: 'HTML Liste de toutes les instances',
561
- it: 'HTML Elenco di tutte le istanze',
562
- es: 'HTML Lista de todas las instancias',
563
- pl: 'HTML Lista wszystkich instancji',
564
- uk: 'HTML список усіх екземплярів',
565
- 'zh-cn': 'HTML 所有实例的列表',
566
- },
567
- type: 'string',
568
- role: 'html',
569
- read: true,
570
- write: false,
571
- },
572
- native: {},
573
- });
574
-
575
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
576
- type: 'state',
577
- common: {
578
- name: {
579
- en: 'HTML List of all active instances',
580
- de: 'HTML Liste aller aktiven Instanzen',
581
- ru: 'HTML список всех активных экземпляров',
582
- pt: 'HTML Lista de todas as instâncias ativas',
583
- nl: 'HTML Lijst van alle actieve instanties',
584
- fr: 'HTML Liste de toutes les instances actives',
585
- it: 'HTML Elenco di tutte le istanze attive',
586
- es: 'HTML Lista de todas las instancias activas',
587
- pl: 'HTML Lista wszystkich aktywnych instancji',
588
- uk: 'HTML список усіх активних екземплярів',
589
- 'zh-cn': 'HTML 所有活动实例的列表',
590
- },
591
- type: 'string',
592
- role: 'value',
593
- read: true,
594
- write: false,
595
- },
596
- native: {},
597
- });
598
-
599
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
600
- type: 'state',
601
- common: {
602
- name: {
603
- en: 'HTML List of all deactivated instances',
604
- de: 'HTML Liste aller deaktivierten Instanzen',
605
- ru: 'HTML список всех деактивированных экземпляров',
606
- pt: 'HTML Lista de todas as instâncias desativadas',
607
- nl: 'HTML Lijst van alle gedeactiveerde instanties',
608
- fr: 'HTML Liste de toutes les instances désactivées',
609
- it: 'HTML Elenco di tutte le istanze disattivate',
610
- es: 'HTML Lista de todas las instancias desactivadas',
611
- pl: 'HTML Lista wszystkich dezaktywowanych instancji',
612
- uk: 'HTML список усіх деактивованих екземплярів',
613
- 'zh-cn': 'HTML 所有已停用实例的列表',
614
- },
615
- type: 'string',
616
- role: 'html',
617
- read: true,
618
- write: false,
619
- },
620
- native: {},
621
- });
622
-
623
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
624
- type: 'state',
625
- common: {
626
- name: {
627
- en: 'HTML List of instances with error',
628
- de: 'HTML Liste der Instanzen mit Fehler',
629
- ru: 'HTML список экземпляров с ошибкой',
630
- pt: 'HTML Lista de instâncias com erro',
631
- nl: 'HTML Lijst van instanties met fouten',
632
- fr: 'HTML Liste des instances avec erreur',
633
- it: 'HTML Elenco delle istanze con errore',
634
- es: 'HTML Lista de instancias con error',
635
- pl: 'HTML Lista instancji z błędem',
636
- uk: 'HTML список екземплярів з помилкою',
637
- 'zh-cn': 'HTML 含错误实例的列表',
638
- },
639
- type: 'string',
640
- role: 'html',
641
- read: true,
642
- write: false,
643
- },
644
- native: {},
645
- });
646
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
647
- type: 'state',
648
- common: {
649
- name: {
650
- en: 'HTML list of adapters with available updates',
651
- de: 'HTML-Liste der Adapter mit verfügbaren Updates',
652
- ru: 'HTML список адаптеров с доступными обновлениями',
653
- pt: 'Lista HTML de adaptadores com atualizações disponíveis',
654
- nl: 'HTML lijst van adapters met beschikbare updates',
655
- fr: 'Liste HTML des adaptateurs avec mises à jour disponibles',
656
- it: 'Elenco HTML degli adattatori con aggiornamenti disponibili',
657
- es: 'Lista HTML de adaptadores con actualizaciones disponibles',
658
- pl: 'Lista adapterów HTML z dostępnymi aktualizacjami',
659
- uk: 'HTML список адаптерів з доступними оновленнями',
660
- 'zh-cn': 'HTML 具有可用更新的适配器列表',
661
- },
662
- type: 'string',
663
- role: 'html',
664
- read: true,
665
- write: false,
666
- },
667
- native: {},
668
- });
669
- }
670
-
671
- /**
672
- * delete html datapoints for instances
673
- *
674
- * @param adaptr
675
- */
676
- async function deleteHtmlListDatapointsInstances(adaptr) {
677
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`);
678
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`);
679
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`);
680
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`);
681
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`);
682
- await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists`);
683
- }
684
-
685
- /*=============================================
686
- = functions to create html lists =
687
- =============================================*/
688
- /**
689
- * @param adaptr
690
- * @param {string} type - type of list
691
- * @param {object} devices - Device
692
- * @param {number} deviceCount - Counted devices
693
- * @param {object} isLowBatteryList - list Low Battery Devices
694
- */
695
- async function createListHTML(adaptr, type, devices, deviceCount, isLowBatteryList) {
696
- let html;
697
- switch (type) {
698
- case 'linkQualityList':
699
- devices = devices.sort((a, b) => {
700
- a = a.Device || '';
701
- b = b.Device || '';
702
- return a.localeCompare(b);
703
- });
704
- html = `<center>
705
- <b>${[translations.Link_quality_devices[adaptr.config.userSelectedLanguage]]}:<font> ${deviceCount}</b><small></small></font>
706
- <p></p>
707
- </center>
708
- <table width=100%>
709
- <tr>
710
- <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
711
- <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
712
- <th align=right>${[translations.Signal_strength[adaptr.config.userSelectedLanguage]]}</th>
713
- </tr>
714
- <tr>
715
- <td colspan="5"><hr></td>
716
- </tr>`;
717
-
718
- for (const device of devices) {
719
- html += `<tr>
720
- <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
721
- <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
722
- <td align=right><font>${device[translations.Signal_strength[adaptr.config.userSelectedLanguage]]}</font></td>
723
- </tr>`;
724
- }
725
-
726
- html += '</table>';
727
- break;
728
-
729
- case 'offlineList':
730
- devices = devices.sort((a, b) => {
731
- a = a.Device || '';
732
- b = b.Device || '';
733
- return a.localeCompare(b);
734
- });
735
- html = `<center>
736
- <b>${[translations.offline_devices[adaptr.config.userSelectedLanguage]]}: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
737
- <p></p>
738
- </center>
739
- <table width=100%>
740
- <tr>
741
- <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
742
- <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
743
- <th align=center>${[translations.Last_Contact[adaptr.config.userSelectedLanguage]]}</th>
744
- </tr>
745
- <tr>
746
- <td colspan="5"><hr></td>
747
- </tr>`;
748
-
749
- for (const device of devices) {
750
- html += `<tr>
751
- <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
752
- <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
753
- <td align=center><font color=orange>${device[translations.Last_Contact[adaptr.config.userSelectedLanguage]]}</font></td>
754
- </tr>`;
755
- }
756
-
757
- html += '</table>';
758
- break;
759
-
760
- case 'batteryList':
761
- devices = devices.sort((a, b) => {
762
- a = a.Device || '';
763
- b = b.Device || '';
764
- return a.localeCompare(b);
765
- });
766
- html = `<center>
767
- <b>${isLowBatteryList === true ? `${[translations.low[adaptr.config.userSelectedLanguage]]} ` : ''}${[translations.battery_devices[adaptr.config.userSelectedLanguage]]}:
768
- <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
769
- <p></p>
770
- </center>
771
- <table width=100%>
772
- <tr>
773
- <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
774
- <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
775
- <th align=${isLowBatteryList ? 'center' : 'right'}>${[translations.Battery[adaptr.config.userSelectedLanguage]]}</th>
776
- </tr>
777
- <tr>
778
- <td colspan="5"><hr></td>
779
- </tr>`;
780
- for (const device of devices) {
781
- html += `<tr>
782
- <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
783
- <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>`;
784
-
785
- if (isLowBatteryList) {
786
- html += `<td align=center><font color=orange>${device[translations.Battery[adaptr.config.userSelectedLanguage]]}</font></td>`;
787
- } else {
788
- html += `<td align=right><font color=#3bcf0e>${device[translations.Battery[adaptr.config.userSelectedLanguage]]}</font></td>`;
789
- }
790
- html += `</tr>`;
791
- }
792
-
793
- html += '</table>';
794
- break;
795
- }
796
- return html;
797
- }
798
-
799
- /**
800
- * @param adaptr
801
- * @param {string} type - type of list
802
- * @param {object} instances - Instance
803
- * @param {number} instancesCount - Counted devices
804
- */
805
- async function createListHTMLInstances(adaptr, type, instances, instancesCount) {
806
- let html;
807
- switch (type) {
808
- case 'allInstancesList':
809
- instances = instances.sort((a, b) => {
810
- a = a.Instance || '';
811
- b = b.Instance || '';
812
- return a.localeCompare(b);
813
- });
814
- html = `<center>
815
- <b>${[translations.All_Instances[adaptr.config.userSelectedLanguage]]}:<font> ${instancesCount}</b><small></small></font>
816
- <p></p>
817
- </center>
818
- <table width=100%>
819
- <tr>
820
- <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
821
- <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
822
- <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
823
- </tr>
824
- <tr>
825
- <td colspan="5"><hr></td>
826
- </tr>`;
827
-
828
- for (const instanceData of instances) {
829
- html += `<tr>
830
- <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
831
- <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
832
- <td align=center><font>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
833
- </tr>`;
834
- }
835
-
836
- html += '</table>';
837
- break;
838
-
839
- case 'allActiveInstancesList':
840
- instances = instances.sort((a, b) => {
841
- a = a.Instance || '';
842
- b = b.Instances || '';
843
- return a.localeCompare(b);
844
- });
845
- html = `<center>
846
- <b>${[translations.Active_Instances[adaptr.config.userSelectedLanguage]]}: <font> ${instancesCount}</b><small></small></font>
847
- <p></p>
848
- </center>
849
- <table width=100%>
850
- <tr>
851
- <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
852
- <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
853
- <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
854
- </tr>
855
- <tr>
856
- <td colspan="5"><hr></td>
857
- </tr>`;
858
-
859
- for (const instanceData of instances) {
860
- html += `<tr>
861
- <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
862
- <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
863
- <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
864
- </tr>`;
865
- }
866
-
867
- html += '</table>';
868
- break;
869
-
870
- case 'errorInstanceList':
871
- instances = instances.sort((a, b) => {
872
- a = a.Instance || '';
873
- b = b.Instances || '';
874
- return a.localeCompare(b);
875
- });
876
- html = `<center>
877
- <b>${[translations.Error_Instances[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
878
- <p></p>
879
- </center>
880
- <table width=100%>
881
- <tr>
882
- <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
883
- <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
884
- <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
885
- </tr>
886
- <tr>
887
- <td colspan="5"><hr></td>
888
- </tr>`;
889
-
890
- for (const instanceData of instances) {
891
- html += `<tr>
892
- <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
893
- <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
894
- <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
895
- </tr>`;
896
- }
897
-
898
- html += '</table>';
899
- break;
900
-
901
- case 'deactivatedInstanceList':
902
- instances = instances.sort((a, b) => {
903
- a = a.Instance || '';
904
- b = b.Instances || '';
905
- return a.localeCompare(b);
906
- });
907
- html = `<center>
908
- <b>${[translations.Deactivated_Instances[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
909
- <p></p>
910
- </center>
911
- <table width=100%>
912
- <tr>
913
- <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
914
- <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
915
- <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
916
- </tr>
917
- <tr>
918
- <td colspan="5"><hr></td>
919
- </tr>`;
920
-
921
- for (const instanceData of instances) {
922
- if (!instanceData.isAlive) {
923
- html += `<tr>
924
- <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
925
- <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
926
- <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
927
- </tr>`;
928
- }
929
- }
930
-
931
- html += '</table>';
932
- break;
933
-
934
- case 'updateAdapterList':
935
- html = `<center>
936
- <b>${[translations.Updatable_adapters[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
937
- <p></p>
938
- </center>
939
- <table width=100%>
940
- <tr>
941
- <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
942
- <th align=center>${[translations.Installed_Version[adaptr.config.userSelectedLanguage]]}</th>
943
- <th align=center>${[translations.Available_Version[adaptr.config.userSelectedLanguage]]}</th>
944
- </tr>
945
- <tr>
946
- <td colspan="5"><hr></td>
947
- </tr>`;
948
-
949
- for (const instanceData of instances.values()) {
950
- if (instanceData.updateAvailable !== ' - ') {
951
- html += `<tr>
952
- <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
953
- <td align=center><font>${instanceData[translations.Installed_Version[adaptr.config.userSelectedLanguage]]}</font></td>
954
- <td align=center><font color=orange>${instanceData[translations.Available_Version[adaptr.config.userSelectedLanguage]]}</font></td>
955
- </tr>`;
956
- }
957
- }
958
-
959
- html += '</table>';
960
- break;
961
- }
962
- return html;
963
- }
964
-
965
- /**
966
- * create blacklist
967
- *
968
- * @param adaptr
969
- */
970
- async function createBlacklist(adaptr) {
971
- adaptr.log.debug(`Start the function createBlacklist`);
972
-
973
- // DEVICES
974
- const myBlacklist = adaptr.config.tableBlacklist;
975
- if (myBlacklist.length >= 1) {
976
- for (const i in myBlacklist) {
977
- try {
978
- const blacklistParse = tools.parseData(myBlacklist[i].devices);
979
- // push devices in list to ignor device in lists
980
- if (myBlacklist[i].checkIgnorLists) {
981
- adaptr.blacklistLists.push(blacklistParse.path);
982
- }
983
- if (myBlacklist[i].checkIgnorAdapterLists) {
984
- adaptr.blacklistAdapterLists.push(blacklistParse.path);
985
- }
986
- // push devices in list to ignor device in notifications
987
- if (myBlacklist[i].checkIgnorNotify) {
988
- adaptr.blacklistNotify.push(blacklistParse.path);
989
- }
990
- } catch (error) {
991
- adaptr.log.error(`[createBlacklist] - ${error}`);
992
- }
993
- if (adaptr.blacklistLists.length >= 1) {
994
- adaptr.log.info(`Found devices/services on blacklist for lists: ${adaptr.blacklistLists}`);
995
- }
996
- if (adaptr.blacklistAdapterLists.length >= 1) {
997
- adaptr.log.info(`Found devices/services on blacklist for own adapter lists: ${adaptr.blacklistAdapterLists}`);
998
- }
999
- if (adaptr.blacklistNotify.length >= 1) {
1000
- adaptr.log.info(`Found devices/services on blacklist for notifications: ${adaptr.blacklistNotify}`);
1001
- }
1002
- }
1003
- }
1004
-
1005
- // INSTANCES
1006
- const myBlacklistInstances = adaptr.config.tableBlacklistInstances;
1007
- if (myBlacklistInstances.length >= 1) {
1008
- for (const i in myBlacklistInstances) {
1009
- try {
1010
- const blacklistParse = tools.parseData(myBlacklistInstances[i].instances);
1011
- // push devices in list to ignor device in lists
1012
- if (myBlacklistInstances[i].checkIgnorLists) {
1013
- adaptr.blacklistInstancesLists.push(blacklistParse.instanceID);
1014
- }
1015
- // push devices in list to ignor device in notifications
1016
- if (myBlacklistInstances[i].checkIgnorNotify) {
1017
- adaptr.blacklistInstancesNotify.push(blacklistParse.instanceID);
1018
- }
1019
- } catch (error) {
1020
- adaptr.log.error(`[createBlacklist] - ${error}`);
1021
- }
1022
- }
1023
- if (adaptr.blacklistInstancesLists.length >= 1) {
1024
- adaptr.log.info(`Found instances items on blacklist for lists: ${adaptr.blacklistInstancesLists}`);
1025
- }
1026
- if (adaptr.blacklistInstancesNotify.length >= 1) {
1027
- adaptr.log.info(`Found instances items on blacklist for notifications: ${adaptr.blacklistInstancesNotify}`);
1028
- }
1029
- }
1030
- }
1031
-
1032
- /**
1033
- * create list with time for instances
1034
- *
1035
- * @param adaptr
1036
- */
1037
- async function createTimeListInstances(adaptr) {
1038
- // INSTANCES
1039
- const userTimeListInstances = adaptr.config.tableTimeInstance;
1040
-
1041
- if (userTimeListInstances.length >= 1) {
1042
- for (const i in userTimeListInstances) {
1043
- try {
1044
- const userTimeListparse = tools.parseData(userTimeListInstances[i].instancesTime);
1045
- // push devices in list to ignor device in lists
1046
- adaptr.userTimeInstancesList.set(userTimeListparse.instanceName, {
1047
- deactivationTime: userTimeListInstances[i].deactivationTime,
1048
- errorTime: userTimeListInstances[i].errorTime,
1049
- });
1050
- } catch (error) {
1051
- adaptr.log.error(`[createTimeListInstances] - ${error}`);
1052
- }
1053
- }
1054
- if (adaptr.userTimeInstancesList.size >= 1) {
1055
- adaptr.log.info(`Found instances items on lists for timesettings: ${Array.from(adaptr.userTimeInstancesList.keys())}`);
1056
- }
1057
- }
1058
- }
1059
-
1060
- /**
1061
- * @param adaptr
1062
- * @param {object} i - Device Object
1063
- */
1064
- async function createData(adaptr, i) {
1065
- try {
1066
- const devices = await adaptr.getForeignStatesAsync(adaptr.selAdapter[i].selektor);
1067
- const adapterID = adaptr.selAdapter[i].adapterID;
1068
-
1069
- /*---------- Start of loop ----------*/
1070
- for (const [id] of Object.entries(devices)) {
1071
- if (id.endsWith('.')) {
1072
- continue;
1073
- }
1074
-
1075
- // matter: nur matter.<inst>.controller.<nodeId>.info.connection zulassen
1076
- if (adapterID === 'matter') {
1077
- const parts = id.split('.');
1078
- if (parts.length !== 6 || parts[2] !== 'controller' || parts[4] !== 'info' || parts[5] !== 'connection') {
1079
- continue;
1080
- }
1081
- }
1082
-
1083
- // zigbee2MQTT: Bridge/Coordinator/System-Objekte ausfiltern (kein echter Gerätepfad)
1084
- if (adapterID === 'zigbee2MQTT') {
1085
- const parts = id.split('.');
1086
- // Pfad muss mindestens 4 Teile haben: zigbee2mqtt.0.<device>.<state>
1087
- if (parts.length < 4) {
1088
- continue;
1089
- }
1090
- // Bridge und System-Objekte ausschließen
1091
- const deviceSegment = parts[2].toLowerCase();
1092
- if (deviceSegment === 'bridge' || deviceSegment === 'coordinator' || deviceSegment === 'info' || deviceSegment === 'groups') {
1093
- continue;
1094
- }
1095
- // Zigbee2MQTT Gruppen ausschließen: Gruppen haben native.type === 'group'
1096
- // Gruppen liegen direkt auf Instanz-Ebene z.B. zigbee2mqtt.0.büro
1097
- const currDevStr = id.slice(0, id.lastIndexOf('.'));
1098
- const deviceObj = await adaptr.getForeignObjectAsync(currDevStr);
1099
- if (deviceObj && deviceObj.native && deviceObj.native.type === 'group') {
1100
- adaptr.log.debug(`[createData zigbee2MQTT] Skipping group (native.type): ${currDevStr}`);
1101
- continue;
1102
- }
1103
- // Fallback: Gruppen haben weder last_seen noch link_quality → kein echtes Gerät
1104
- const hasLastSeen = await tools.getInitValue(adaptr, `${currDevStr}.last_seen`);
1105
- const hasLinkQuality = await tools.getInitValue(adaptr, `${currDevStr}.link_quality`);
1106
- if (hasLastSeen === undefined && hasLinkQuality === undefined) {
1107
- adaptr.log.debug(`[createData zigbee2MQTT] Skipping group (no last_seen/link_quality): ${currDevStr}`);
1108
- continue;
1109
- }
1110
- }
1111
-
1112
- const mainSelector = id;
1113
-
1114
- /*=============================================
1115
- = get Instanz =
1116
- =============================================*/
1117
- const instance = id.slice(0, id.indexOf('.') + 2);
1118
-
1119
- let instanceDeviceConnectionDP = `${instance}.info.connection`;
1120
- let instanceDeviceConnected = await tools.getInitValue(adaptr, instanceDeviceConnectionDP);
1121
-
1122
- if (instanceDeviceConnected === undefined) {
1123
- const sysAdmin = `system.adapter.${instanceDeviceConnectionDP.replace('info.connection', 'connected')}`;
1124
- instanceDeviceConnectionDP = sysAdmin;
1125
- instanceDeviceConnected = await tools.getInitValue(adaptr, sysAdmin);
1126
- }
1127
-
1128
- adaptr.subscribeForeignStates(instanceDeviceConnectionDP);
1129
- adaptr.subscribeForeignObjects(`${adaptr.selAdapter[i].selektor}`);
1130
-
1131
- const deviceName = await adaptr.getDeviceName(id, i);
1132
-
1133
- const adapter = adaptr.selAdapter[i].adapter;
1134
-
1135
- /*=============================================
1136
- = Get path to datapoints =
1137
- =============================================*/
1138
- const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
1139
- const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
1140
-
1141
- // subscribe to object device path
1142
- adaptr.subscribeForeignStates(currDeviceString);
1143
-
1144
- /*=============================================
1145
- = Get signal strength =
1146
- =============================================*/
1147
- let deviceQualityDP = currDeviceString + adaptr.selAdapter[i].rssiState;
1148
- let deviceQualityState;
1149
- let linkQuality;
1150
- let linkQualityRaw;
1151
-
1152
- if (!deviceQualityDP.includes('undefined')) {
1153
- switch (adapterID) {
1154
- case 'mihomeVacuum':
1155
- deviceQualityDP = shortCurrDeviceString + adaptr.selAdapter[i].rssiState;
1156
- deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1157
- break;
1158
-
1159
- case 'netatmo':
1160
- deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1161
- if (!deviceQualityState) {
1162
- deviceQualityDP = currDeviceString + adaptr.selAdapter[i].rfState;
1163
- deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1164
- }
1165
- break;
1166
-
1167
- default:
1168
- deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1169
- }
1170
- //subscribe to states
1171
- adaptr.subscribeForeignStates(deviceQualityDP);
1172
-
1173
- const signalData = await adaptr.calculateSignalStrength(deviceQualityState, adapterID);
1174
- linkQuality = signalData[0];
1175
- linkQualityRaw = signalData[1];
1176
- }
1177
-
1178
- /*=============================================
1179
- = Get battery data =
1180
- =============================================*/
1181
- let deviceBatteryStateDP;
1182
- let deviceBatteryState;
1183
- let batteryHealth;
1184
- let batteryHealthRaw;
1185
- let batteryUnitRaw;
1186
- let lowBatIndicator;
1187
- let isBatteryDevice;
1188
- let isLowBatDP;
1189
- let faultReportingDP;
1190
- let faultReportingState;
1191
-
1192
- const deviceChargerStateDP = currDeviceString + adaptr.selAdapter[i].charger;
1193
- const deviceChargerState = await tools.getInitValue(adaptr, deviceChargerStateDP);
1194
-
1195
- if (deviceChargerState === undefined || deviceChargerState === false) {
1196
- // Get battery states
1197
- switch (adapterID) {
1198
- case 'hmrpc':
1199
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1200
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1201
-
1202
- if (deviceBatteryState === undefined) {
1203
- deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].hmDNBattery;
1204
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1205
- }
1206
- break;
1207
- case 'hueExt':
1208
- // hue-extended: battery is at currDeviceString level (e.g. hue-extended.0.lights.1.config.battery)
1209
- // NOT shortCurrDeviceString (which is the lights/sensors folder, e.g. hue-extended.0.lights)
1210
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1211
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1212
-
1213
- if (deviceBatteryState === undefined) {
1214
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery2;
1215
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1216
- }
1217
- break;
1218
- case 'mihomeVacuum':
1219
- case 'mqttNuki':
1220
- case 'loqedSmartLock':
1221
- deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].battery;
1222
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1223
-
1224
- if (deviceBatteryState === undefined) {
1225
- deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].battery2;
1226
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1227
- }
1228
- break;
1229
- case 'homee': // only battery devices, structure problem like homee.0.*.BatteryLevel-964
1230
- const devicePrefix = `${currDeviceString}.BatteryLevel-`;
1231
- const listeDP = await adaptr.getObjectViewAsync('system', 'state', {
1232
- startkey: `${devicePrefix}`,
1233
- endkey: `${devicePrefix}\u9999`,
1234
- });
1235
-
1236
- if (listeDP.rows.length > 0) {
1237
- deviceBatteryStateDP = listeDP.rows[0].id;
1238
- }
1239
-
1240
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1241
- break;
1242
-
1243
- case 'matter': {
1244
- // matter: Batterie liegt unter shortCurrDeviceString.PowerSource-N.BATTERY
1245
- // N ist variabel -> dynamisch per getObjectViewAsync suchen
1246
- const matterBattPrefix = `${shortCurrDeviceString}.PowerSource-`;
1247
- const matterBattList = await adaptr.getObjectViewAsync('system', 'state', {
1248
- startkey: `${matterBattPrefix}`,
1249
- endkey: `${matterBattPrefix}\u9999`,
1250
- });
1251
- // ersten BATTERY-State nehmen
1252
- const matterBattRow = matterBattList.rows.find((r) => r.id.endsWith('.BATTERY'));
1253
- if (matterBattRow) {
1254
- deviceBatteryStateDP = matterBattRow.id;
1255
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1256
- }
1257
- break;
1258
- }
1259
-
1260
- default:
1261
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1262
- if (adaptr.selAdapter[i].battery === 'none') {
1263
- // adapter has no battery percentage DP (e.g. hmiP) – skip lookups
1264
- deviceBatteryState = undefined;
1265
- } else {
1266
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1267
-
1268
- if (deviceBatteryState === undefined) {
1269
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery2;
1270
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1271
-
1272
- if (deviceBatteryState === undefined) {
1273
- deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery3;
1274
- deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1275
- }
1276
- }
1277
- }
1278
- break;
1279
- }
1280
-
1281
- // Get low bat states
1282
- isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat;
1283
- let deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1284
-
1285
- if (deviceLowBatState === undefined) {
1286
- isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat2;
1287
- deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1288
-
1289
- if (deviceLowBatState === undefined) {
1290
- isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat3;
1291
- deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1292
- }
1293
- }
1294
-
1295
- // matter: LOWBAT dynamisch über PowerSource-N.LOWBAT suchen
1296
- if (adapterID === 'matter' && deviceLowBatState === undefined) {
1297
- const matterLowBatPrefix = `${shortCurrDeviceString}.PowerSource-`;
1298
- const matterLowBatList = await adaptr.getObjectViewAsync('system', 'state', {
1299
- startkey: matterLowBatPrefix,
1300
- endkey: `${matterLowBatPrefix}\u9999`,
1301
- });
1302
- const matterLowBatRow = matterLowBatList.rows.find((r) => r.id.endsWith('.LOWBAT'));
1303
- if (matterLowBatRow) {
1304
- isLowBatDP = matterLowBatRow.id;
1305
- deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1306
- }
1307
- }
1308
-
1309
- if (deviceLowBatState === undefined) {
1310
- isLowBatDP = 'none';
1311
- }
1312
-
1313
- faultReportingDP = shortCurrDeviceString + adaptr.selAdapter[i].faultReporting;
1314
- faultReportingState = await tools.getInitValue(adaptr, faultReportingDP);
1315
-
1316
- //subscribe to states
1317
- if (!deviceBatteryStateDP.endsWith('undefined')) {
1318
- adaptr.subscribeForeignStates(deviceBatteryStateDP);
1319
- }
1320
- if (!isLowBatDP.endsWith('undefined') && isLowBatDP !== 'none') {
1321
- adaptr.subscribeForeignStates(isLowBatDP);
1322
- }
1323
- if (!faultReportingDP.endsWith('undefined')) {
1324
- adaptr.subscribeForeignStates(faultReportingDP);
1325
- }
1326
-
1327
- const batteryData = await adaptr.getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
1328
-
1329
- batteryHealth = batteryData[0];
1330
- batteryHealthRaw = batteryData[2];
1331
- batteryUnitRaw = batteryData[3];
1332
- isBatteryDevice = batteryData[1];
1333
-
1334
- if (isBatteryDevice) {
1335
- lowBatIndicator = await adaptr.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
1336
- }
1337
- }
1338
-
1339
- /*=============================================
1340
- = Get last contact of device =
1341
- =============================================*/
1342
- let deviceStateSelectorHMRPC;
1343
- let rssiPeerSelectorHMRPC;
1344
-
1345
- // HMRPC
1346
- if (adaptr.selAdapter[i].stateValue != undefined) {
1347
- deviceStateSelectorHMRPC = shortCurrDeviceString + adaptr.selAdapter[i].stateValue;
1348
- rssiPeerSelectorHMRPC = currDeviceString + adaptr.selAdapter[i].rssiPeerState;
1349
- adaptr.subscribeForeignStates(deviceStateSelectorHMRPC);
1350
- adaptr.subscribeForeignStates(rssiPeerSelectorHMRPC);
1351
- }
1352
-
1353
- let timeSelector = currDeviceString + adaptr.selAdapter[i].timeSelector;
1354
- const timeSelectorState = await tools.getInitValue(adaptr, timeSelector);
1355
-
1356
- if (timeSelectorState === undefined) {
1357
- timeSelector = shortCurrDeviceString + adaptr.selAdapter[i].timeSelector;
1358
- }
1359
-
1360
- let unreachDP = currDeviceString + adaptr.selAdapter[i].reach;
1361
-
1362
- let deviceUnreachState = await tools.getInitValue(adaptr, unreachDP);
1363
-
1364
- if (deviceUnreachState === undefined) {
1365
- unreachDP = shortCurrDeviceString + adaptr.selAdapter[i].reach;
1366
- deviceUnreachState = await tools.getInitValue(adaptr, shortCurrDeviceString + adaptr.selAdapter[i].reach);
1367
- }
1368
-
1369
- // subscribe to states
1370
- adaptr.subscribeForeignStates(timeSelector);
1371
- adaptr.subscribeForeignStates(unreachDP);
1372
-
1373
- const onlineState = await adaptr.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorHMRPC, rssiPeerSelectorHMRPC);
1374
-
1375
- let deviceState;
1376
- let lastContactString;
1377
-
1378
- if (onlineState !== undefined && onlineState !== null) {
1379
- lastContactString = onlineState[0];
1380
- deviceState = onlineState[1];
1381
- linkQuality = onlineState[2];
1382
- }
1383
-
1384
- /*=============================================
1385
- = Get update data =
1386
- =============================================*/
1387
- let isUpgradable = ' - ';
1388
- let deviceUpdateDP;
1389
-
1390
- if (adaptr.config.checkSendDeviceUpgrade) {
1391
- deviceUpdateDP = currDeviceString + adaptr.selAdapter[i].upgrade;
1392
- let deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1393
- if (deviceUpdateSelector === undefined) {
1394
- deviceUpdateDP = shortCurrDeviceString + adaptr.selAdapter[i].upgrade;
1395
- deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1396
- if (deviceUpdateSelector === undefined) {
1397
- const shortShortCurrDeviceString = shortCurrDeviceString.slice(0, shortCurrDeviceString.lastIndexOf('.') + 1 - 1);
1398
- deviceUpdateDP = shortShortCurrDeviceString + adaptr.selAdapter[i].upgrade;
1399
- deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1400
- }
1401
- }
1402
-
1403
- if (deviceUpdateSelector !== undefined) {
1404
- isUpgradable = await adaptr.checkDeviceUpdate(adapterID, deviceUpdateSelector);
1405
- }
1406
-
1407
- if (!deviceUpdateDP.endsWith('undefined')) {
1408
- if (!deviceUpdateDP.endsWith('none')) {
1409
- if (!deviceUpdateDP.endsWith('null')) {
1410
- adaptr.subscribeForeignStates(deviceUpdateDP);
1411
- }
1412
- }
1413
- }
1414
- }
1415
-
1416
- /*=============================================
1417
- = Fill Raw Lists =
1418
- =============================================*/
1419
- const setupList = () => {
1420
- adaptr.listAllDevicesRaw.set(currDeviceString, {
1421
- Path: id,
1422
- mainSelector: mainSelector,
1423
- instanceDeviceConnectionDP: instanceDeviceConnectionDP,
1424
- instanceDeviceConnected: instanceDeviceConnected,
1425
- instance: instance,
1426
- Device: deviceName,
1427
- adapterID: adapterID,
1428
- Adapter: adapter,
1429
- timeSelector: timeSelector,
1430
- isBatteryDevice: isBatteryDevice,
1431
- Battery: batteryHealth,
1432
- BatteryRaw: batteryHealthRaw,
1433
- BatteryUnitRaw: batteryUnitRaw,
1434
- batteryDP: deviceBatteryStateDP,
1435
- LowBat: lowBatIndicator,
1436
- LowBatDP: isLowBatDP,
1437
- faultReport: faultReportingState,
1438
- faultReportDP: faultReportingDP,
1439
- SignalStrengthDP: deviceQualityDP,
1440
- SignalStrength: linkQuality,
1441
- SignalStrengthRaw: linkQualityRaw,
1442
- UnreachState: deviceUnreachState,
1443
- UnreachDP: unreachDP,
1444
- deviceStateSelectorHMRPC: deviceStateSelectorHMRPC,
1445
- rssiPeerSelectorHMRPC: rssiPeerSelectorHMRPC,
1446
- LastContact: lastContactString,
1447
- Status: deviceState,
1448
- UpdateDP: deviceUpdateDP,
1449
- Upgradable: isUpgradable,
1450
- });
1451
- };
1452
-
1453
- if (!adaptr.configListOnlyBattery) {
1454
- // Add all devices
1455
- setupList();
1456
- } else {
1457
- // Add only devices with battery in the rawlist
1458
- if (!isBatteryDevice) {
1459
- continue;
1460
- }
1461
-
1462
- setupList();
1463
- }
1464
- } // <-- end of loop
1465
- } catch (error) {
1466
- adaptr.log.error(`[createData - create data of devices] - ${error}`);
1467
- }
1468
- } // <-- end of createData
1469
-
1470
- /**
1471
- * Create Lists
1472
- *
1473
- * @param adaptr
1474
- * @param {string | undefined} [adptName]
1475
- */
1476
- async function createLists(adaptr, adptName) {
1477
- adaptr.linkQualityDevices = [];
1478
- adaptr.batteryPowered = [];
1479
- adaptr.batteryLowPowered = [];
1480
- adaptr.listAllDevicesUserRaw = [];
1481
- adaptr.listAllDevices = [];
1482
- adaptr.offlineDevices = [];
1483
- adaptr.batteryLowPoweredRaw = [];
1484
- adaptr.offlineDevicesRaw = [];
1485
- adaptr.upgradableDevicesRaw = [];
1486
- adaptr.upgradableList = [];
1487
-
1488
- if (adptName === undefined) {
1489
- adptName = '';
1490
- }
1491
-
1492
- for (const deviceData of adaptr.listAllDevicesRaw.values()) {
1493
- /*---------- fill raw lists ----------*/
1494
- // low bat list
1495
- if (deviceData.LowBat && deviceData.Status !== 'Offline') {
1496
- adaptr.batteryLowPoweredRaw.push({
1497
- Path: deviceData.Path,
1498
- Device: deviceData.Device,
1499
- Adapter: deviceData.Adapter,
1500
- Battery: deviceData.Battery,
1501
- });
1502
- }
1503
- // offline raw list
1504
- if (deviceData.Status === 'Offline') {
1505
- adaptr.offlineDevicesRaw.push({
1506
- Path: deviceData.Path,
1507
- Device: deviceData.Device,
1508
- Adapter: deviceData.Adapter,
1509
- LastContact: deviceData.LastContact,
1510
- });
1511
- }
1512
-
1513
- // upgradable raw list
1514
- if (deviceData.Upgradable === true) {
1515
- adaptr.upgradableDevicesRaw.push({
1516
- Path: deviceData.Path,
1517
- Device: deviceData.Device,
1518
- Adapter: deviceData.Adapter,
1519
- });
1520
- }
1521
-
1522
- if (adptName === '' && !adaptr.blacklistLists.includes(deviceData.Path)) {
1523
- await adaptr.theLists(deviceData);
1524
- }
1525
-
1526
- if (adaptr.config.createOwnFolder && adptName !== '') {
1527
- if (!deviceData.adapterID.includes(adptName)) {
1528
- continue;
1529
- }
1530
- /*---------- fill user lists for each adapter ----------*/
1531
- if (adaptr.blacklistAdapterLists.includes(deviceData.Path)) {
1532
- continue;
1533
- }
1534
- await adaptr.theLists(deviceData);
1535
- }
1536
- }
1537
- await tools.countDevices(adaptr);
1538
- }
1539
-
1540
- /**
1541
- * @param adaptr
1542
- * @param {string} [adptName] - Adaptername
1543
- */
1544
- async function writeDatapoints(adaptr, adptName) {
1545
- // fill the datapoints
1546
- adaptr.log.debug(`Start the function writeDatapoints`);
1547
-
1548
- try {
1549
- let dpSubFolder;
1550
- //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
1551
- if (adptName) {
1552
- dpSubFolder = `${adptName}.`;
1553
- } else {
1554
- dpSubFolder = '';
1555
- }
1556
-
1557
- // Write Datapoints for counts
1558
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}offlineCount`, { val: adaptr.offlineDevicesCount, ack: true });
1559
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}countAll`, { val: adaptr.deviceCounter, ack: true });
1560
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}batteryCount`, { val: adaptr.batteryPoweredCount, ack: true });
1561
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: adaptr.lowBatteryPoweredCount, ack: true });
1562
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}upgradableCount`, { val: adaptr.upgradableDevicesCount, ack: true });
1563
- // List all devices
1564
- if (adaptr.deviceCounter === 0) {
1565
- // if no device is count, write the JSON List with default value
1566
- adaptr.listAllDevices = [
1567
- {
1568
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1569
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1570
- [translations.Battery[adaptr.config.userSelectedLanguage]]: '',
1571
- [translations.Signal_strength[adaptr.config.userSelectedLanguage]]: '',
1572
- [translations.Last_Contact[adaptr.config.userSelectedLanguage]]: '',
1573
- [translations.Status[adaptr.config.userSelectedLanguage]]: '',
1574
- },
1575
- ];
1576
- adaptr.listAllDevicesUserRaw = [
1577
- {
1578
- Device: '--none--',
1579
- Adapter: '',
1580
- Instance: '',
1581
- 'Instance connected': '',
1582
- isBatteryDevice: '',
1583
- Battery: '',
1584
- BatteryRaw: '',
1585
- isLowBat: '',
1586
- 'Signal strength': '',
1587
- 'Last contact': '',
1588
- UpdateAvailable: '',
1589
- Status: '',
1590
- },
1591
- ];
1592
- }
1593
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(adaptr.listAllDevices), ack: true });
1594
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}listAllRawJSON`, { val: JSON.stringify(adaptr.listAllDevicesUserRaw), ack: true });
1595
-
1596
- // List link quality
1597
- if (adaptr.linkQualityCount === 0) {
1598
- // if no device is count, write the JSON List with default value
1599
- adaptr.linkQualityDevices = [
1600
- {
1601
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1602
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1603
- [translations.Signal_strength[adaptr.config.userSelectedLanguage]]: '',
1604
- },
1605
- ];
1606
- }
1607
- //write JSON list
1608
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}linkQualityList`, {
1609
- val: JSON.stringify(adaptr.linkQualityDevices),
1610
- ack: true,
1611
- });
1612
-
1613
- // List offline devices
1614
- if (adaptr.offlineDevicesCount === 0) {
1615
- // if no device is count, write the JSON List with default value
1616
- adaptr.offlineDevices = [
1617
- {
1618
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1619
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1620
- [translations.Last_Contact[adaptr.config.userSelectedLanguage]]: '',
1621
- },
1622
- ];
1623
- }
1624
- //write JSON list
1625
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}offlineList`, {
1626
- val: JSON.stringify(adaptr.offlineDevices),
1627
- ack: true,
1628
- });
1629
-
1630
- // List updatable
1631
- if (adaptr.upgradableDevicesCount === 0) {
1632
- // if no device is count, write the JSON List with default value
1633
- adaptr.upgradableList = [
1634
- {
1635
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1636
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1637
- [translations.Last_Contact[adaptr.config.userSelectedLanguage]]: '',
1638
- },
1639
- ];
1640
- }
1641
- //write JSON list
1642
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}upgradableList`, {
1643
- val: JSON.stringify(adaptr.upgradableList),
1644
- ack: true,
1645
- });
1646
-
1647
- // List battery powered
1648
- if (adaptr.batteryPoweredCount === 0) {
1649
- // if no device is count, write the JSON List with default value
1650
- adaptr.batteryPowered = [
1651
- {
1652
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1653
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1654
- [translations.Battery[adaptr.config.userSelectedLanguage]]: '',
1655
- },
1656
- ];
1657
- }
1658
- //write JSON list
1659
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}batteryList`, {
1660
- val: JSON.stringify(adaptr.batteryPowered),
1661
- ack: true,
1662
- });
1663
-
1664
- // list battery low powered
1665
- if (adaptr.lowBatteryPoweredCount === 0) {
1666
- // if no device is count, write the JSON List with default value
1667
- adaptr.batteryLowPowered = [
1668
- {
1669
- [translations.Device[adaptr.config.userSelectedLanguage]]: '--none--',
1670
- [translations.Adapter[adaptr.config.userSelectedLanguage]]: '',
1671
- [translations.Battery[adaptr.config.userSelectedLanguage]]: '',
1672
- },
1673
- ];
1674
- }
1675
- //write JSON list
1676
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryList`, {
1677
- val: JSON.stringify(adaptr.batteryLowPowered),
1678
- ack: true,
1679
- });
1680
-
1681
- // set booleans datapoints
1682
- if (adaptr.offlineDevicesCount === 0) {
1683
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1684
- val: false,
1685
- ack: true,
1686
- });
1687
- } else {
1688
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1689
- val: true,
1690
- ack: true,
1691
- });
1692
- }
1693
-
1694
- if (adaptr.lowBatteryPoweredCount === 0) {
1695
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1696
- val: false,
1697
- ack: true,
1698
- });
1699
- } else {
1700
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1701
- val: true,
1702
- ack: true,
1703
- });
1704
- }
1705
-
1706
- if (adaptr.upgradableDevicesCount === 0) {
1707
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1708
- val: false,
1709
- ack: true,
1710
- });
1711
- } else {
1712
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1713
- val: true,
1714
- ack: true,
1715
- });
1716
- }
1717
-
1718
- //write HTML list
1719
- if (adaptr.configCreateHtmlList) {
1720
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1721
- val: await this.createListHTML(adaptr, 'linkQualityList', adaptr.linkQualityDevices, adaptr.linkQualityCount, null),
1722
- ack: true,
1723
- });
1724
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}offlineListHTML`, {
1725
- val: await this.createListHTML(adaptr, 'offlineList', adaptr.offlineDevices, adaptr.offlineDevicesCount, null),
1726
- ack: true,
1727
- });
1728
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}batteryListHTML`, {
1729
- val: await this.createListHTML(adaptr, 'batteryList', adaptr.batteryPowered, adaptr.batteryPoweredCount, false),
1730
- ack: true,
1731
- });
1732
- await adaptr.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1733
- val: await this.createListHTML(adaptr, 'batteryList', adaptr.batteryLowPowered, adaptr.lowBatteryPoweredCount, true),
1734
- ack: true,
1735
- });
1736
-
1737
- if (adaptr.config.checkAdapterInstances) {
1738
- await adaptr.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
1739
- val: await this.createListHTMLInstances(adaptr, 'allInstancesList', adaptr.listAllInstances, adaptr.countAllInstances),
1740
- ack: true,
1741
- });
1742
- await adaptr.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
1743
- val: await this.createListHTMLInstances(adaptr, 'allActiveInstancesList', adaptr.listAllActiveInstances, adaptr.countAllActiveInstances),
1744
- ack: true,
1745
- });
1746
- await adaptr.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
1747
- val: await this.createListHTMLInstances(adaptr, 'errorInstanceList', adaptr.listErrorInstance, adaptr.countErrorInstance),
1748
- ack: true,
1749
- });
1750
- await adaptr.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
1751
- val: await this.createListHTMLInstances(adaptr, 'deactivatedInstanceList', adaptr.listDeactivatedInstances, adaptr.countDeactivatedInstances),
1752
- ack: true,
1753
- });
1754
- await adaptr.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
1755
- val: await this.createListHTMLInstances(adaptr, 'updateAdapterList', adaptr.listAdapterUpdates, adaptr.countAdapterUpdates),
1756
- ack: true,
1757
- });
1758
- }
1759
- }
1760
-
1761
- // create timestamp of last run
1762
- const lastCheck = `${adaptr.formatDate(new Date(), 'DD.MM.YYYY')} - ${adaptr.formatDate(new Date(), 'hh:mm:ss')}`;
1763
- await adaptr.setStateChangedAsync('lastCheck', lastCheck, true);
1764
- } catch (error) {
1765
- adaptr.log.error(`[writeDatapoints] - ${error}`);
1766
- }
1767
- } //<--End of writing Datapoints
1768
-
1769
- /**
1770
- * create Datapoints for Instances
1771
- *
1772
- * @param adaptr
1773
- */
1774
- async function createDPsForInstances(adaptr) {
1775
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances`, {
1776
- type: 'channel',
1777
- common: {
1778
- name: {
1779
- en: 'Adapter and Instances',
1780
- de: 'Adapter und Instanzen',
1781
- ru: 'Адаптер и экземпляры',
1782
- pt: 'Adaptador e Instâncias',
1783
- nl: 'Adapter en Instanties',
1784
- fr: 'Adaptateur et instances',
1785
- it: 'Adattatore e istanze',
1786
- es: 'Adaptador e instancias',
1787
- pl: 'Adapter i Instancje',
1788
- uk: 'Адаптер та його екземпляри',
1789
- 'zh-cn': '适配器和实例',
1790
- },
1791
- },
1792
- native: {},
1793
- });
1794
-
1795
- // Instances
1796
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAllInstances`, {
1797
- type: 'state',
1798
- common: {
1799
- name: {
1800
- en: 'JSON List of all instances',
1801
- de: 'JSON-Liste aller Instanzen',
1802
- ru: 'JSON-список всех экземпляров',
1803
- pt: 'Lista JSON de todas as instâncias',
1804
- nl: 'JSON-lijst van alle instanties',
1805
- fr: 'Liste JSON de toutes les instances',
1806
- it: 'Elenco JSON di tutte le istanze',
1807
- es: 'Lista JSON de todas las instancias',
1808
- pl: 'Lista JSON wszystkich instancji',
1809
- uk: 'JSON-список всіх інстанцій',
1810
- 'zh-cn': '所有实例的JSON列表',
1811
- },
1812
- type: 'array',
1813
- role: 'json',
1814
- read: true,
1815
- write: false,
1816
- },
1817
- native: {},
1818
- });
1819
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAllInstances`, {
1820
- type: 'state',
1821
- common: {
1822
- name: {
1823
- en: 'Number of all instances',
1824
- de: 'Anzahl aller Instanzen',
1825
- ru: 'Количество всех экземпляров',
1826
- pt: 'Número de todas as instâncias',
1827
- nl: 'Aantal van alle instanties',
1828
- fr: 'Nombre de toutes les instances',
1829
- it: 'Numero di tutte le istanze',
1830
- es: 'Número de todas las instancias',
1831
- pl: 'Liczba wszystkich instancji',
1832
- uk: 'Кількість усіх інстанцій',
1833
- 'zh-cn': '所有实例的数量',
1834
- },
1835
- type: 'number',
1836
- role: 'value',
1837
- read: true,
1838
- write: false,
1839
- },
1840
- native: {},
1841
- });
1842
- // Instances
1843
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAllActiveInstances`, {
1844
- type: 'state',
1845
- common: {
1846
- name: {
1847
- en: 'JSON List of all active instances',
1848
- de: 'JSON-Liste aller aktiven Instanzen',
1849
- ru: 'JSON список всех активных экземпляров',
1850
- pt: 'Lista JSON de todas as instâncias ativas',
1851
- nl: 'JSON-lijst van alle actieve instanties',
1852
- fr: 'Liste JSON de toutes les instances actives',
1853
- it: 'Elenco JSON di tutte le istanze attive',
1854
- es: 'Lista JSON de todas las instancias activas',
1855
- pl: 'JSON lista wszystkich aktywnych instancji',
1856
- uk: 'JSON список усіх активних екземплярів',
1857
- 'zh-cn': '所有活动实例的 JSON 列表',
1858
- },
1859
- type: 'array',
1860
- role: 'json',
1861
- read: true,
1862
- write: false,
1863
- },
1864
- native: {},
1865
- });
1866
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAllActiveInstances`, {
1867
- type: 'state',
1868
- common: {
1869
- name: {
1870
- en: 'Number of all active instances',
1871
- de: 'Anzahl aller aktiven Instanzen',
1872
- ru: 'Количество всех активных экземпляров',
1873
- pt: 'Número de todas as instâncias ativas',
1874
- nl: 'Aantal van alle actieve instanties',
1875
- fr: 'Nombre de toutes les instances actives',
1876
- it: 'Numero di tutte le istanze attive',
1877
- es: 'Número de todas las instancias activas',
1878
- pl: 'Liczba wszystkich aktywnych instancji',
1879
- uk: 'Кількість усіх активних екземплярів',
1880
- 'zh-cn': '所有活动实例的数量',
1881
- },
1882
- type: 'number',
1883
- role: 'value',
1884
- read: true,
1885
- write: false,
1886
- },
1887
- native: {},
1888
- });
1889
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listDeactivatedInstances`, {
1890
- type: 'state',
1891
- common: {
1892
- name: {
1893
- en: 'JSON List of deactivated instances',
1894
- de: 'JSON-Liste der deaktivierten Instanzen',
1895
- ru: 'JSON список деактивированных экземпляров',
1896
- pt: 'JSON Lista de instâncias desativadas',
1897
- nl: 'JSON-lijst van gedeactiveerde instanties',
1898
- fr: 'Liste JSON des instances désactivées',
1899
- it: 'JSON Elenco delle istanze disattivate',
1900
- es: 'Lista JSON de instancias desactivadas',
1901
- pl: 'JSON lista dezaktywowanych instancji',
1902
- uk: 'JSON список деактивованих екземплярів',
1903
- 'zh-cn': '已停用实例的 JSON 列表',
1904
- },
1905
- type: 'array',
1906
- role: 'json',
1907
- read: true,
1908
- write: false,
1909
- },
1910
- native: {},
1911
- });
1912
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countDeactivatedInstances`, {
1913
- type: 'state',
1914
- common: {
1915
- name: {
1916
- en: 'Number of deactivated instances',
1917
- de: 'Anzahl deaktivierter Instanzen',
1918
- ru: 'Количество деактивированных экземпляров',
1919
- pt: 'Número de instâncias desativadas',
1920
- nl: 'Aantal gedeactiveerde instanties',
1921
- fr: "Nombre d'instances désactivées",
1922
- it: 'Numero di istanze disattivate',
1923
- es: 'Número de instancias desactivadas',
1924
- pl: 'Liczba deaktywowanych instancji',
1925
- uk: 'Кількість деактивованих екземплярів',
1926
- 'zh-cn': '已停用实例的数量',
1927
- },
1928
- type: 'number',
1929
- role: 'value',
1930
- read: true,
1931
- write: false,
1932
- },
1933
- native: {},
1934
- });
1935
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listInstancesError`, {
1936
- type: 'state',
1937
- common: {
1938
- name: {
1939
- en: 'JSON list of instances with error',
1940
- de: 'JSON-Liste von Instanzen mit Fehler',
1941
- ru: 'JSON список экземпляров с ошибкой',
1942
- pt: 'Lista de instâncias JSON com erro',
1943
- nl: 'JSON lijst met fouten',
1944
- fr: 'Liste des instances avec erreur',
1945
- it: 'Elenco JSON delle istanze con errore',
1946
- es: 'JSON lista de casos con error',
1947
- pl: 'JSON lista instancji z błędem',
1948
- uk: 'JSON список інстанцій з помилкою',
1949
- 'zh-cn': '含错误实例的 JSON 列表',
1950
- },
1951
- type: 'array',
1952
- role: 'json',
1953
- read: true,
1954
- write: false,
1955
- },
1956
- native: {},
1957
- });
1958
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countInstancesError`, {
1959
- type: 'state',
1960
- common: {
1961
- name: {
1962
- en: 'Count of instances with error',
1963
- de: 'Anzahl der Instanzen mit Fehler',
1964
- ru: 'Количество экземпляров с ошибкой',
1965
- pt: 'Contagem de instâncias com erro',
1966
- nl: 'Aantal instanties met fouten',
1967
- fr: "Nombre d'instances avec erreur",
1968
- it: 'Conteggio delle istanze con errore',
1969
- es: 'Recuento de instancias con error',
1970
- pl: 'Liczba instancji z błędem',
1971
- uk: 'Кількість інстанцій з помилкою',
1972
- 'zh-cn': '出错实例的数量',
1973
- },
1974
- type: 'number',
1975
- role: 'value',
1976
- read: true,
1977
- write: false,
1978
- },
1979
- native: {},
1980
- });
1981
-
1982
- // Adapter
1983
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAdapterUpdates`, {
1984
- type: 'state',
1985
- common: {
1986
- name: {
1987
- en: 'JSON list of adapters with available updates',
1988
- de: 'JSON-Liste der Adapter mit verfügbaren Updates',
1989
- ru: 'JSON список адаптеров с доступными обновлениями',
1990
- pt: 'Lista de adaptadores JSON com atualizações disponíveis',
1991
- nl: 'JSON lijst van adapters met beschikbare updates',
1992
- fr: 'Liste JSON des adaptateurs avec mises à jour disponibles',
1993
- it: 'Elenco JSON degli adattatori con aggiornamenti disponibili',
1994
- es: 'JSON lista de adaptadores con actualizaciones disponibles',
1995
- pl: 'JSON lista adapterów z dostępnymi aktualizacjami',
1996
- uk: 'JSON список адаптерів з доступними оновленнями',
1997
- 'zh-cn': '具有可用更新的适配器的 JSON 列表',
1998
- },
1999
- type: 'array',
2000
- role: 'json',
2001
- read: true,
2002
- write: false,
2003
- },
2004
- native: {},
2005
- });
2006
- await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAdapterUpdates`, {
2007
- type: 'state',
2008
- common: {
2009
- name: {
2010
- en: 'Number of adapters with available updates',
2011
- de: 'Anzahl der Adapter mit verfügbaren Updates',
2012
- ru: 'Количество адаптеров с доступными обновлениями',
2013
- pt: 'Número de adaptadores com atualizações disponíveis',
2014
- nl: 'Aantal adapters met beschikbare updates',
2015
- fr: "Nombre d'adaptateurs avec mises à jour disponibles",
2016
- it: 'Numero di adattatori con aggiornamenti disponibili',
2017
- es: 'Número de adaptadores con actualizaciones disponibles',
2018
- pl: 'Liczba adapterów z dostępnymi aktualizacjami',
2019
- uk: 'Кількість адаптерів з доступними оновленнями',
2020
- 'zh-cn': '具有可用更新的适配器数量',
2021
- },
2022
- type: 'number',
2023
- role: 'value',
2024
- read: true,
2025
- write: false,
2026
- },
2027
- native: {},
2028
- });
2029
- }
2030
-
2031
- /**
2032
- * delete Datapoints for Instances
2033
- *
2034
- * @param adaptr
2035
- */
2036
- async function deleteDPsForInstances(adaptr) {
2037
- await adaptr.delObjectAsync(`adapterAndInstances`);
2038
- await adaptr.delObjectAsync(`adapterAndInstances.listAllInstances`);
2039
- await adaptr.delObjectAsync(`adapterAndInstances.countAllInstances`);
2040
- await adaptr.delObjectAsync(`adapterAndInstances.listAllActiveInstances`);
2041
- await adaptr.delObjectAsync(`adapterAndInstances.countAllActiveInstances`);
2042
- await adaptr.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
2043
- await adaptr.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
2044
- await adaptr.delObjectAsync(`adapterAndInstances.listInstancesError`);
2045
- await adaptr.delObjectAsync(`adapterAndInstances.countInstancesError`);
2046
- await adaptr.delObjectAsync(`adapterAndInstances.listAdapterUpdates`);
2047
- await adaptr.delObjectAsync(`adapterAndInstances.countAdapterUpdates`);
2048
- }
2049
-
2050
- /**
2051
- * create adapter update data
2052
- *
2053
- * @param adaptr
2054
- * @param adapterUpdateListDP
2055
- */
2056
- async function createAdapterUpdateData(adaptr, adapterUpdateListDP) {
2057
- // subscribe to datapoint
2058
- adaptr.subscribeForeignStates(adapterUpdateListDP);
2059
-
2060
- await adaptr.getAdapterUpdateData(adapterUpdateListDP);
2061
-
2062
- await adaptr.createAdapterUpdateList();
2063
- }
2064
-
2065
- module.exports = {
2066
- createDPsForEachAdapter,
2067
- deleteDPsForEachAdapter,
2068
- createHtmlListDatapoints,
2069
- deleteHtmlListDatapoints,
2070
- createHtmlListDatapointsInstances,
2071
- deleteHtmlListDatapointsInstances,
2072
- createListHTML,
2073
- createListHTMLInstances,
2074
- createBlacklist,
2075
- createTimeListInstances,
2076
- createData,
2077
- createLists,
2078
- writeDatapoints,
2079
- createDPsForInstances,
2080
- deleteDPsForInstances,
2081
- createAdapterUpdateData,
2082
- };
1
+ const translations = require('./translations');
2
+ const tools = require('./tools');
3
+
4
+ // In-Memory-Cache für writeDatapoints – verhindert unnötige State-Schreibvorgänge
5
+ const _dpWriteCache = new Map();
6
+
7
+ /**
8
+ * Serialisiert für den Cache-Vergleich.
9
+ * LastContact-Felder werden ignoriert – sie ändern sich jede Minute ("5 min" → "6 min")
10
+ * und dürfen keinen State-Write triggern.
11
+ *
12
+ * @param {string|any} val - Der zu serialisierende Wert; Arrays werden von LastContact-Feldern bereinigt
13
+ */
14
+ function serializeForCache(val) {
15
+ if (typeof val !== 'string' || !val.startsWith('[')) {
16
+ return typeof val === 'object' ? JSON.stringify(val) : String(val);
17
+ }
18
+ try {
19
+ const parsed = JSON.parse(val);
20
+ if (!Array.isArray(parsed)) {
21
+ return val;
22
+ }
23
+ const stripped = parsed.map((entry) => {
24
+ if (typeof entry !== 'object' || entry === null) {
25
+ return entry;
26
+ }
27
+ const copy = { ...entry };
28
+ for (const key of Object.keys(copy)) {
29
+ if (key.toLowerCase().includes('contact') || key.toLowerCase().includes('kontakt')) {
30
+ delete copy[key];
31
+ }
32
+ }
33
+ return copy;
34
+ });
35
+ return JSON.stringify(stripped);
36
+ } catch {
37
+ return val;
38
+ }
39
+ }
40
+
41
+ async function setStateIfChanged(adaptr, dpKey, val, cacheKey = null) {
42
+ const cached = _dpWriteCache.get(dpKey);
43
+ const key = cacheKey !== null ? cacheKey : serializeForCache(val);
44
+ if (cached === key) {
45
+ return;
46
+ }
47
+ _dpWriteCache.set(dpKey, key);
48
+ await adaptr.setStateChangedAsync(dpKey, { val, ack: true });
49
+ }
50
+
51
+ /**
52
+ * @param {object} adaptr - ioBroker Adapter-Instanz
53
+ * @param {object} adptName - Adaptername of devices
54
+ */
55
+ async function createDPsForEachAdapter(adaptr, adptName) {
56
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}`, {
57
+ type: 'channel',
58
+ common: {
59
+ name: adptName,
60
+ },
61
+ native: {},
62
+ });
63
+
64
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.offlineCount`, {
65
+ type: 'state',
66
+ common: {
67
+ name: {
68
+ en: 'Number of devices offline',
69
+ de: 'Anzahl der Geräte offline',
70
+ ru: 'Количество устройств оффлайн',
71
+ pt: 'Número de dispositivos offline',
72
+ nl: 'Aantal offline apparaten',
73
+ fr: 'Nombre de dispositifs hors ligne',
74
+ it: 'Numero di dispositivi offline',
75
+ es: 'Número de dispositivos sin conexión',
76
+ pl: 'Liczba urządzeń offline',
77
+ 'zh-cn': '离线设备数量',
78
+ },
79
+ type: 'number',
80
+ role: 'value',
81
+ read: true,
82
+ write: false,
83
+ },
84
+ native: {},
85
+ });
86
+
87
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.offlineList`, {
88
+ type: 'state',
89
+ common: {
90
+ name: {
91
+ en: 'List of offline devices',
92
+ de: 'Liste der Offline-Geräte',
93
+ ru: 'Список оффлайн устройств',
94
+ pt: 'Lista de dispositivos offline',
95
+ nl: 'Lijst van offline apparaten',
96
+ fr: 'Liste des dispositifs hors ligne',
97
+ it: 'Elenco dei dispositivi offline',
98
+ es: 'Lista de dispositivos sin conexión',
99
+ pl: 'Lista urządzeń offline',
100
+ 'zh-cn': '离线设备列表',
101
+ },
102
+ type: 'array',
103
+ role: 'json',
104
+ read: true,
105
+ write: false,
106
+ },
107
+ native: {},
108
+ });
109
+
110
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceOffline`, {
111
+ type: 'state',
112
+ common: {
113
+ name: {
114
+ en: 'Is one device offline',
115
+ de: 'Ist ein Gerät offline',
116
+ ru: 'Есть ли одно устройство оффлайн',
117
+ pt: ' um dispositivo offline',
118
+ nl: 'Is er een apparaat offline',
119
+ fr: 'Y a-t-il un appareil hors ligne',
120
+ it: "C'è un dispositivo offline",
121
+ es: '¿Hay un dispositivo sin conexión?',
122
+ pl: 'Czy jedno urządzenie jest offline',
123
+ uk: 'Чи є один пристрій офлайн',
124
+ 'zh-cn': '是否有一台设备离线',
125
+ },
126
+ type: 'boolean',
127
+ role: 'state',
128
+ read: true,
129
+ write: false,
130
+ def: false,
131
+ },
132
+ native: {},
133
+ });
134
+
135
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.listAllRawJSON`, {
136
+ type: 'state',
137
+ common: {
138
+ name: {
139
+ en: 'JSON RAW List of all devices',
140
+ de: 'JSON RAW Liste aller Geräte',
141
+ ru: 'JSON RAW Список всех устройств',
142
+ pt: 'JSON RAW Lista de todos os dispositivos',
143
+ nl: 'JSON RAW Lijst van alle apparaten',
144
+ fr: 'JSON RAW Liste de tous les dispositifs',
145
+ it: 'JSON RAW Elenco di tutti i dispositivi',
146
+ es: 'JSON RAW Lista de todos los dispositivos',
147
+ pl: 'JSON RAW Lista wszystkich urządzeń',
148
+ uk: 'JSON RAW Список усіх пристроїв',
149
+ 'zh-cn': 'JSON RAW 所有设备列表',
150
+ },
151
+ type: 'array',
152
+ role: 'json',
153
+ read: true,
154
+ write: false,
155
+ },
156
+ native: {},
157
+ });
158
+
159
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.listAll`, {
160
+ type: 'state',
161
+ common: {
162
+ name: {
163
+ en: 'List of all devices',
164
+ de: 'Liste aller Geräte',
165
+ ru: 'Список всех устройств',
166
+ pt: 'Lista de todos os dispositivos',
167
+ nl: 'Lijst van alle apparaten',
168
+ fr: 'Liste de tous les dispositifs',
169
+ it: 'Elenco di tutti i dispositivi',
170
+ es: 'Lista de todos los dispositivos',
171
+ pl: 'Lista wszystkich urządzeń',
172
+ 'zh-cn': '所有设备的列表',
173
+ },
174
+ type: 'array',
175
+ role: 'json',
176
+ read: true,
177
+ write: false,
178
+ },
179
+ native: {},
180
+ });
181
+
182
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.linkQualityList`, {
183
+ type: 'state',
184
+ common: {
185
+ name: {
186
+ en: 'List of devices with signal strength',
187
+ de: 'Liste der Geräte mit Signalstärke',
188
+ ru: 'Список устройств с уровнем сигнала',
189
+ pt: 'Lista de dispositivos com força de sinal',
190
+ nl: 'Lijst van apparaten met signaalkracht',
191
+ fr: 'Liste des dispositifs avec force de signal',
192
+ it: 'Elenco dei dispositivi con forza del segnale',
193
+ es: 'Lista de dispositivos con fuerza de señal',
194
+ pl: 'Lista urządzeń z siłą sygnału',
195
+ 'zh-cn': '具有信号强度的设备列表',
196
+ },
197
+ type: 'array',
198
+ role: 'json',
199
+ read: true,
200
+ write: false,
201
+ },
202
+ native: {},
203
+ });
204
+
205
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.countAll`, {
206
+ type: 'state',
207
+ common: {
208
+ name: {
209
+ en: 'Number of all devices',
210
+ de: 'Anzahl aller Geräte',
211
+ ru: 'Количество всех устройств',
212
+ pt: 'Número de todos os dispositivos',
213
+ nl: 'Aantal van alle apparaten',
214
+ fr: 'Nombre de tous les appareils',
215
+ it: 'Numero di tutti i dispositivi',
216
+ es: 'Número de todos los dispositivos',
217
+ pl: 'Liczba wszystkich urządzeń',
218
+ 'zh-cn': '所有设备的数量',
219
+ },
220
+ type: 'number',
221
+ role: 'value',
222
+ read: true,
223
+ write: false,
224
+ },
225
+ native: {},
226
+ });
227
+
228
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.batteryList`, {
229
+ type: 'state',
230
+ common: {
231
+ name: {
232
+ en: 'List of devices with battery state',
233
+ de: 'Liste der Geräte mit Batteriezustand',
234
+ ru: 'Список устройств с состоянием батареи',
235
+ pt: 'Lista de dispositivos com estado da bateria',
236
+ nl: 'Lijst van apparaten met batterijstatus',
237
+ fr: 'Liste des appareils avec état de batterie',
238
+ it: 'Elenco dei dispositivi con stato della batteria',
239
+ es: 'Lista de dispositivos con estado de batería',
240
+ pl: 'Lista urządzeń ze stanem baterii',
241
+ 'zh-cn': '具有电池状态的设备列表',
242
+ },
243
+ type: 'array',
244
+ role: 'json',
245
+ read: true,
246
+ write: false,
247
+ },
248
+ native: {},
249
+ });
250
+
251
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryList`, {
252
+ type: 'state',
253
+ common: {
254
+ name: {
255
+ en: 'List of devices with low battery state',
256
+ de: 'Liste der Geräte mit niedrigem Batteriezustand',
257
+ ru: 'Список устройств с низким уровнем заряда батареи',
258
+ pt: 'Lista de dispositivos com baixo estado da bateria',
259
+ nl: 'Lijst van apparaten met lage batterijstatus',
260
+ fr: 'Liste des appareils à faible état de batterie',
261
+ it: 'Elenco di dispositivi con stato di batteria basso',
262
+ es: 'Lista de dispositivos con estado de batería bajo',
263
+ pl: 'Lista urządzeń o niskim stanie baterii',
264
+ 'zh-cn': '低电量设备列表',
265
+ },
266
+ type: 'array',
267
+ role: 'json',
268
+ read: true,
269
+ write: false,
270
+ },
271
+ native: {},
272
+ });
273
+
274
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryCount`, {
275
+ type: 'state',
276
+ common: {
277
+ name: {
278
+ en: 'Number of devices with low battery',
279
+ de: 'Anzahl der Geräte mit niedriger Batterie',
280
+ ru: 'Количество устройств с низким зарядом батареи',
281
+ pt: 'Número de dispositivos com bateria baixa',
282
+ nl: 'Aantal apparaten met lage batterij',
283
+ fr: 'Nombre de dispositifs avec batterie faible',
284
+ it: 'Numero di dispositivi con batteria scarica',
285
+ es: 'Número de dispositivos con batería baja',
286
+ pl: 'Liczba urządzeń z niskim poziomem baterii',
287
+ 'zh-cn': '低电量设备的数量',
288
+ },
289
+ type: 'number',
290
+ role: 'value',
291
+ read: true,
292
+ write: false,
293
+ },
294
+ native: {},
295
+ });
296
+
297
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceLowBat`, {
298
+ type: 'state',
299
+ common: {
300
+ name: {
301
+ en: 'Is one device with low battery',
302
+ de: 'Ist ein Gerät mit niedrigem Akku',
303
+ ru: 'Есть ли устройство с низким зарядом батареи',
304
+ pt: 'É um dispositivo com bateria baixa',
305
+ nl: 'Is er een apparaat met lage batterij',
306
+ fr: 'Y a-t-il un appareil avec batterie faible',
307
+ it: "C'è un dispositivo con batteria scarica",
308
+ es: '¿Hay un dispositivo con batería baja?',
309
+ pl: 'Czy jest jedno urządzenie z niskim poziomem baterii',
310
+ uk: 'Чи є пристрій з низьким зарядом батареї',
311
+ 'zh-cn': '是否有设备电量低',
312
+ },
313
+ type: 'boolean',
314
+ role: 'state',
315
+ read: true,
316
+ write: false,
317
+ def: false,
318
+ },
319
+ native: {},
320
+ });
321
+
322
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.batteryCount`, {
323
+ type: 'state',
324
+ common: {
325
+ name: {
326
+ en: 'Number of devices with battery',
327
+ de: 'Anzahl der Geräte mit Batterie',
328
+ ru: 'Количество устройств с батареей',
329
+ pt: 'Número de dispositivos com bateria',
330
+ nl: 'Aantal apparaten met batterij',
331
+ fr: 'Nombre de dispositifs avec batterie',
332
+ it: 'Numero di dispositivi con batteria',
333
+ es: 'Número de dispositivos con batería',
334
+ pl: 'Liczba urządzeń z baterią',
335
+ 'zh-cn': '带电池的设备数量',
336
+ },
337
+ type: 'number',
338
+ role: 'value',
339
+ read: true,
340
+ write: false,
341
+ },
342
+ native: {},
343
+ });
344
+
345
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.upgradableCount`, {
346
+ type: 'state',
347
+ common: {
348
+ name: {
349
+ en: 'Number of devices with available updates',
350
+ de: 'Anzahl der Geräte mit verfügbaren Updates',
351
+ ru: 'Количество устройств с доступными обновлениями',
352
+ pt: 'Número de dispositivos com atualizações disponíveis',
353
+ nl: 'Aantal apparaten met beschikbare updates',
354
+ fr: 'Nombre de dispositifs avec mises à jour disponibles',
355
+ it: 'Numero di dispositivi con aggiornamenti disponibili',
356
+ es: 'Número de dispositivos con actualizações disponíveis',
357
+ pl: 'Liczba urządzeń z dostępnymi aktualizacjami',
358
+ uk: 'Кількість пристроїв з доступними оновленнями',
359
+ 'zh-cn': '具有可用更新的设备数量',
360
+ },
361
+ type: 'number',
362
+ role: 'value',
363
+ read: true,
364
+ write: false,
365
+ },
366
+ native: {},
367
+ });
368
+
369
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.upgradableList`, {
370
+ type: 'state',
371
+ common: {
372
+ name: {
373
+ en: 'JSON List of devices with available updates',
374
+ de: 'JSON Liste der Geräte mit verfügbaren Updates',
375
+ ru: 'JSON список устройств с доступными обновлениями',
376
+ pt: 'JSON Lista de dispositivos com atualizações disponíveis',
377
+ nl: 'JSON Lijst van apparaten met beschikbare updates',
378
+ fr: 'JSON Liste des appareils avec mises à jour disponibles',
379
+ it: 'JSON Elenco dei dispositivi con aggiornamenti disponibili',
380
+ es: 'JSON Lista de dispositivos con actualizaciones disponibles',
381
+ pl: 'JSON Lista urządzeń z dostępnymi aktualizacjami',
382
+ uk: 'JSON список пристроїв з доступними оновленнями',
383
+ 'zh-cn': '具有可用更新的设备的 JSON 列表',
384
+ },
385
+ type: 'array',
386
+ role: 'json',
387
+ read: true,
388
+ write: false,
389
+ },
390
+ native: {},
391
+ });
392
+
393
+ await adaptr.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceUpdatable`, {
394
+ type: 'state',
395
+ common: {
396
+ name: {
397
+ en: 'Is one device updatable',
398
+ de: 'Ist ein Gerät aktualisierbar',
399
+ ru: 'Можно ли обновить одно устройство',
400
+ pt: um dispositivo atualizável',
401
+ nl: 'Is er een apparaat dat kan worden bijgewerkt',
402
+ fr: 'Y a-t-il un appareil qui peut être mis à jour',
403
+ it: "C'è un dispositivo aggiornabile",
404
+ es: '¿Hay un dispositivo actualizable?',
405
+ pl: 'Czy jest jedno urządzenie do zaktualizowania',
406
+ uk: 'Чи є пристрій, який можна оновити',
407
+ 'zh-cn': '是否有设备可更新',
408
+ },
409
+ type: 'boolean',
410
+ role: 'state',
411
+ read: true,
412
+ write: false,
413
+ def: false,
414
+ },
415
+ native: {},
416
+ });
417
+ }
418
+
419
+ /**
420
+ * delete datapoints for each adapter
421
+ *
422
+ * @param {object} adaptr - ioBroker Adapter-Instanz
423
+ * @param {object} adptName - Adaptername of devices
424
+ */
425
+ async function deleteDPsForEachAdapter(adaptr, adptName) {
426
+ await adaptr.delObjectAsync(`devices.${adptName}`);
427
+ await adaptr.delObjectAsync(`devices.${adptName}.offlineCount`);
428
+ await adaptr.delObjectAsync(`devices.${adptName}.offlineList`);
429
+ await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
430
+ await adaptr.delObjectAsync(`devices.${adptName}.listAllRawJSON`);
431
+ await adaptr.delObjectAsync(`devices.${adptName}.listAll`);
432
+ await adaptr.delObjectAsync(`devices.${adptName}.linkQualityList`);
433
+ await adaptr.delObjectAsync(`devices.${adptName}.countAll`);
434
+ await adaptr.delObjectAsync(`devices.${adptName}.batteryList`);
435
+ await adaptr.delObjectAsync(`devices.${adptName}.lowBatteryList`);
436
+ await adaptr.delObjectAsync(`devices.${adptName}.lowBatteryCount`);
437
+ await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceLowBat`);
438
+ await adaptr.delObjectAsync(`devices.${adptName}.batteryCount`);
439
+ await adaptr.delObjectAsync(`devices.${adptName}.upgradableCount`);
440
+ await adaptr.delObjectAsync(`devices.${adptName}.upgradableList`);
441
+ await adaptr.delObjectAsync(`devices.${adptName}.oneDeviceUpdatable`);
442
+ }
443
+
444
+ /**
445
+ * create HTML list datapoints
446
+ *
447
+ * @param {object} adaptr - ioBroker Adapter-Instanz
448
+ * @param {object} [adptName] - Adaptername of devices
449
+ */
450
+ async function createHtmlListDatapoints(adaptr, adptName) {
451
+ let dpSubFolder;
452
+ //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
453
+ if (adptName) {
454
+ dpSubFolder = `${adptName}.`;
455
+ } else {
456
+ dpSubFolder = '';
457
+ }
458
+
459
+ await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}offlineListHTML`, {
460
+ type: 'state',
461
+ common: {
462
+ name: {
463
+ en: 'HTML List of offline devices',
464
+ de: 'HTML Liste der Offline-Geräte',
465
+ ru: 'HTML список оффлайн устройств',
466
+ pt: 'HTML Lista de dispositivos offline',
467
+ nl: 'HTML Lijst van offline apparaten',
468
+ fr: 'HTML Liste des dispositifs hors ligne',
469
+ it: 'HTML Elenco dei dispositivi offline',
470
+ es: 'HTML Lista de dispositivos sin conexión',
471
+ pl: 'HTML Lista urządzeń offline',
472
+ 'zh-cn': 'HTML 离线设备列表',
473
+ },
474
+ type: 'string',
475
+ role: 'html',
476
+ read: true,
477
+ write: false,
478
+ },
479
+ native: {},
480
+ });
481
+
482
+ await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
483
+ type: 'state',
484
+ common: {
485
+ name: {
486
+ en: 'HTML List of devices with signal strength',
487
+ de: 'HTML Liste der Geräte mit Signalstärke',
488
+ ru: 'HTML список устройств с уровнем сигнала',
489
+ pt: 'HTML Lista de dispositivos com força de sinal',
490
+ nl: 'HTML Lijst van apparaten met signaalkracht',
491
+ fr: 'HTML Liste des dispositifs avec force de signal',
492
+ it: 'HTML Elenco dei dispositivi con forza del segnale',
493
+ es: 'HTML Lista de dispositivos con fuerza de señal',
494
+ pl: 'HTML Lista urządzeń z siłą sygnału',
495
+ 'zh-cn': 'HTML 具有信号强度的设备列表',
496
+ },
497
+ type: 'string',
498
+ role: 'value',
499
+ read: true,
500
+ write: false,
501
+ },
502
+ native: {},
503
+ });
504
+
505
+ await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}batteryListHTML`, {
506
+ type: 'state',
507
+ common: {
508
+ name: {
509
+ en: 'HTML List of devices with battery state',
510
+ de: 'HTML Liste der Geräte mit Batteriezustand',
511
+ ru: 'HTML список устройств с состоянием батареи',
512
+ pt: 'HTML Lista de dispositivos com estado da bateria',
513
+ nl: 'HTML Lijst van apparaten met batterijstatus',
514
+ fr: 'HTML Liste des appareils avec état de batterie',
515
+ it: 'HTML Elenco dei dispositivi con stato della batteria',
516
+ es: 'HTML Lista de dispositivos con estado de batería',
517
+ pl: 'HTML Lista urządzeń ze stanem baterii',
518
+ 'zh-cn': 'HTML 具有电池状态的设备列表',
519
+ },
520
+ type: 'string',
521
+ role: 'html',
522
+ read: true,
523
+ write: false,
524
+ },
525
+ native: {},
526
+ });
527
+
528
+ await adaptr.setObjectNotExistsAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
529
+ type: 'state',
530
+ common: {
531
+ name: {
532
+ en: 'HTML List of devices with low battery state',
533
+ de: 'HTML Liste der Geräte mit niedrigem Batteriezustand',
534
+ ru: 'HTML список устройств с низким уровнем заряда батареи',
535
+ pt: 'HTML Lista de dispositivos com baixo estado da bateria',
536
+ nl: 'HTML Lijst van apparaten met lage batterijstatus',
537
+ fr: 'HTML Liste des appareils à faible état de batterie',
538
+ it: 'HTML Elenco di dispositivi con stato di batteria basso',
539
+ es: 'HTML Lista de dispositivos con estado de batería bajo',
540
+ pl: 'HTML Lista urządzeń o niskim stanie baterii',
541
+ 'zh-cn': 'HTML 低电量设备列表',
542
+ },
543
+ type: 'string',
544
+ role: 'html',
545
+ read: true,
546
+ write: false,
547
+ },
548
+ native: {},
549
+ });
550
+ }
551
+
552
+ /**
553
+ * delete html datapoints
554
+ *
555
+ * @param {object} adaptr - ioBroker Adapter-Instanz
556
+ * @param {object} [adptName] - Adaptername of devices
557
+ */
558
+ async function deleteHtmlListDatapoints(adaptr, adptName) {
559
+ // delete the datapoints in subfolders with the adaptername otherwise delete the dP's in the root folder
560
+ let dpSubFolder;
561
+ if (adptName) {
562
+ dpSubFolder = `${adptName}.`;
563
+ } else {
564
+ dpSubFolder = '';
565
+ }
566
+
567
+ await adaptr.delObjectAsync(`devices.${dpSubFolder}offlineListHTML`);
568
+ await adaptr.delObjectAsync(`devices.${dpSubFolder}linkQualityListHTML`);
569
+ await adaptr.delObjectAsync(`devices.${dpSubFolder}batteryListHTML`);
570
+ await adaptr.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
571
+ }
572
+
573
+ /**
574
+ * create HTML list datapoints for instances
575
+ *
576
+ * @param {object} adaptr - ioBroker Adapter-Instanz
577
+ */
578
+ async function createHtmlListDatapointsInstances(adaptr) {
579
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists`, {
580
+ type: 'channel',
581
+ common: {
582
+ name: {
583
+ en: 'HTML lists for adapter and instances',
584
+ de: 'HTML-Listen für Adapter und Instanzen',
585
+ ru: 'HTML списки для адаптера и экземпляров',
586
+ pt: 'Listas HTML para adaptador e instâncias',
587
+ nl: 'HTML lijsten voor adapter en instanties',
588
+ fr: "Listes HTML pour l'adaptateur et les instances",
589
+ it: 'Elenchi HTML per adattatore e istanze',
590
+ es: 'Listas HTML para adaptador e instancias',
591
+ pl: 'Listy HTML dla adaptera i instancji',
592
+ uk: 'HTML списки для адаптера та екземплярів',
593
+ 'zh-cn': '适配器和实例的 HTML 列表',
594
+ },
595
+ },
596
+ native: {},
597
+ });
598
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
599
+ type: 'state',
600
+ common: {
601
+ name: {
602
+ en: 'HTML List of all instances',
603
+ de: 'HTML Liste aller Instanzen',
604
+ ru: 'HTML список всех экземпляров',
605
+ pt: 'HTML Lista de todas as instâncias',
606
+ nl: 'HTML Lijst van alle instanties',
607
+ fr: 'HTML Liste de toutes les instances',
608
+ it: 'HTML Elenco di tutte le istanze',
609
+ es: 'HTML Lista de todas las instancias',
610
+ pl: 'HTML Lista wszystkich instancji',
611
+ uk: 'HTML список усіх інстанцій',
612
+ 'zh-cn': 'HTML 所有实例的列表',
613
+ },
614
+ type: 'string',
615
+ role: 'html',
616
+ read: true,
617
+ write: false,
618
+ },
619
+ native: {},
620
+ });
621
+
622
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
623
+ type: 'state',
624
+ common: {
625
+ name: {
626
+ en: 'HTML List of all active instances',
627
+ de: 'HTML Liste aller aktiven Instanzen',
628
+ ru: 'HTML список всех активных экземпляров',
629
+ pt: 'HTML Lista de todas as instâncias ativas',
630
+ nl: 'HTML Lijst van alle actieve instanties',
631
+ fr: 'HTML Liste de toutes les instances actives',
632
+ it: 'HTML Elenco di tutte le istanze attive',
633
+ es: 'HTML Lista de todas las instancias activas',
634
+ pl: 'HTML Lista wszystkich aktywnych instancji',
635
+ uk: 'HTML список усіх активних екземплярів',
636
+ 'zh-cn': 'HTML 所有活动实例的列表',
637
+ },
638
+ type: 'string',
639
+ role: 'value',
640
+ read: true,
641
+ write: false,
642
+ },
643
+ native: {},
644
+ });
645
+
646
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
647
+ type: 'state',
648
+ common: {
649
+ name: {
650
+ en: 'HTML List of all deactivated instances',
651
+ de: 'HTML Liste aller deaktivierten Instanzen',
652
+ ru: 'HTML список всех деактивированных экземпляров',
653
+ pt: 'HTML Lista de todas as instâncias desativadas',
654
+ nl: 'HTML Lijst van alle gedeactiveerde instanties',
655
+ fr: 'HTML Liste de toutes les instances désactivées',
656
+ it: 'HTML Elenco di tutte le istanze disattivate',
657
+ es: 'HTML Lista de todas las instancias desactivadas',
658
+ pl: 'HTML Lista wszystkich dezaktywowanych instancji',
659
+ uk: 'HTML список усіх деактивованих екземплярів',
660
+ 'zh-cn': 'HTML 所有已停用实例的列表',
661
+ },
662
+ type: 'string',
663
+ role: 'html',
664
+ read: true,
665
+ write: false,
666
+ },
667
+ native: {},
668
+ });
669
+
670
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
671
+ type: 'state',
672
+ common: {
673
+ name: {
674
+ en: 'HTML List of instances with error',
675
+ de: 'HTML Liste der Instanzen mit Fehler',
676
+ ru: 'HTML список экземпляров с ошибкой',
677
+ pt: 'HTML Lista de instâncias com erro',
678
+ nl: 'HTML Lijst van instanties met fouten',
679
+ fr: 'HTML Liste des instances avec erreur',
680
+ it: 'HTML Elenco delle istanze con errore',
681
+ es: 'HTML Lista de instancias con error',
682
+ pl: 'HTML Lista instancji z błędem',
683
+ uk: 'HTML список екземплярів з помилкою',
684
+ 'zh-cn': 'HTML 含错误实例的列表',
685
+ },
686
+ type: 'string',
687
+ role: 'html',
688
+ read: true,
689
+ write: false,
690
+ },
691
+ native: {},
692
+ });
693
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
694
+ type: 'state',
695
+ common: {
696
+ name: {
697
+ en: 'HTML list of adapters with available updates',
698
+ de: 'HTML-Liste der Adapter mit verfügbaren Updates',
699
+ ru: 'HTML список адаптеров с доступными обновлениями',
700
+ pt: 'Lista HTML de adaptadores com atualizações disponíveis',
701
+ nl: 'HTML lijst van adapters met beschikbare updates',
702
+ fr: 'Liste HTML des adaptateurs avec mises à jour disponibles',
703
+ it: 'Elenco HTML degli adattatori con aggiornamenti disponibili',
704
+ es: 'Lista HTML de adaptadores con actualizaciones disponibles',
705
+ pl: 'Lista adapterów HTML z dostępnymi aktualizacjami',
706
+ uk: 'HTML список адаптерів з доступними оновленнями',
707
+ 'zh-cn': 'HTML 具有可用更新的适配器列表',
708
+ },
709
+ type: 'string',
710
+ role: 'html',
711
+ read: true,
712
+ write: false,
713
+ },
714
+ native: {},
715
+ });
716
+ }
717
+
718
+ /**
719
+ * delete html datapoints for instances
720
+ *
721
+ * @param {object} adaptr - ioBroker Adapter-Instanz
722
+ */
723
+ async function deleteHtmlListDatapointsInstances(adaptr) {
724
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`);
725
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`);
726
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`);
727
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`);
728
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`);
729
+ await adaptr.delObjectAsync(`adapterAndInstances.HTML_Lists`);
730
+ }
731
+
732
+ /*=============================================
733
+ = functions to create html lists =
734
+ =============================================*/
735
+ /**
736
+ * @param {object} adaptr - ioBroker Adapter-Instanz
737
+ * @param {string} type - type of list
738
+ * @param {object} devices - Device
739
+ * @param {number} deviceCount - Counted devices
740
+ * @param {object} isLowBatteryList - list Low Battery Devices
741
+ */
742
+ async function createListHTML(adaptr, type, devices, deviceCount, isLowBatteryList) {
743
+ let html;
744
+ switch (type) {
745
+ case 'linkQualityList':
746
+ devices = devices.sort((a, b) => {
747
+ a = a.Device || '';
748
+ b = b.Device || '';
749
+ return a.localeCompare(b);
750
+ });
751
+ html = `<center>
752
+ <b>${[translations.Link_quality_devices[adaptr.config.userSelectedLanguage]]}:<font> ${deviceCount}</b><small></small></font>
753
+ <p></p>
754
+ </center>
755
+ <table width=100%>
756
+ <tr>
757
+ <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
758
+ <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
759
+ <th align=right>${[translations.Signal_strength[adaptr.config.userSelectedLanguage]]}</th>
760
+ </tr>
761
+ <tr>
762
+ <td colspan="5"><hr></td>
763
+ </tr>`;
764
+
765
+ for (const device of devices) {
766
+ html += `<tr>
767
+ <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
768
+ <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
769
+ <td align=right><font>${device[translations.Signal_strength[adaptr.config.userSelectedLanguage]]}</font></td>
770
+ </tr>`;
771
+ }
772
+
773
+ html += '</table>';
774
+ break;
775
+
776
+ case 'offlineList':
777
+ devices = devices.sort((a, b) => {
778
+ a = a.Device || '';
779
+ b = b.Device || '';
780
+ return a.localeCompare(b);
781
+ });
782
+ html = `<center>
783
+ <b>${[translations.offline_devices[adaptr.config.userSelectedLanguage]]}: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
784
+ <p></p>
785
+ </center>
786
+ <table width=100%>
787
+ <tr>
788
+ <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
789
+ <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
790
+ <th align=center>${[translations.Last_Contact[adaptr.config.userSelectedLanguage]]}</th>
791
+ </tr>
792
+ <tr>
793
+ <td colspan="5"><hr></td>
794
+ </tr>`;
795
+
796
+ for (const device of devices) {
797
+ html += `<tr>
798
+ <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
799
+ <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
800
+ <td align=center><font color=orange>${device[translations.Last_Contact[adaptr.config.userSelectedLanguage]]}</font></td>
801
+ </tr>`;
802
+ }
803
+
804
+ html += '</table>';
805
+ break;
806
+
807
+ case 'batteryList':
808
+ devices = devices.sort((a, b) => {
809
+ a = a.Device || '';
810
+ b = b.Device || '';
811
+ return a.localeCompare(b);
812
+ });
813
+ html = `<center>
814
+ <b>${isLowBatteryList === true ? `${[translations.low[adaptr.config.userSelectedLanguage]]} ` : ''}${[translations.battery_devices[adaptr.config.userSelectedLanguage]]}:
815
+ <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
816
+ <p></p>
817
+ </center>
818
+ <table width=100%>
819
+ <tr>
820
+ <th align=left>${[translations.Device[adaptr.config.userSelectedLanguage]]}</th>
821
+ <th align=center width=120>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
822
+ <th align=${isLowBatteryList ? 'center' : 'right'}>${[translations.Battery[adaptr.config.userSelectedLanguage]]}</th>
823
+ </tr>
824
+ <tr>
825
+ <td colspan="5"><hr></td>
826
+ </tr>`;
827
+ for (const device of devices) {
828
+ html += `<tr>
829
+ <td><font>${device[translations.Device[adaptr.config.userSelectedLanguage]]}</font></td>
830
+ <td align=center><font>${device[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>`;
831
+
832
+ if (isLowBatteryList) {
833
+ html += `<td align=center><font color=orange>${device[translations.Battery[adaptr.config.userSelectedLanguage]]}</font></td>`;
834
+ } else {
835
+ html += `<td align=right><font color=#3bcf0e>${device[translations.Battery[adaptr.config.userSelectedLanguage]]}</font></td>`;
836
+ }
837
+ html += `</tr>`;
838
+ }
839
+
840
+ html += '</table>';
841
+ break;
842
+ }
843
+ return html;
844
+ }
845
+
846
+ /**
847
+ * @param {object} adaptr - ioBroker Adapter-Instanz
848
+ * @param {string} type - type of list
849
+ * @param {object} instances - Instance
850
+ * @param {number} instancesCount - Counted devices
851
+ */
852
+ async function createListHTMLInstances(adaptr, type, instances, instancesCount) {
853
+ let html;
854
+ switch (type) {
855
+ case 'allInstancesList':
856
+ instances = instances.sort((a, b) => {
857
+ a = a.Instance || '';
858
+ b = b.Instance || '';
859
+ return a.localeCompare(b);
860
+ });
861
+ html = `<center>
862
+ <b>${[translations.All_Instances[adaptr.config.userSelectedLanguage]]}:<font> ${instancesCount}</b><small></small></font>
863
+ <p></p>
864
+ </center>
865
+ <table width=100%>
866
+ <tr>
867
+ <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
868
+ <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
869
+ <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
870
+ </tr>
871
+ <tr>
872
+ <td colspan="5"><hr></td>
873
+ </tr>`;
874
+
875
+ for (const instanceData of instances) {
876
+ html += `<tr>
877
+ <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
878
+ <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
879
+ <td align=center><font>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
880
+ </tr>`;
881
+ }
882
+
883
+ html += '</table>';
884
+ break;
885
+
886
+ case 'allActiveInstancesList':
887
+ instances = instances.sort((a, b) => {
888
+ a = a.Instance || '';
889
+ b = b.Instances || '';
890
+ return a.localeCompare(b);
891
+ });
892
+ html = `<center>
893
+ <b>${[translations.Active_Instances[adaptr.config.userSelectedLanguage]]}: <font> ${instancesCount}</b><small></small></font>
894
+ <p></p>
895
+ </center>
896
+ <table width=100%>
897
+ <tr>
898
+ <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
899
+ <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
900
+ <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
901
+ </tr>
902
+ <tr>
903
+ <td colspan="5"><hr></td>
904
+ </tr>`;
905
+
906
+ for (const instanceData of instances) {
907
+ html += `<tr>
908
+ <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
909
+ <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
910
+ <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
911
+ </tr>`;
912
+ }
913
+
914
+ html += '</table>';
915
+ break;
916
+
917
+ case 'errorInstanceList':
918
+ instances = instances.sort((a, b) => {
919
+ a = a.Instance || '';
920
+ b = b.Instances || '';
921
+ return a.localeCompare(b);
922
+ });
923
+ html = `<center>
924
+ <b>${[translations.Error_Instances[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
925
+ <p></p>
926
+ </center>
927
+ <table width=100%>
928
+ <tr>
929
+ <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
930
+ <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
931
+ <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
932
+ </tr>
933
+ <tr>
934
+ <td colspan="5"><hr></td>
935
+ </tr>`;
936
+
937
+ for (const instanceData of instances) {
938
+ html += `<tr>
939
+ <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
940
+ <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
941
+ <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
942
+ </tr>`;
943
+ }
944
+
945
+ html += '</table>';
946
+ break;
947
+
948
+ case 'deactivatedInstanceList':
949
+ instances = instances.sort((a, b) => {
950
+ a = a.Instance || '';
951
+ b = b.Instances || '';
952
+ return a.localeCompare(b);
953
+ });
954
+ html = `<center>
955
+ <b>${[translations.Deactivated_Instances[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
956
+ <p></p>
957
+ </center>
958
+ <table width=100%>
959
+ <tr>
960
+ <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
961
+ <th align=center>${[translations.Instance[adaptr.config.userSelectedLanguage]]}</th>
962
+ <th align=center width=180>${[translations.Status[adaptr.config.userSelectedLanguage]]}</th>
963
+ </tr>
964
+ <tr>
965
+ <td colspan="5"><hr></td>
966
+ </tr>`;
967
+
968
+ for (const instanceData of instances) {
969
+ if (!instanceData.isAlive) {
970
+ html += `<tr>
971
+ <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
972
+ <td align=center><font>${instanceData[translations.Instance[adaptr.config.userSelectedLanguage]]}</font></td>
973
+ <td align=center><font color=orange>${instanceData[translations.Status[adaptr.config.userSelectedLanguage]]}</font></td>
974
+ </tr>`;
975
+ }
976
+ }
977
+
978
+ html += '</table>';
979
+ break;
980
+
981
+ case 'updateAdapterList':
982
+ html = `<center>
983
+ <b>${[translations.Updatable_adapters[adaptr.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
984
+ <p></p>
985
+ </center>
986
+ <table width=100%>
987
+ <tr>
988
+ <th align=left>${[translations.Adapter[adaptr.config.userSelectedLanguage]]}</th>
989
+ <th align=center>${[translations.Installed_Version[adaptr.config.userSelectedLanguage]]}</th>
990
+ <th align=center>${[translations.Available_Version[adaptr.config.userSelectedLanguage]]}</th>
991
+ </tr>
992
+ <tr>
993
+ <td colspan="5"><hr></td>
994
+ </tr>`;
995
+
996
+ for (const instanceData of instances.values()) {
997
+ if (instanceData.updateAvailable !== ' - ') {
998
+ html += `<tr>
999
+ <td><font>${instanceData[translations.Adapter[adaptr.config.userSelectedLanguage]]}</font></td>
1000
+ <td align=center><font>${instanceData[translations.Installed_Version[adaptr.config.userSelectedLanguage]]}</font></td>
1001
+ <td align=center><font color=orange>${instanceData[translations.Available_Version[adaptr.config.userSelectedLanguage]]}</font></td>
1002
+ </tr>`;
1003
+ }
1004
+ }
1005
+
1006
+ html += '</table>';
1007
+ break;
1008
+ }
1009
+ return html;
1010
+ }
1011
+ /**
1012
+ * create blacklist
1013
+ *
1014
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1015
+ */
1016
+ async function createBlacklist(adaptr) {
1017
+ adaptr.log.debug(`Start the function createBlacklist`);
1018
+
1019
+ // DEVICES
1020
+ const myBlacklist = adaptr.config.tableBlacklist;
1021
+ if (myBlacklist.length >= 1) {
1022
+ for (const i in myBlacklist) {
1023
+ try {
1024
+ const blacklistParse = tools.parseData(myBlacklist[i].devices);
1025
+ // push devices in list to ignor device in lists
1026
+ if (myBlacklist[i].checkIgnorLists) {
1027
+ adaptr.blacklistLists.push(blacklistParse.path);
1028
+ }
1029
+ if (myBlacklist[i].checkIgnorAdapterLists) {
1030
+ adaptr.blacklistAdapterLists.push(blacklistParse.path);
1031
+ }
1032
+ // push devices in list to ignor device in notifications
1033
+ if (myBlacklist[i].checkIgnorNotify) {
1034
+ adaptr.blacklistNotify.push(blacklistParse.path);
1035
+ }
1036
+ } catch (error) {
1037
+ adaptr.log.error(`[createBlacklist] - ${error}`);
1038
+ }
1039
+ if (adaptr.blacklistLists.length >= 1) {
1040
+ adaptr.log.info(`Found devices/services on blacklist for lists: ${adaptr.blacklistLists}`);
1041
+ }
1042
+ if (adaptr.blacklistAdapterLists.length >= 1) {
1043
+ adaptr.log.info(`Found devices/services on blacklist for own adapter lists: ${adaptr.blacklistAdapterLists}`);
1044
+ }
1045
+ if (adaptr.blacklistNotify.length >= 1) {
1046
+ adaptr.log.info(`Found devices/services on blacklist for notifications: ${adaptr.blacklistNotify}`);
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ // INSTANCES
1052
+ const myBlacklistInstances = adaptr.config.tableBlacklistInstances;
1053
+ if (myBlacklistInstances.length >= 1) {
1054
+ for (const i in myBlacklistInstances) {
1055
+ try {
1056
+ const blacklistParse = tools.parseData(myBlacklistInstances[i].instances);
1057
+ // push devices in list to ignor device in lists
1058
+ if (myBlacklistInstances[i].checkIgnorLists) {
1059
+ adaptr.blacklistInstancesLists.push(blacklistParse.instanceID);
1060
+ }
1061
+ // push devices in list to ignor device in notifications
1062
+ if (myBlacklistInstances[i].checkIgnorNotify) {
1063
+ adaptr.blacklistInstancesNotify.push(blacklistParse.instanceID);
1064
+ }
1065
+ } catch (error) {
1066
+ adaptr.log.error(`[createBlacklist] - ${error}`);
1067
+ }
1068
+ }
1069
+ if (adaptr.blacklistInstancesLists.length >= 1) {
1070
+ adaptr.log.info(`Found instances items on blacklist for lists: ${adaptr.blacklistInstancesLists}`);
1071
+ }
1072
+ if (adaptr.blacklistInstancesNotify.length >= 1) {
1073
+ adaptr.log.info(`Found instances items on blacklist for notifications: ${adaptr.blacklistInstancesNotify}`);
1074
+ }
1075
+ }
1076
+ }
1077
+
1078
+ /**
1079
+ * create list with time for instances
1080
+ *
1081
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1082
+ */
1083
+ async function createTimeListInstances(adaptr) {
1084
+ // INSTANCES
1085
+ const userTimeListInstances = adaptr.config.tableTimeInstance;
1086
+
1087
+ if (userTimeListInstances.length >= 1) {
1088
+ for (const i in userTimeListInstances) {
1089
+ try {
1090
+ const userTimeListparse = tools.parseData(userTimeListInstances[i].instancesTime);
1091
+ // push devices in list to ignor device in lists
1092
+ adaptr.userTimeInstancesList.set(userTimeListparse.instanceName, {
1093
+ deactivationTime: userTimeListInstances[i].deactivationTime,
1094
+ errorTime: userTimeListInstances[i].errorTime,
1095
+ });
1096
+ } catch (error) {
1097
+ adaptr.log.error(`[createTimeListInstances] - ${error}`);
1098
+ }
1099
+ }
1100
+ if (adaptr.userTimeInstancesList.size >= 1) {
1101
+ adaptr.log.info(`Found instances items on lists for timesettings: ${Array.from(adaptr.userTimeInstancesList.keys())}`);
1102
+ }
1103
+ }
1104
+ }
1105
+
1106
+ /**
1107
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1108
+ * @param {object} i - Device Object
1109
+ */
1110
+ async function createData(adaptr, i) {
1111
+ try {
1112
+ const devices = await adaptr.getForeignStatesAsync(adaptr.selAdapter[i].selektor);
1113
+ const adapterID = adaptr.selAdapter[i].adapterID;
1114
+
1115
+ /*---------- Start of loop ----------*/
1116
+ for (const [id] of Object.entries(devices)) {
1117
+ if (id.endsWith('.')) {
1118
+ continue;
1119
+ }
1120
+
1121
+ // matter: nur matter.<inst>.controller.<nodeId>.info.connection zulassen
1122
+ if (adapterID === 'matter') {
1123
+ const parts = id.split('.');
1124
+ if (parts.length !== 6 || parts[2] !== 'controller' || parts[4] !== 'info' || parts[5] !== 'connection') {
1125
+ continue;
1126
+ }
1127
+ }
1128
+
1129
+ // zigbee2MQTT: Bridge/Coordinator/System-Objekte ausfiltern (kein echter Gerätepfad)
1130
+ if (adapterID === 'zigbee2MQTT') {
1131
+ const parts = id.split('.');
1132
+ // Pfad muss mindestens 4 Teile haben: zigbee2mqtt.0.<device>.<state>
1133
+ if (parts.length < 4) {
1134
+ continue;
1135
+ }
1136
+ // Bridge und System-Objekte ausschließen
1137
+ const deviceSegment = parts[2].toLowerCase();
1138
+ if (deviceSegment === 'bridge' || deviceSegment === 'coordinator' || deviceSegment === 'info' || deviceSegment === 'groups') {
1139
+ continue;
1140
+ }
1141
+ // Zigbee2MQTT Gruppen ausschließen: Gruppen haben native.type === 'group'
1142
+ // Gruppen liegen direkt auf Instanz-Ebene z.B. zigbee2mqtt.0.büro
1143
+ const currDevStr = id.slice(0, id.lastIndexOf('.'));
1144
+ const deviceObj = await adaptr.getForeignObjectAsync(currDevStr);
1145
+ if (deviceObj && deviceObj.native && deviceObj.native.type === 'group') {
1146
+ adaptr.log.debug(`[createData zigbee2MQTT] Skipping group (native.type): ${currDevStr}`);
1147
+ continue;
1148
+ }
1149
+ // Fallback: Gruppen haben weder last_seen noch link_quality → kein echtes Gerät
1150
+ const hasLastSeen = await tools.getInitValue(adaptr, `${currDevStr}.last_seen`);
1151
+ const hasLinkQuality = await tools.getInitValue(adaptr, `${currDevStr}.link_quality`);
1152
+ if (hasLastSeen === undefined && hasLinkQuality === undefined) {
1153
+ adaptr.log.debug(`[createData zigbee2MQTT] Skipping group (no last_seen/link_quality): ${currDevStr}`);
1154
+ continue;
1155
+ }
1156
+ }
1157
+
1158
+ const mainSelector = id;
1159
+
1160
+ /*=============================================
1161
+ = get Instanz =
1162
+ =============================================*/
1163
+ const instance = id.slice(0, id.indexOf('.') + 2);
1164
+
1165
+ let instanceDeviceConnectionDP = `${instance}.info.connection`;
1166
+ let instanceDeviceConnected = await tools.getInitValue(adaptr, instanceDeviceConnectionDP);
1167
+
1168
+ if (instanceDeviceConnected === undefined) {
1169
+ const sysAdmin = `system.adapter.${instanceDeviceConnectionDP.replace('info.connection', 'connected')}`;
1170
+ instanceDeviceConnectionDP = sysAdmin;
1171
+ instanceDeviceConnected = await tools.getInitValue(adaptr, sysAdmin);
1172
+ }
1173
+
1174
+ adaptr.subscribeForeignStates(instanceDeviceConnectionDP);
1175
+ adaptr.subscribeForeignObjects(`${adaptr.selAdapter[i].selektor}`);
1176
+
1177
+ const deviceName = await adaptr.getDeviceName(id, i);
1178
+
1179
+ const adapter = adaptr.selAdapter[i].adapter;
1180
+
1181
+ /*=============================================
1182
+ = Get path to datapoints =
1183
+ =============================================*/
1184
+ const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
1185
+ const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
1186
+
1187
+ // subscribe to object device path
1188
+ adaptr.subscribeForeignStates(currDeviceString);
1189
+
1190
+ /*=============================================
1191
+ = Get signal strength =
1192
+ =============================================*/
1193
+ let deviceQualityDP = currDeviceString + adaptr.selAdapter[i].rssiState;
1194
+ let deviceQualityState;
1195
+ let linkQuality;
1196
+ let linkQualityRaw;
1197
+
1198
+ if (!deviceQualityDP.includes('undefined')) {
1199
+ switch (adapterID) {
1200
+ case 'mihomeVacuum':
1201
+ deviceQualityDP = shortCurrDeviceString + adaptr.selAdapter[i].rssiState;
1202
+ deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1203
+ break;
1204
+
1205
+ case 'netatmo':
1206
+ deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1207
+ if (!deviceQualityState) {
1208
+ deviceQualityDP = currDeviceString + adaptr.selAdapter[i].rfState;
1209
+ deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1210
+ }
1211
+ break;
1212
+
1213
+ default:
1214
+ deviceQualityState = await adaptr.getForeignStateAsync(deviceQualityDP);
1215
+ }
1216
+ //subscribe to states
1217
+ adaptr.subscribeForeignStates(deviceQualityDP);
1218
+
1219
+ const signalData = await adaptr.calculateSignalStrength(deviceQualityState, adapterID);
1220
+ linkQuality = signalData[0];
1221
+ linkQualityRaw = signalData[1];
1222
+ }
1223
+
1224
+ /*=============================================
1225
+ = Get battery data =
1226
+ =============================================*/
1227
+ let deviceBatteryStateDP;
1228
+ let deviceBatteryState;
1229
+ let batteryHealth;
1230
+ let batteryHealthRaw;
1231
+ let batteryUnitRaw;
1232
+ let lowBatIndicator;
1233
+ let isBatteryDevice;
1234
+ let isLowBatDP;
1235
+ let faultReportingDP;
1236
+ let faultReportingState;
1237
+
1238
+ const deviceChargerStateDP = currDeviceString + adaptr.selAdapter[i].charger;
1239
+ const deviceChargerState = await tools.getInitValue(adaptr, deviceChargerStateDP);
1240
+
1241
+ if (deviceChargerState === undefined || deviceChargerState === false) {
1242
+ // Get battery states
1243
+ switch (adapterID) {
1244
+ case 'hmrpc':
1245
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1246
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1247
+
1248
+ if (deviceBatteryState === undefined) {
1249
+ deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].hmDNBattery;
1250
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1251
+ }
1252
+ break;
1253
+ case 'hueExt':
1254
+ // hue-extended: battery is at currDeviceString level (e.g. hue-extended.0.lights.1.config.battery)
1255
+ // NOT shortCurrDeviceString (which is the lights/sensors folder, e.g. hue-extended.0.lights)
1256
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1257
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1258
+
1259
+ if (deviceBatteryState === undefined) {
1260
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery2;
1261
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1262
+ }
1263
+ break;
1264
+ case 'mihomeVacuum':
1265
+ case 'mqttNuki':
1266
+ case 'loqedSmartLock':
1267
+ deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].battery;
1268
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1269
+
1270
+ if (deviceBatteryState === undefined) {
1271
+ deviceBatteryStateDP = shortCurrDeviceString + adaptr.selAdapter[i].battery2;
1272
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1273
+ }
1274
+ break;
1275
+ case 'homee': // only battery devices, structure problem like homee.0.*.BatteryLevel-964
1276
+ const devicePrefix = `${currDeviceString}.BatteryLevel-`;
1277
+ const listeDP = await adaptr.getObjectViewAsync('system', 'state', {
1278
+ startkey: `${devicePrefix}`,
1279
+ endkey: `${devicePrefix}\u9999`,
1280
+ });
1281
+
1282
+ if (listeDP.rows.length > 0) {
1283
+ deviceBatteryStateDP = listeDP.rows[0].id;
1284
+ }
1285
+
1286
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1287
+ break;
1288
+
1289
+ case 'matter': {
1290
+ // matter: Batterie liegt unter shortCurrDeviceString.PowerSource-N.BATTERY
1291
+ // N ist variabel -> dynamisch per getObjectViewAsync suchen
1292
+ const matterBattPrefix = `${shortCurrDeviceString}.PowerSource-`;
1293
+ const matterBattList = await adaptr.getObjectViewAsync('system', 'state', {
1294
+ startkey: `${matterBattPrefix}`,
1295
+ endkey: `${matterBattPrefix}\u9999`,
1296
+ });
1297
+ // ersten BATTERY-State nehmen
1298
+ const matterBattRow = matterBattList.rows.find((r) => r.id.endsWith('.BATTERY'));
1299
+ if (matterBattRow) {
1300
+ deviceBatteryStateDP = matterBattRow.id;
1301
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1302
+ }
1303
+ break;
1304
+ }
1305
+
1306
+ default:
1307
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery;
1308
+ if (adaptr.selAdapter[i].battery === 'none') {
1309
+ // adapter has no battery percentage DP (e.g. hmiP) – skip lookups
1310
+ deviceBatteryState = undefined;
1311
+ } else {
1312
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1313
+
1314
+ if (deviceBatteryState === undefined) {
1315
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery2;
1316
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1317
+
1318
+ if (deviceBatteryState === undefined) {
1319
+ deviceBatteryStateDP = currDeviceString + adaptr.selAdapter[i].battery3;
1320
+ deviceBatteryState = await tools.getInitValue(adaptr, deviceBatteryStateDP);
1321
+ }
1322
+ }
1323
+ }
1324
+ break;
1325
+ }
1326
+
1327
+ // Get low bat states
1328
+ isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat;
1329
+ let deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1330
+
1331
+ if (deviceLowBatState === undefined) {
1332
+ isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat2;
1333
+ deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1334
+
1335
+ if (deviceLowBatState === undefined) {
1336
+ isLowBatDP = currDeviceString + adaptr.selAdapter[i].isLowBat3;
1337
+ deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1338
+ }
1339
+ }
1340
+
1341
+ // matter: LOWBAT dynamisch über PowerSource-N.LOWBAT suchen
1342
+ if (adapterID === 'matter' && deviceLowBatState === undefined) {
1343
+ const matterLowBatPrefix = `${shortCurrDeviceString}.PowerSource-`;
1344
+ const matterLowBatList = await adaptr.getObjectViewAsync('system', 'state', {
1345
+ startkey: matterLowBatPrefix,
1346
+ endkey: `${matterLowBatPrefix}\u9999`,
1347
+ });
1348
+ const matterLowBatRow = matterLowBatList.rows.find((r) => r.id.endsWith('.LOWBAT'));
1349
+ if (matterLowBatRow) {
1350
+ isLowBatDP = matterLowBatRow.id;
1351
+ deviceLowBatState = await tools.getInitValue(adaptr, isLowBatDP);
1352
+ }
1353
+ }
1354
+
1355
+ if (deviceLowBatState === undefined) {
1356
+ isLowBatDP = 'none';
1357
+ }
1358
+
1359
+ faultReportingDP = shortCurrDeviceString + adaptr.selAdapter[i].faultReporting;
1360
+ faultReportingState = await tools.getInitValue(adaptr, faultReportingDP);
1361
+
1362
+ //subscribe to states
1363
+ if (!deviceBatteryStateDP.endsWith('undefined')) {
1364
+ adaptr.subscribeForeignStates(deviceBatteryStateDP);
1365
+ }
1366
+ if (!isLowBatDP.endsWith('undefined') && isLowBatDP !== 'none') {
1367
+ adaptr.subscribeForeignStates(isLowBatDP);
1368
+ }
1369
+ if (!faultReportingDP.endsWith('undefined')) {
1370
+ adaptr.subscribeForeignStates(faultReportingDP);
1371
+ }
1372
+
1373
+ const batteryData = await adaptr.getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
1374
+
1375
+ batteryHealth = batteryData[0];
1376
+ batteryHealthRaw = batteryData[2];
1377
+ batteryUnitRaw = batteryData[3];
1378
+ isBatteryDevice = batteryData[1];
1379
+
1380
+ if (isBatteryDevice) {
1381
+ lowBatIndicator = await adaptr.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
1382
+ }
1383
+ }
1384
+
1385
+ /*=============================================
1386
+ = Get last contact of device =
1387
+ =============================================*/
1388
+ let deviceStateSelectorHMRPC;
1389
+ let rssiPeerSelectorHMRPC;
1390
+
1391
+ // HMRPC
1392
+ if (adaptr.selAdapter[i].stateValue != undefined) {
1393
+ deviceStateSelectorHMRPC = shortCurrDeviceString + adaptr.selAdapter[i].stateValue;
1394
+ rssiPeerSelectorHMRPC = currDeviceString + adaptr.selAdapter[i].rssiPeerState;
1395
+ adaptr.subscribeForeignStates(deviceStateSelectorHMRPC);
1396
+ adaptr.subscribeForeignStates(rssiPeerSelectorHMRPC);
1397
+ }
1398
+
1399
+ let timeSelector = currDeviceString + adaptr.selAdapter[i].timeSelector;
1400
+ const timeSelectorState = await tools.getInitValue(adaptr, timeSelector);
1401
+
1402
+ if (timeSelectorState === undefined) {
1403
+ timeSelector = shortCurrDeviceString + adaptr.selAdapter[i].timeSelector;
1404
+ }
1405
+
1406
+ let unreachDP = currDeviceString + adaptr.selAdapter[i].reach;
1407
+
1408
+ let deviceUnreachState = await tools.getInitValue(adaptr, unreachDP);
1409
+
1410
+ if (deviceUnreachState === undefined) {
1411
+ unreachDP = shortCurrDeviceString + adaptr.selAdapter[i].reach;
1412
+ deviceUnreachState = await tools.getInitValue(adaptr, shortCurrDeviceString + adaptr.selAdapter[i].reach);
1413
+ }
1414
+
1415
+ // subscribe to states
1416
+ adaptr.subscribeForeignStates(timeSelector);
1417
+ adaptr.subscribeForeignStates(unreachDP);
1418
+
1419
+ const onlineState = await adaptr.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorHMRPC, rssiPeerSelectorHMRPC);
1420
+
1421
+ let deviceState;
1422
+ let lastContactString;
1423
+
1424
+ if (onlineState !== undefined && onlineState !== null) {
1425
+ lastContactString = onlineState[0];
1426
+ deviceState = onlineState[1];
1427
+ linkQuality = onlineState[2];
1428
+ }
1429
+
1430
+ /*=============================================
1431
+ = Get update data =
1432
+ =============================================*/
1433
+ let isUpgradable = ' - ';
1434
+ let deviceUpdateDP;
1435
+
1436
+ if (adaptr.config.checkSendDeviceUpgrade) {
1437
+ deviceUpdateDP = currDeviceString + adaptr.selAdapter[i].upgrade;
1438
+ let deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1439
+ if (deviceUpdateSelector === undefined) {
1440
+ deviceUpdateDP = shortCurrDeviceString + adaptr.selAdapter[i].upgrade;
1441
+ deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1442
+ if (deviceUpdateSelector === undefined) {
1443
+ const shortShortCurrDeviceString = shortCurrDeviceString.slice(0, shortCurrDeviceString.lastIndexOf('.') + 1 - 1);
1444
+ deviceUpdateDP = shortShortCurrDeviceString + adaptr.selAdapter[i].upgrade;
1445
+ deviceUpdateSelector = await tools.getInitValue(adaptr, deviceUpdateDP);
1446
+ }
1447
+ }
1448
+
1449
+ if (deviceUpdateSelector !== undefined) {
1450
+ isUpgradable = await adaptr.checkDeviceUpdate(adapterID, deviceUpdateSelector);
1451
+ }
1452
+
1453
+ if (!deviceUpdateDP.endsWith('undefined')) {
1454
+ if (!deviceUpdateDP.endsWith('none')) {
1455
+ if (!deviceUpdateDP.endsWith('null')) {
1456
+ adaptr.subscribeForeignStates(deviceUpdateDP);
1457
+ }
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ /*=============================================
1463
+ = Fill Raw Lists =
1464
+ =============================================*/
1465
+ const setupList = () => {
1466
+ adaptr.listAllDevicesRaw.set(currDeviceString, {
1467
+ Path: id,
1468
+ mainSelector: mainSelector,
1469
+ instanceDeviceConnectionDP: instanceDeviceConnectionDP,
1470
+ instanceDeviceConnected: instanceDeviceConnected,
1471
+ instance: instance,
1472
+ Device: deviceName,
1473
+ adapterID: adapterID,
1474
+ Adapter: adapter,
1475
+ timeSelector: timeSelector,
1476
+ isBatteryDevice: isBatteryDevice,
1477
+ Battery: batteryHealth,
1478
+ BatteryRaw: batteryHealthRaw,
1479
+ BatteryUnitRaw: batteryUnitRaw,
1480
+ batteryDP: deviceBatteryStateDP,
1481
+ LowBat: lowBatIndicator,
1482
+ LowBatDP: isLowBatDP,
1483
+ faultReport: faultReportingState,
1484
+ faultReportDP: faultReportingDP,
1485
+ SignalStrengthDP: deviceQualityDP,
1486
+ SignalStrength: linkQuality,
1487
+ SignalStrengthRaw: linkQualityRaw,
1488
+ UnreachState: deviceUnreachState,
1489
+ UnreachDP: unreachDP,
1490
+ deviceStateSelectorHMRPC: deviceStateSelectorHMRPC,
1491
+ rssiPeerSelectorHMRPC: rssiPeerSelectorHMRPC,
1492
+ LastContact: lastContactString,
1493
+ Status: deviceState,
1494
+ UpdateDP: deviceUpdateDP,
1495
+ Upgradable: isUpgradable,
1496
+ });
1497
+ };
1498
+
1499
+ if (!adaptr.configListOnlyBattery) {
1500
+ // Add all devices
1501
+ setupList();
1502
+ } else {
1503
+ // Add only devices with battery in the rawlist
1504
+ if (!isBatteryDevice) {
1505
+ continue;
1506
+ }
1507
+
1508
+ setupList();
1509
+ }
1510
+ } // <-- end of loop
1511
+ } catch (error) {
1512
+ adaptr.log.error(`[createData - create data of devices] - ${error}`);
1513
+ }
1514
+ } // <-- end of createData
1515
+
1516
+ /**
1517
+ * Create Lists
1518
+ *
1519
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1520
+ * @param {string | undefined} [adptName]
1521
+ */
1522
+ async function createLists(adaptr, adptName) {
1523
+ if (adptName !== undefined && adptName !== '') {
1524
+ // ── Schneller Pfad: nur Adapter-Unterordner ──────────────────────────────
1525
+ // Root-Listen werden NICHT resettet – das würde adaptr.deviceCounter etc.
1526
+ // korrumpieren und Race Conditions mit refreshData/main() verursachen.
1527
+ const tmpLinkQuality = [];
1528
+ const tmpBattery = [];
1529
+ const tmpLowBattery = [];
1530
+ const tmpUserRaw = [];
1531
+ const tmpAllDevices = [];
1532
+ const tmpOffline = [];
1533
+ const tmpUpgradable = [];
1534
+
1535
+ const orig = {
1536
+ linkQualityDevices: adaptr.linkQualityDevices,
1537
+ batteryPowered: adaptr.batteryPowered,
1538
+ batteryLowPowered: adaptr.batteryLowPowered,
1539
+ listAllDevicesUserRaw: adaptr.listAllDevicesUserRaw,
1540
+ listAllDevices: adaptr.listAllDevices,
1541
+ offlineDevices: adaptr.offlineDevices,
1542
+ upgradableList: adaptr.upgradableList,
1543
+ };
1544
+
1545
+ adaptr.linkQualityDevices = tmpLinkQuality;
1546
+ adaptr.batteryPowered = tmpBattery;
1547
+ adaptr.batteryLowPowered = tmpLowBattery;
1548
+ adaptr.listAllDevicesUserRaw = tmpUserRaw;
1549
+ adaptr.listAllDevices = tmpAllDevices;
1550
+ adaptr.offlineDevices = tmpOffline;
1551
+ adaptr.upgradableList = tmpUpgradable;
1552
+
1553
+ for (const deviceData of adaptr.listAllDevicesRaw.values()) {
1554
+ if (deviceData.adapterID !== adptName) {
1555
+ continue;
1556
+ }
1557
+ if (adaptr.blacklistAdapterLists.includes(deviceData.Path)) {
1558
+ continue;
1559
+ }
1560
+ await adaptr.theLists(deviceData);
1561
+ }
1562
+
1563
+ await tools.countDevices(adaptr);
1564
+
1565
+ // Root-Listen wiederherstellen
1566
+ adaptr.linkQualityDevices = orig.linkQualityDevices;
1567
+ adaptr.batteryPowered = orig.batteryPowered;
1568
+ adaptr.batteryLowPowered = orig.batteryLowPowered;
1569
+ adaptr.listAllDevicesUserRaw = orig.listAllDevicesUserRaw;
1570
+ adaptr.listAllDevices = orig.listAllDevices;
1571
+ adaptr.offlineDevices = orig.offlineDevices;
1572
+ adaptr.upgradableList = orig.upgradableList;
1573
+
1574
+ adaptr._adapterLists = adaptr._adapterLists || {};
1575
+ adaptr._adapterLists[adptName] = {
1576
+ linkQualityDevices: tmpLinkQuality,
1577
+ batteryPowered: tmpBattery,
1578
+ batteryLowPowered: tmpLowBattery,
1579
+ listAllDevicesUserRaw: tmpUserRaw,
1580
+ listAllDevices: tmpAllDevices,
1581
+ offlineDevices: tmpOffline,
1582
+ upgradableList: tmpUpgradable,
1583
+ linkQualityCount: tmpLinkQuality.length,
1584
+ offlineDevicesCount: tmpOffline.length,
1585
+ batteryPoweredCount: tmpBattery.length,
1586
+ lowBatteryPoweredCount: tmpLowBattery.length,
1587
+ deviceCounter: tmpAllDevices.length,
1588
+ upgradableDevicesCount: tmpUpgradable.length,
1589
+ };
1590
+ } else {
1591
+ // ── Vollständiger Durchlauf: Root-Listen ─────────────────────────────────
1592
+ adaptr.linkQualityDevices = [];
1593
+ adaptr.batteryPowered = [];
1594
+ adaptr.batteryLowPowered = [];
1595
+ adaptr.listAllDevicesUserRaw = [];
1596
+ adaptr.listAllDevices = [];
1597
+ adaptr.offlineDevices = [];
1598
+ adaptr.batteryLowPoweredRaw = [];
1599
+ adaptr.offlineDevicesRaw = [];
1600
+ adaptr.upgradableDevicesRaw = [];
1601
+ adaptr.upgradableList = [];
1602
+
1603
+ for (const deviceData of adaptr.listAllDevicesRaw.values()) {
1604
+ if (deviceData.LowBat && deviceData.Status !== 'Offline') {
1605
+ adaptr.batteryLowPoweredRaw.push({ Path: deviceData.Path, Device: deviceData.Device, Adapter: deviceData.Adapter, Battery: deviceData.Battery });
1606
+ }
1607
+ if (deviceData.Status === 'Offline') {
1608
+ adaptr.offlineDevicesRaw.push({ Path: deviceData.Path, Device: deviceData.Device, Adapter: deviceData.Adapter, LastContact: deviceData.LastContact });
1609
+ }
1610
+ if (deviceData.Upgradable === true) {
1611
+ adaptr.upgradableDevicesRaw.push({ Path: deviceData.Path, Device: deviceData.Device, Adapter: deviceData.Adapter });
1612
+ }
1613
+ if (!adaptr.blacklistLists.includes(deviceData.Path)) {
1614
+ await adaptr.theLists(deviceData);
1615
+ }
1616
+ }
1617
+
1618
+ await tools.countDevices(adaptr);
1619
+ }
1620
+ }
1621
+
1622
+ /**
1623
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1624
+ * @param {string} [adptName] - Adaptername
1625
+ */
1626
+ async function writeDatapoints(adaptr, adptName) {
1627
+ adaptr.log.debug(`Start the function writeDatapoints`);
1628
+
1629
+ try {
1630
+ const dpSubFolder = adptName ? `${adptName}.` : '';
1631
+ const lang = adaptr.config.userSelectedLanguage || 'en';
1632
+ const tDevice = translations.Device[lang] || translations.Device['en'];
1633
+ const tAdapter = translations.Adapter[lang] || translations.Adapter['en'];
1634
+ const tBattery = translations.Battery[lang] || translations.Battery['en'];
1635
+ const tSignal = translations.Signal_strength[lang] || translations.Signal_strength['en'];
1636
+ const tContact = translations.Last_Contact[lang] || translations.Last_Contact['en'];
1637
+ const tStatus = translations.Status[lang] || translations.Status['en'];
1638
+
1639
+ let lists;
1640
+ if (adptName && adaptr._adapterLists && adaptr._adapterLists[adptName]) {
1641
+ lists = adaptr._adapterLists[adptName];
1642
+ } else {
1643
+ lists = {
1644
+ linkQualityDevices: adaptr.linkQualityDevices,
1645
+ batteryPowered: adaptr.batteryPowered,
1646
+ batteryLowPowered: adaptr.batteryLowPowered,
1647
+ listAllDevicesUserRaw: adaptr.listAllDevicesUserRaw,
1648
+ listAllDevices: adaptr.listAllDevices,
1649
+ offlineDevices: adaptr.offlineDevices,
1650
+ upgradableList: adaptr.upgradableList,
1651
+ linkQualityCount: adaptr.linkQualityCount,
1652
+ offlineDevicesCount: adaptr.offlineDevicesCount,
1653
+ batteryPoweredCount: adaptr.batteryPoweredCount,
1654
+ lowBatteryPoweredCount: adaptr.lowBatteryPoweredCount,
1655
+ deviceCounter: adaptr.deviceCounter,
1656
+ upgradableDevicesCount: adaptr.upgradableDevicesCount,
1657
+ };
1658
+ }
1659
+
1660
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}offlineCount`, lists.offlineDevicesCount);
1661
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}countAll`, lists.deviceCounter);
1662
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}batteryCount`, lists.batteryPoweredCount);
1663
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}lowBatteryCount`, lists.lowBatteryPoweredCount);
1664
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}upgradableCount`, lists.upgradableDevicesCount);
1665
+
1666
+ let listAllDevices = lists.listAllDevices;
1667
+ let listAllDevicesUserRaw = lists.listAllDevicesUserRaw;
1668
+ if (lists.deviceCounter === 0) {
1669
+ listAllDevices = [{ [tDevice]: '--none--', [tAdapter]: '', [tBattery]: '', [tSignal]: '', [tContact]: '', [tStatus]: '' }];
1670
+ listAllDevicesUserRaw = [{ Device: '--none--', Adapter: '', Instance: '', 'Instance connected': '', isBatteryDevice: '', Battery: '', BatteryRaw: '', isLowBat: '', 'Signal strength': '', 'Last contact': '', UpdateAvailable: '', Status: '' }];
1671
+ }
1672
+ const listAllJson = JSON.stringify(listAllDevices);
1673
+ const listAllRawJson = JSON.stringify(listAllDevicesUserRaw);
1674
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}listAll`, listAllJson, serializeForCache(listAllJson));
1675
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}listAllRawJSON`, listAllRawJson, serializeForCache(listAllRawJson));
1676
+
1677
+ let linkQualityDevices = lists.linkQualityDevices;
1678
+ if (lists.linkQualityCount === 0) {
1679
+ linkQualityDevices = [{ [tDevice]: '--none--', [tAdapter]: '', [tSignal]: '' }];
1680
+ }
1681
+ const lqJson = JSON.stringify(linkQualityDevices);
1682
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}linkQualityList`, lqJson, serializeForCache(lqJson));
1683
+
1684
+ let offlineDevices = lists.offlineDevices;
1685
+ if (lists.offlineDevicesCount === 0) {
1686
+ offlineDevices = [{ [tDevice]: '--none--', [tAdapter]: '', [tContact]: '' }];
1687
+ }
1688
+ const offlineJson = JSON.stringify(offlineDevices);
1689
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}offlineList`, offlineJson, serializeForCache(offlineJson));
1690
+
1691
+ let upgradableList = lists.upgradableList;
1692
+ if (lists.upgradableDevicesCount === 0) {
1693
+ upgradableList = [{ [tDevice]: '--none--', [tAdapter]: '', [tContact]: '' }];
1694
+ }
1695
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}upgradableList`, JSON.stringify(upgradableList));
1696
+
1697
+ let batteryPowered = lists.batteryPowered;
1698
+ if (lists.batteryPoweredCount === 0) {
1699
+ batteryPowered = [{ [tDevice]: '--none--', [tAdapter]: '', [tBattery]: '' }];
1700
+ }
1701
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}batteryList`, JSON.stringify(batteryPowered));
1702
+
1703
+ let batteryLowPowered = lists.batteryLowPowered;
1704
+ if (lists.lowBatteryPoweredCount === 0) {
1705
+ batteryLowPowered = [{ [tDevice]: '--none--', [tAdapter]: '', [tBattery]: '' }];
1706
+ }
1707
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}lowBatteryList`, JSON.stringify(batteryLowPowered));
1708
+
1709
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}oneDeviceOffline`, lists.offlineDevicesCount > 0);
1710
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}oneDeviceLowBat`, lists.lowBatteryPoweredCount > 0);
1711
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}oneDeviceUpdatable`, lists.upgradableDevicesCount > 0);
1712
+
1713
+ if (adaptr.configCreateHtmlList) {
1714
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}linkQualityListHTML`,
1715
+ await createListHTML(adaptr, 'linkQualityList', linkQualityDevices, lists.linkQualityCount, null));
1716
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}offlineListHTML`,
1717
+ await createListHTML(adaptr, 'offlineList', offlineDevices, lists.offlineDevicesCount, null));
1718
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}batteryListHTML`,
1719
+ await createListHTML(adaptr, 'batteryList', batteryPowered, lists.batteryPoweredCount, false));
1720
+ await setStateIfChanged(adaptr, `devices.${dpSubFolder}lowBatteryListHTML`,
1721
+ await createListHTML(adaptr, 'batteryList', batteryLowPowered, lists.lowBatteryPoweredCount, true));
1722
+
1723
+ if (adaptr.config.checkAdapterInstances) {
1724
+ await setStateIfChanged(adaptr, `adapterAndInstances.HTML_Lists.listAllInstancesHTML`,
1725
+ await createListHTMLInstances(adaptr, 'allInstancesList', adaptr.listAllInstances, adaptr.countAllInstances));
1726
+ await setStateIfChanged(adaptr, `adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`,
1727
+ await createListHTMLInstances(adaptr, 'allActiveInstancesList', adaptr.listAllActiveInstances, adaptr.countAllActiveInstances));
1728
+ await setStateIfChanged(adaptr, `adapterAndInstances.HTML_Lists.listInstancesErrorHTML`,
1729
+ await createListHTMLInstances(adaptr, 'errorInstanceList', adaptr.listErrorInstance, adaptr.countErrorInstance));
1730
+ await setStateIfChanged(adaptr, `adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`,
1731
+ await createListHTMLInstances(adaptr, 'deactivatedInstanceList', adaptr.listDeactivatedInstances, adaptr.countDeactivatedInstances));
1732
+ await setStateIfChanged(adaptr, `adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`,
1733
+ await createListHTMLInstances(adaptr, 'updateAdapterList', adaptr.listAdapterUpdates, adaptr.countAdapterUpdates));
1734
+ }
1735
+ }
1736
+
1737
+ const lastCheck = `${adaptr.formatDate(new Date(), 'DD.MM.YYYY')} - ${adaptr.formatDate(new Date(), 'hh:mm:ss')}`;
1738
+ await adaptr.setStateChangedAsync('lastCheck', lastCheck, true);
1739
+ } catch (error) {
1740
+ adaptr.log.error(`[writeDatapoints] - ${error}`);
1741
+ }
1742
+ } //<--End of writing Datapoints
1743
+
1744
+ /**
1745
+ * create Datapoints for Instances
1746
+ *
1747
+ * @param {object} adaptr - ioBroker Adapter-Instanz
1748
+ */
1749
+ async function createDPsForInstances(adaptr) {
1750
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances`, {
1751
+ type: 'channel',
1752
+ common: {
1753
+ name: {
1754
+ en: 'Adapter and Instances',
1755
+ de: 'Adapter und Instanzen',
1756
+ ru: 'Адаптер и экземпляры',
1757
+ pt: 'Adaptador e Instâncias',
1758
+ nl: 'Adapter en Instanties',
1759
+ fr: 'Adaptateur et instances',
1760
+ it: 'Adattatore e istanze',
1761
+ es: 'Adaptador e instancias',
1762
+ pl: 'Adapter i Instancje',
1763
+ uk: 'Адаптер та його екземпляри',
1764
+ 'zh-cn': '适配器和实例',
1765
+ },
1766
+ },
1767
+ native: {},
1768
+ });
1769
+
1770
+ // Instances
1771
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAllInstances`, {
1772
+ type: 'state',
1773
+ common: {
1774
+ name: {
1775
+ en: 'JSON List of all instances',
1776
+ de: 'JSON-Liste aller Instanzen',
1777
+ ru: 'JSON-список всех экземпляров',
1778
+ pt: 'Lista JSON de todas as instâncias',
1779
+ nl: 'JSON-lijst van alle instanties',
1780
+ fr: 'Liste JSON de toutes les instances',
1781
+ it: 'Elenco JSON di tutte le istanze',
1782
+ es: 'Lista JSON de todas las instancias',
1783
+ pl: 'Lista JSON wszystkich instancji',
1784
+ uk: 'JSON-список всіх інстанцій',
1785
+ 'zh-cn': '所有实例的JSON列表',
1786
+ },
1787
+ type: 'array',
1788
+ role: 'json',
1789
+ read: true,
1790
+ write: false,
1791
+ },
1792
+ native: {},
1793
+ });
1794
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAllInstances`, {
1795
+ type: 'state',
1796
+ common: {
1797
+ name: {
1798
+ en: 'Number of all instances',
1799
+ de: 'Anzahl aller Instanzen',
1800
+ ru: 'Количество всех экземпляров',
1801
+ pt: 'Número de todas as instâncias',
1802
+ nl: 'Aantal van alle instanties',
1803
+ fr: 'Nombre de toutes les instances',
1804
+ it: 'Numero di tutte le istanze',
1805
+ es: 'Número de todas las instancias',
1806
+ pl: 'Liczba wszystkich instancji',
1807
+ uk: 'Кількість усіх інстанцій',
1808
+ 'zh-cn': '所有实例的数量',
1809
+ },
1810
+ type: 'number',
1811
+ role: 'value',
1812
+ read: true,
1813
+ write: false,
1814
+ },
1815
+ native: {},
1816
+ });
1817
+ // Instances
1818
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAllActiveInstances`, {
1819
+ type: 'state',
1820
+ common: {
1821
+ name: {
1822
+ en: 'JSON List of all active instances',
1823
+ de: 'JSON-Liste aller aktiven Instanzen',
1824
+ ru: 'JSON список всех активных экземпляров',
1825
+ pt: 'Lista JSON de todas as instâncias ativas',
1826
+ nl: 'JSON-lijst van alle actieve instanties',
1827
+ fr: 'Liste JSON de toutes les instances actives',
1828
+ it: 'Elenco JSON di tutte le istanze attive',
1829
+ es: 'Lista JSON de todas las instancias activas',
1830
+ pl: 'JSON lista wszystkich aktywnych instancji',
1831
+ uk: 'JSON список усіх активних екземплярів',
1832
+ 'zh-cn': 'HTML 所有活动实例的列表',
1833
+ },
1834
+ type: 'array',
1835
+ role: 'json',
1836
+ read: true,
1837
+ write: false,
1838
+ },
1839
+ native: {},
1840
+ });
1841
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAllActiveInstances`, {
1842
+ type: 'state',
1843
+ common: {
1844
+ name: {
1845
+ en: 'Number of all active instances',
1846
+ de: 'Anzahl aller aktiven Instanzen',
1847
+ ru: 'Количество всех активных экземпляров',
1848
+ pt: 'Número de todas as instâncias ativas',
1849
+ nl: 'Aantal van alle actieve instanties',
1850
+ fr: 'Nombre de toutes les instances actives',
1851
+ it: 'Numero di tutte le istanze attive',
1852
+ es: 'Número de todas las instancias activas',
1853
+ pl: 'Liczba wszystkich aktywnych instancji',
1854
+ uk: 'Кількість усіх активних екземплярів',
1855
+ 'zh-cn': '所有活动实例的数量',
1856
+ },
1857
+ type: 'number',
1858
+ role: 'value',
1859
+ read: true,
1860
+ write: false,
1861
+ },
1862
+ native: {},
1863
+ });
1864
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listDeactivatedInstances`, {
1865
+ type: 'state',
1866
+ common: {
1867
+ name: {
1868
+ en: 'JSON List of deactivated instances',
1869
+ de: 'JSON-Liste der deaktivierten Instanzen',
1870
+ ru: 'JSON список деактивированных экземпляров',
1871
+ pt: 'JSON Lista de instâncias desativadas',
1872
+ nl: 'JSON-lijst van gedeactiveerde instanties',
1873
+ fr: 'Liste JSON des instances désactivées',
1874
+ it: 'JSON Elenco delle istanze disattivate',
1875
+ es: 'Lista JSON de instancias desactivadas',
1876
+ pl: 'JSON lista dezaktywowanych instancji',
1877
+ uk: 'JSON список деактивованих екземплярів',
1878
+ 'zh-cn': '已停用实例的 JSON 列表',
1879
+ },
1880
+ type: 'array',
1881
+ role: 'json',
1882
+ read: true,
1883
+ write: false,
1884
+ },
1885
+ native: {},
1886
+ });
1887
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countDeactivatedInstances`, {
1888
+ type: 'state',
1889
+ common: {
1890
+ name: {
1891
+ en: 'Number of deactivated instances',
1892
+ de: 'Anzahl deaktivierter Instanzen',
1893
+ ru: 'Количество деактивированных экземпляров',
1894
+ pt: 'Número de instâncias desativadas',
1895
+ nl: 'Aantal gedeactiveerde instanties',
1896
+ fr: "Nombre d'instances désactivées",
1897
+ it: 'Numero di istanze disattivate',
1898
+ es: 'Número de instancias desactivadas',
1899
+ pl: 'Liczba deaktywowanych instancji',
1900
+ uk: 'Кількість деактивованих екземплярів',
1901
+ 'zh-cn': '已停用实例的数量',
1902
+ },
1903
+ type: 'number',
1904
+ role: 'value',
1905
+ read: true,
1906
+ write: false,
1907
+ },
1908
+ native: {},
1909
+ });
1910
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listInstancesError`, {
1911
+ type: 'state',
1912
+ common: {
1913
+ name: {
1914
+ en: 'JSON list of instances with error',
1915
+ de: 'JSON-Liste von Instanzen mit Fehler',
1916
+ ru: 'JSON список экземпляров с ошибкой',
1917
+ pt: 'Lista de instâncias JSON com erro',
1918
+ nl: 'JSON lijst met fouten',
1919
+ fr: 'Liste des instances avec erreur',
1920
+ it: 'Elenco JSON delle istanze con errore',
1921
+ es: 'JSON lista de casos con error',
1922
+ pl: 'JSON lista instancji z błędem',
1923
+ uk: 'JSON список інстанцій з помилкою',
1924
+ 'zh-cn': '含错误实例的 JSON 列表',
1925
+ },
1926
+ type: 'array',
1927
+ role: 'json',
1928
+ read: true,
1929
+ write: false,
1930
+ },
1931
+ native: {},
1932
+ });
1933
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countInstancesError`, {
1934
+ type: 'state',
1935
+ common: {
1936
+ name: {
1937
+ en: 'Count of instances with error',
1938
+ de: 'Anzahl der Instanzen mit Fehler',
1939
+ ru: 'Количество экземпляров с ошибкой',
1940
+ pt: 'Contagem de instâncias com erro',
1941
+ nl: 'Aantal instanties met fouten',
1942
+ fr: "Nombre d'instances avec erreur",
1943
+ it: 'Conteggio delle istanze con errore',
1944
+ es: 'Recuento de instancias con error',
1945
+ pl: 'Liczba instancji z błędem',
1946
+ uk: 'Кількість інстанцій з помилкою',
1947
+ 'zh-cn': '出错实例的数量',
1948
+ },
1949
+ type: 'number',
1950
+ role: 'value',
1951
+ read: true,
1952
+ write: false,
1953
+ },
1954
+ native: {},
1955
+ });
1956
+
1957
+ // Adapter
1958
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.listAdapterUpdates`, {
1959
+ type: 'state',
1960
+ common: {
1961
+ name: {
1962
+ en: 'JSON list of adapters with available updates',
1963
+ de: 'JSON-Liste der Adapter mit verfügbaren Updates',
1964
+ ru: 'JSON список адаптеров с доступными обновлениями',
1965
+ pt: 'Lista de adaptadores JSON com atualizações disponíveis',
1966
+ nl: 'JSON lijst van adapters met beschikbare updates',
1967
+ fr: 'Liste JSON des adaptateurs avec mises à jour disponibles',
1968
+ it: 'Elenco JSON degli adattatori con aggiornamenti disponibili',
1969
+ es: 'JSON lista de adaptadores con actualizaciones disponibles',
1970
+ pl: 'JSON lista adapterów z dostępnymi aktualizacjami',
1971
+ uk: 'JSON список адаптерів з доступними оновленнями',
1972
+ 'zh-cn': '具有可用更新的适配器的 JSON 列表',
1973
+ },
1974
+ type: 'array',
1975
+ role: 'json',
1976
+ read: true,
1977
+ write: false,
1978
+ },
1979
+ native: {},
1980
+ });
1981
+ await adaptr.setObjectNotExistsAsync(`adapterAndInstances.countAdapterUpdates`, {
1982
+ type: 'state',
1983
+ common: {
1984
+ name: {
1985
+ en: 'Number of adapters with available updates',
1986
+ de: 'Anzahl der Adapter mit verfügbaren Updates',
1987
+ ru: 'Количество адаптеров с доступными обновлениями',
1988
+ pt: 'Número de adaptadores com atualizações disponíveis',
1989
+ nl: 'Aantal adapters com disponível updates',
1990
+ fr: "Nombre d'adaptateurs avec mises à jour disponibles",
1991
+ it: 'Numero di adattatori con aggiornamenti disponibili',
1992
+ es: 'Número de adaptadores con actualizaciones disponibles',
1993
+ pl: 'Liczba adapterów z dostępnymi aktualizacjami',
1994
+ uk: 'Кількість адаптерів з доступними оновленнями',
1995
+ 'zh-cn': '具有可用更新的适配器数量',
1996
+ },
1997
+ type: 'number',
1998
+ role: 'value',
1999
+ read: true,
2000
+ write: false,
2001
+ },
2002
+ native: {},
2003
+ });
2004
+ }
2005
+
2006
+ /**
2007
+ * delete Datapoints for Instances
2008
+ *
2009
+ * @param {object} adaptr - ioBroker Adapter-Instanz
2010
+ */
2011
+ async function deleteDPsForInstances(adaptr) {
2012
+ await adaptr.delObjectAsync(`adapterAndInstances`);
2013
+ await adaptr.delObjectAsync(`adapterAndInstances.listAllInstances`);
2014
+ await adaptr.delObjectAsync(`adapterAndInstances.countAllInstances`);
2015
+ await adaptr.delObjectAsync(`adapterAndInstances.listAllActiveInstances`);
2016
+ await adaptr.delObjectAsync(`adapterAndInstances.countAllActiveInstances`);
2017
+ await adaptr.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
2018
+ await adaptr.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
2019
+ await adaptr.delObjectAsync(`adapterAndInstances.listInstancesError`);
2020
+ await adaptr.delObjectAsync(`adapterAndInstances.countInstancesError`);
2021
+ await adaptr.delObjectAsync(`adapterAndInstances.listAdapterUpdates`);
2022
+ await adaptr.delObjectAsync(`adapterAndInstances.countAdapterUpdates`);
2023
+ }
2024
+
2025
+ /**
2026
+ * create adapter update data
2027
+ *
2028
+ * @param {object} adaptr - ioBroker Adapter-Instanz
2029
+ * @param adapterUpdateListDP
2030
+ */
2031
+ async function createAdapterUpdateData(adaptr, adapterUpdateListDP) {
2032
+ // subscribe to datapoint
2033
+ adaptr.subscribeForeignStates(adapterUpdateListDP);
2034
+
2035
+ await adaptr.getAdapterUpdateData(adapterUpdateListDP);
2036
+
2037
+ await adaptr.createAdapterUpdateList();
2038
+ }
2039
+
2040
+ module.exports = {
2041
+ createDPsForEachAdapter,
2042
+ deleteDPsForEachAdapter,
2043
+ createHtmlListDatapoints,
2044
+ deleteHtmlListDatapoints,
2045
+ createHtmlListDatapointsInstances,
2046
+ deleteHtmlListDatapointsInstances,
2047
+ createListHTML,
2048
+ createListHTMLInstances,
2049
+ createBlacklist,
2050
+ createTimeListInstances,
2051
+ createData,
2052
+ createLists,
2053
+ writeDatapoints,
2054
+ createDPsForInstances,
2055
+ deleteDPsForInstances,
2056
+ createAdapterUpdateData,
2057
+ };