iobroker.device-watcher 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/main.js CHANGED
@@ -6,10 +6,13 @@
6
6
 
7
7
  const utils = require('@iobroker/adapter-core');
8
8
  const adapterName = require('./package.json').name.split('.').pop();
9
+ const schedule = require('node-schedule');
9
10
 
10
11
  // Sentry error reporting, disable when testing code!
11
12
  const enableSendSentry = true;
12
13
 
14
+ let isUnloaded = false;
15
+
13
16
  class DeviceWatcher extends utils.Adapter {
14
17
 
15
18
  constructor(options) {
@@ -41,6 +44,19 @@ class DeviceWatcher extends utils.Adapter {
41
44
  // Interval timer
42
45
  this.refreshDataTimeout = null;
43
46
 
47
+ this.devices = new Map();
48
+
49
+ // Information for dev: add ' 0_userdata.0. ' to selector for testing with own datapoints.
50
+ /*
51
+ This is the main template:
52
+ 'Selektor': '',
53
+ 'adapter': '',
54
+ 'battery': 'none',
55
+ 'reach': 'none',
56
+ 'isLowBat': 'none',
57
+ 'id': 'none''
58
+ */
59
+
44
60
  // arrays of supported adapters
45
61
  this.arrApart = {
46
62
  alexa2: {
@@ -93,6 +109,22 @@ class DeviceWatcher extends utils.Adapter {
93
109
  'reach': '.hubConnected',
94
110
  'isLowBat': 'none'
95
111
  },
112
+ ham: {
113
+ 'Selektor': 'ham.*.Battery-Level',
114
+ 'adapter': 'ham',
115
+ 'battery': '.Battery-Level',
116
+ 'reach': 'none',
117
+ 'isLowBat': 'none',
118
+ 'id': '.Name'
119
+ },
120
+ hmiP: {
121
+ 'Selektor': 'hmip.*.rssiDeviceValue',
122
+ 'adapter': 'hmiP',
123
+ 'rssiState': '.rssiDeviceValue',
124
+ 'battery': 'none',
125
+ 'reach': '.unreach',
126
+ 'isLowBat': '.lowBat',
127
+ },
96
128
  homematic: {
97
129
  'Selektor': 'hm-rpc.*.UNREACH',
98
130
  'adapter': 'homematic',
@@ -100,7 +132,8 @@ class DeviceWatcher extends utils.Adapter {
100
132
  'battery': '.OPERATING_VOLTAGE',
101
133
  'reach': '.UNREACH',
102
134
  'isLowBat': '.LOW_BAT',
103
- 'isLowBat2': '.LOWBAT'
135
+ 'isLowBat2': '.LOWBAT',
136
+ 'stateValue': '.1.STATE'
104
137
  },
105
138
  hue: {
106
139
  'Selektor': 'hue.*.reachable',
@@ -123,6 +156,13 @@ class DeviceWatcher extends utils.Adapter {
123
156
  'reach': 'none',
124
157
  'isLowBat': '.lowBatt'
125
158
  },
159
+ meross: {
160
+ 'Selektor': 'meross.*.online',
161
+ 'adapter': 'meross',
162
+ 'battery': '.battery',
163
+ 'reach': '.online',
164
+ 'isLowBat': 'none'
165
+ },
126
166
  mihome: {
127
167
  'Selektor': 'mihome.*.percent',
128
168
  'adapter': 'miHome',
@@ -147,6 +187,15 @@ class DeviceWatcher extends utils.Adapter {
147
187
  'isLowBat': 'none',
148
188
  'id': '.deviceInfo.model'
149
189
  },
190
+ netatmo: {
191
+ 'Selektor': 'netatmo.*.LastUpdate',
192
+ 'adapter': 'netatmo',
193
+ 'rssiState': '.WifiStatus',
194
+ 'rfState': '.RfStatus',
195
+ 'battery': '.BatteryStatus',
196
+ 'reach': 'none',
197
+ 'isLowBat': 'none'
198
+ },
150
199
  nukiExt: {
151
200
  'Selektor': 'nuki-extended.*.lastDataUpdate',
152
201
  'adapter': 'nuki-extended',
@@ -155,6 +204,13 @@ class DeviceWatcher extends utils.Adapter {
155
204
  'reach': 'none',
156
205
  'isLowBat': '.batteryCritical'
157
206
  },
207
+ nut: {
208
+ 'Selektor': 'nut.*.charge',
209
+ 'adapter': 'nut',
210
+ 'battery': '.charge',
211
+ 'reach': 'none',
212
+ 'isLowBat': 'none'
213
+ },
158
214
  ping: {
159
215
  'Selektor': 'ping.*.alive',
160
216
  'adapter': 'ping',
@@ -162,15 +218,24 @@ class DeviceWatcher extends utils.Adapter {
162
218
  'reach': '.alive',
163
219
  'isLowBat': 'none'
164
220
  },
221
+ roomba: {
222
+ 'Selektor': 'roomba.*.signal',
223
+ 'adapter': 'roomba',
224
+ 'battery': '.battery',
225
+ 'reach': '._connected',
226
+ 'isLowBat': 'none',
227
+ 'id': '.device.name'
228
+ },
165
229
  shelly: {
166
- 'Selektor': 'shelly.*.rssi',
230
+ 'Selektor': 'shelly.*.uptime',
167
231
  'adapter': 'shelly',
232
+ 'rssiState': '.rssi',
168
233
  'battery': '.sensor.battery',
169
234
  'reach': '.online',
170
235
  'isLowBat': 'none'
171
236
  },
172
237
  sonoff: {
173
- 'Selektor': 'sonoff.*.Uptime',
238
+ 'Selektor': 'sonoff.*.alive',
174
239
  'adapter': 'sonoff',
175
240
  'rssiState': '.Wifi_Signal',
176
241
  'battery': '.battery',
@@ -192,6 +257,48 @@ class DeviceWatcher extends utils.Adapter {
192
257
  'isLowBat': 'none',
193
258
  'id': '.id'
194
259
  },
260
+ tado: {
261
+ 'Selektor': 'tado.*.batteryState',
262
+ 'adapter': 'tado',
263
+ 'rssiState': 'none',
264
+ 'battery': 'none',
265
+ 'reach': '.connectionState.value',
266
+ 'isLowBat': '.batteryState',
267
+ 'id': 'none'
268
+ },
269
+ tradfri: {
270
+ 'Selektor': 'tradfri.*.lastSeen',
271
+ 'adapter': 'tradfri',
272
+ 'rssiState': 'none',
273
+ 'battery': '.batteryPercentage',
274
+ 'reach': '.alive',
275
+ 'isLowBat': 'none',
276
+ 'id': 'none'
277
+ },
278
+ unifi: {
279
+ 'Selektor': 'unifi.*.state',
280
+ 'adapter': 'unifi',
281
+ 'battery': 'none',
282
+ 'reach': '.state',
283
+ 'isLowBat': 'none',
284
+ 'id': 'none'
285
+ },
286
+ wled: {
287
+ 'Selektor': 'wled.*._online',
288
+ 'adapter': 'wled',
289
+ 'rssiState': '.wifi.rssi',
290
+ 'battery': 'none',
291
+ 'reach': '._online',
292
+ 'isLowBat': 'none',
293
+ 'id': 'none'
294
+ },
295
+ yeelight: {
296
+ 'Selektor': 'yeelight-2.*.connect',
297
+ 'adapter': 'yeelight-2',
298
+ 'battery': 'none',
299
+ 'reach': '.connect',
300
+ 'isLowBat': 'none'
301
+ },
195
302
  zigbee: {
196
303
  'Selektor': 'zigbee.*.link_quality',
197
304
  'adapter': 'zigbee',
@@ -199,21 +306,19 @@ class DeviceWatcher extends utils.Adapter {
199
306
  'reach': '.available',
200
307
  'isLowBat': '.battery_low'
201
308
  },
309
+ zigbee2mqtt: {
310
+ 'Selektor': 'zigbee2mqtt.*.link_quality',
311
+ 'adapter': 'zigbee2MQTT',
312
+ 'battery': '.battery',
313
+ 'reach': '.available',
314
+ 'isLowBat': '.battery_low'
315
+ },
202
316
  zwave: {
203
317
  'Selektor': 'zwave2.*.ready',
204
318
  'adapter': 'zwave',
205
319
  'battery': '.Battery.level',
206
320
  'reach': '.ready',
207
321
  'isLowBat': '.Battery.isLow'
208
- },
209
- test: { // Only for Dev
210
- 'Selektor': '0_userdata.*.UNREACH',
211
- 'adapter': 'homematic',
212
- 'rssiState': '.RSSI_DEVICE',
213
- 'battery': '.OPERATING_VOLTAGE',
214
- 'reach': '.UNREACH',
215
- 'isLowBat': '.LOW_BAT',
216
- 'isLowBat2': '.LOWBAT'
217
322
  }
218
323
  };
219
324
 
@@ -228,6 +333,8 @@ class DeviceWatcher extends utils.Adapter {
228
333
  async onReady() {
229
334
  this.log.debug(`Adapter ${adapterName} was started`);
230
335
 
336
+ isUnloaded = false;
337
+
231
338
  try {
232
339
  this.supAdapter = {
233
340
  alexa2: this.config.alexa2Devices,
@@ -236,29 +343,44 @@ class DeviceWatcher extends utils.Adapter {
236
343
  enocean: this.config.enoceanDevices,
237
344
  esphome: this.config.esphomeDevices,
238
345
  fritzdect: this.config.fritzdectDevices,
346
+ ham: this.config.hamDevices,
239
347
  harmony: this.config.harmonyDevices,
348
+ hmiP : this.config.hmiPDevices,
240
349
  homematic: this.config.homematicDevices,
241
350
  hue: this.config.hueDevices,
242
351
  hueExt: this.config.hueExtDevices,
243
352
  jeelink: this.config.jeelinkDevices,
353
+ meross: this.config.merossDevices,
244
354
  mihome: this.config.mihomeDevices,
245
355
  mihomeGW: this.config.mihomeDevices,
246
356
  mihomeVacuum: this.config.mihomeVacuumDevices,
357
+ netatmo: this.config.netatmoDevices,
247
358
  nukiExt: this.config.nukiExtDevices,
359
+ nut: this.config.nutDevices,
248
360
  ping: this.config.pingDevices,
361
+ roomba: this.config.roombaDevices,
249
362
  shelly: this.config.shellyDevices,
250
363
  sonoff: this.config.sonoffDevices,
251
364
  sonos: this.config.sonosDevices,
252
365
  switchbotBle: this.config.switchbotBleDevices,
366
+ tado: this.config.tadoDevices,
367
+ tradfri: this.config.tradfriDevices,
368
+ unifi: this.config.unifiDevices,
369
+ wled: this.config.wledDevices,
370
+ yeelight: this.config.yeelightDevices,
253
371
  zigbee: this.config.zigbeeDevices,
372
+ zigbee2mqtt: this.config.zigbee2mqttDevices,
254
373
  zwave: this.config.zwaveDevices,
255
- test: false // Only for Dev
256
374
  };
257
375
 
258
376
  for (const [id] of Object.entries(this.arrApart)) {
259
- if (this.supAdapter[id]) {
260
- this.arrDev.push(this.arrApart[id]);
261
- this.adapterSelected.push(await this.capitalize(id));
377
+ if (!isUnloaded) {
378
+ if (this.supAdapter[id]) {
379
+ this.arrDev.push(this.arrApart[id]);
380
+ this.adapterSelected.push(await this.capitalize(id));
381
+ }
382
+ } else {
383
+ return; // cancel run if unloaded was called.
262
384
  }
263
385
  }
264
386
 
@@ -280,17 +402,51 @@ class DeviceWatcher extends utils.Adapter {
280
402
  this.errorReporting('[onReady - create blacklist]', error);
281
403
  }
282
404
 
283
- // update data now
284
- await this.main();
405
+ //create and fill datapoints for each adapter if selected
406
+ try {
407
+ for (const [id] of Object.entries(this.arrApart)) {
408
+ if (!isUnloaded) {
409
+ if ((this.supAdapter !== undefined) && (this.supAdapter[id])) {
410
+
411
+ if (this.config.createOwnFolder) {
412
+ await this.createDPsForEachAdapter(id);
413
+ if (this.config.createHtmlList) await this.createHtmlListDatapoints(id);
414
+ this.log.debug(`Created datapoints for ${await this.capitalize(id)}`);
415
+ }
416
+ }
417
+ } else {
418
+ return; // cancel run if unloaded was called.
419
+ }
420
+ }
421
+ } catch (error) {
422
+ this.errorReporting('[onReady - create and fill datapoints for each adapter]', error);
423
+ }
424
+
425
+ // create HTML list
426
+ if (this.config.createHtmlList) await this.createHtmlListDatapoints();
285
427
 
286
428
  // update data in interval
287
429
  await this.refreshData();
288
430
 
431
+ // send overview for low battery devices
432
+ if (this.config.checkSendBatteryMsg) await this.sendBatteryNotifyShedule();
433
+
434
+ // send overview of offline devices
435
+ if (this.config.checkSendOfflineMsgDaily) await this.sendOfflineNotificationsShedule();
436
+
289
437
  } catch (error) {
290
438
  this.errorReporting('[onReady]', error);
291
439
  this.terminate ? this.terminate(15) : process.exit(15);
292
440
  }
293
- }
441
+
442
+ /*
443
+ this.devices.forEach((value, key) => {
444
+ this.log.warn(`${key}: ${value}`);
445
+ this.subscribeStates(value);
446
+ this.onStateChange(key, value);
447
+ });
448
+ */
449
+ } // <-- onReady end
294
450
 
295
451
  /**
296
452
  * Is called if a subscribed state changes
@@ -300,11 +456,11 @@ class DeviceWatcher extends utils.Adapter {
300
456
  async onStateChange(id, state) {
301
457
  if (state) {
302
458
  // The state was changed
303
- this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
304
- await this.main();
459
+ this.log.warn(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
460
+ // await this.main();
305
461
  } else {
306
462
  // The state was deleted
307
- this.log.debug(`state ${id} deleted`);
463
+ this.log.warn(`state ${id} deleted`);
308
464
  }
309
465
  }
310
466
 
@@ -319,40 +475,46 @@ class DeviceWatcher extends utils.Adapter {
319
475
  this.clearTimeout(this.refreshDataTimeout);
320
476
  }
321
477
 
322
- this.refreshDataTimeout = this.setTimeout(() => {
323
- this.log.debug('Updating Data');
478
+ if (!isUnloaded) {
479
+ this.refreshDataTimeout = this.setTimeout(() => {
480
+ this.log.debug('Updating Data');
324
481
 
325
- this.refreshDataTimeout = null;
326
- this.refreshData();
327
- }, nextTimeout);
328
- }
482
+ this.refreshDataTimeout = null;
483
+ this.refreshData();
484
+ }, nextTimeout);
485
+ } else {
486
+ return; // cancel run if unloaded was called.
487
+ }
488
+
489
+ } // <-- refreshData end
329
490
 
330
491
  async main() {
331
492
  this.log.debug(`Function started: ${this.main.name}`);
332
493
 
333
494
  try {
334
495
 
335
- //create and fill datapoints for each adapter if selected
496
+ // fill datapoints for each adapter if selected
336
497
  try {
337
498
  for (const [id] of Object.entries(this.arrApart)) {
338
- if ((this.supAdapter !== undefined) && (this.supAdapter[id])) {
339
-
340
- if (this.config.createOwnFolder) {
341
- await this.createDPsForEachAdapter(id);
342
- if (this.config.createHtmlList) await this.createHtmlListDatapoints(id);
343
- this.log.debug(`Created datapoints for ${await this.capitalize(id)}`);
344
- await this.createDataForEachAdapter(id);
345
- this.log.debug(`Created and filled data for each adapter`);
499
+ if (!isUnloaded) {
500
+ if ((this.supAdapter !== undefined) && (this.supAdapter[id])) {
501
+ if (this.config.createOwnFolder) {
502
+ await this.createDataForEachAdapter(id);
503
+ this.log.debug(`Created and filled data for each adapter`);
504
+ }
346
505
  }
506
+ } else {
507
+ this.log.warn('broke up');
508
+ return; // cancel run if unloaded was called.
347
509
  }
348
510
  }
511
+
349
512
  } catch (error) {
350
513
  this.errorReporting('[main - create and fill datapoints for each adapter]', error);
351
514
  }
352
515
 
353
- // creating counts and lists of all selected adapter
516
+ // fill counts and lists of all selected adapter
354
517
  try {
355
- if (this.config.createHtmlList) await this.createHtmlListDatapoints();
356
518
  await this.createDataOfAllAdapter();
357
519
  this.log.debug(`Created and filled data for all adapters`);
358
520
  } catch (error) {
@@ -393,428 +555,182 @@ class DeviceWatcher extends utils.Adapter {
393
555
  if (stateVal) return stateVal.val;
394
556
  }
395
557
 
396
- //create datapoints for each adapter
558
+ async createBlacklist() {
559
+ this.log.debug(`Function started: ${this.createBlacklist.name}`);
560
+
561
+ const myBlacklist = this.config.tableBlacklist;
562
+
563
+ for (const i in myBlacklist) {
564
+ if (!isUnloaded) {
565
+ this.blacklistArr.push(myBlacklist[i].device);
566
+ } else {
567
+ return; // cancel run if unloaded was called.
568
+ }
569
+ }
570
+ this.log.info(`Found items on the blacklist: ${this.blacklistArr}`);
571
+ this.log.debug(`Function finished: ${this.createBlacklist.name}`);
572
+ }
573
+
397
574
  /**
398
- * @param {object} adptName - Adaptername of devices
575
+ * @param {object} i - Device Object
399
576
  **/
400
- async createDPsForEachAdapter(adptName) {
577
+ async createData(i) {
578
+ const devices = await this.getForeignStatesAsync(this.arrDev[i].Selektor);
579
+ const deviceAdapterName = await this.capitalize(this.arrDev[i].adapter);
401
580
 
402
- await this.setObjectNotExistsAsync(`${adptName}`, {
403
- type: 'channel',
404
- common: {
405
- name: adptName,
406
- },
407
- native: {},
408
- });
581
+ /*---------- Start of second main loop ----------*/
582
+ for (const [id] of Object.entries(devices)) {
583
+ if (!isUnloaded) {
584
+ if (!this.blacklistArr.includes(id)) {
409
585
 
410
- await this.setObjectNotExistsAsync(`${adptName}.offlineCount`, {
411
- 'type': 'state',
412
- 'common': {
413
- 'name': {
414
- 'en': 'Number of devices offline',
415
- 'de': 'Anzahl der Geräte offline',
416
- 'ru': 'Количество устройств offline',
417
- 'pt': 'Número de dispositivos offline',
418
- 'nl': 'Nummer van apparatuur offline',
419
- 'fr': 'Nombre de dispositifs hors ligne',
420
- 'it': 'Numero di dispositivi offline',
421
- 'es': 'Número de dispositivos sin conexión',
422
- 'pl': 'Ilość urządzeń offline',
423
- 'zh-cn': '线内装置数量'
424
- },
425
- 'type': 'number',
426
- 'role': 'value',
427
- 'read': true,
428
- 'write': false,
429
- },
430
- 'native': {}
431
- });
586
+ const currDeviceString = id.slice(0, (id.lastIndexOf('.') + 1) - 1);
587
+ const shortCurrDeviceString = currDeviceString.slice(0, (currDeviceString.lastIndexOf('.') + 1) - 1);
588
+ const shortshortCurrDeviceString = shortCurrDeviceString.slice(0, (shortCurrDeviceString.lastIndexOf('.') + 1) - 1);
432
589
 
433
- await this.setObjectNotExistsAsync(`${adptName}.offlineList`, {
434
- 'type': 'state',
435
- 'common': {
436
- 'name': {
437
- 'en': 'List of offline devices',
438
- 'de': 'Liste der Offline-Geräte',
439
- 'ru': 'Список оффлайн устройств',
440
- 'pt': 'Lista de dispositivos off-line',
441
- 'nl': 'List van offline apparatuur',
442
- 'fr': 'Liste des dispositifs hors ligne',
443
- 'it': 'Elenco dei dispositivi offline',
444
- 'es': 'Lista de dispositivos sin conexión',
445
- 'pl': 'Lista urządzeń offline',
446
- 'zh-cn': '线装置清单'
447
- },
448
- 'type': 'array',
449
- 'role': 'json',
450
- 'read': true,
451
- 'write': false,
452
- },
453
- 'native': {}
454
- });
590
+ // Get device name
591
+ const deviceObject = await this.getForeignObjectAsync(currDeviceString);
592
+ const shortDeviceObject = await this.getForeignObjectAsync(shortCurrDeviceString);
593
+ const shortshortDeviceObject = await this.getForeignObjectAsync(shortshortCurrDeviceString);
594
+ let deviceName;
455
595
 
456
- await this.setObjectNotExistsAsync(`${adptName}.listAll`, {
457
- 'type': 'state',
458
- 'common': {
459
- 'name': {
460
- 'en': 'List of all devices',
461
- 'de': 'Liste aller Geräte',
462
- 'ru': 'Список всех устройств',
463
- 'pt': 'Lista de todos os dispositivos',
464
- 'nl': 'List van alle apparaten',
465
- 'fr': 'Liste de tous les dispositifs',
466
- 'it': 'Elenco di tutti i dispositivi',
467
- 'es': 'Lista de todos los dispositivos',
468
- 'pl': 'Lista wszystkich urządzeń',
469
- 'zh-cn': '所有装置清单'
470
- },
471
- 'type': 'array',
472
- 'role': 'json',
473
- 'read': true,
474
- 'write': false,
475
- },
476
- 'native': {}
477
- });
596
+ // Get ID with currDeviceString from datapoint
597
+ switch (this.arrDev[i].adapter) {
598
+ case 'switchbotBle': // Get ID for Switchbot and ESPHome Devices
599
+ case 'esphome':
600
+ deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
601
+ break;
478
602
 
479
- await this.setObjectNotExistsAsync(`${adptName}.linkQualityList`, {
480
- 'type': 'state',
481
- 'common': {
482
- 'name': {
483
- 'en': 'List of devices with signal strength',
484
- 'de': 'Liste der Geräte mit Signalstärke',
485
- 'ru': 'Список устройств с силой сигнала',
486
- 'pt': 'Lista de dispositivos com força de sinal',
487
- 'nl': 'List van apparaten met signaalkracht',
488
- 'fr': 'Liste des dispositifs avec force de signal',
489
- 'it': 'Elenco dei dispositivi con forza del segnale',
490
- 'es': 'Lista de dispositivos con fuerza de señal',
491
- 'pl': 'Lista urządzeń z siłą sygnałową',
492
- 'zh-cn': '具有信号实力的装置清单'
493
- },
494
- 'type': 'array',
495
- 'role': 'json',
496
- 'read': true,
497
- 'write': false,
498
- },
499
- 'native': {}
500
- });
603
+ // Get ID with short currDeviceString from objectjson
604
+ case 'hue-extended':
605
+ case 'homematic':
606
+ case 'nuki-extended':
607
+ case 'wled':
608
+ if (shortDeviceObject && typeof shortDeviceObject === 'object') {
609
+ deviceName = shortDeviceObject.common.name;
610
+ }
611
+ break;
501
612
 
502
- await this.setObjectNotExistsAsync(`${adptName}.countAll`, {
503
- 'type': 'state',
504
- 'common': {
505
- 'name': {
506
- 'en': 'Number of all devices',
507
- 'de': 'Anzahl aller Geräte',
508
- 'ru': 'Количество всех устройств',
509
- 'pt': 'Número de todos os dispositivos',
510
- 'nl': 'Nummer van alle apparaten',
511
- 'fr': 'Nombre de tous les appareils',
512
- 'it': 'Numero di tutti i dispositivi',
513
- 'es': 'Número de todos los dispositivos',
514
- 'pl': 'Ilość wszystkich urządzeń',
515
- 'zh-cn': '所有装置的数目'
516
- },
517
- 'type': 'number',
518
- 'role': 'value',
519
- 'read': true,
520
- 'write': false,
521
- },
522
- 'native': {}
523
- });
613
+ // Get ID with short short currDeviceString vom objectjson
614
+ case 'hmiP':
615
+ if (shortshortDeviceObject && typeof shortshortDeviceObject === 'object') {
616
+ deviceName = shortshortDeviceObject.common.name;
617
+ }
618
+ break;
524
619
 
525
- await this.setObjectNotExistsAsync(`${adptName}.batteryList`, {
526
- 'type': 'state',
527
- 'common': {
528
- 'name': {
529
- 'en': 'List of devices with battery state',
530
- 'de': 'Liste der Geräte mit Batteriezustand',
531
- 'ru': 'Список устройств с состоянием батареи',
532
- 'pt': 'Lista de dispositivos com estado da bateria',
533
- 'nl': 'List van apparaten met batterij staat',
534
- 'fr': 'Liste des appareils avec état de batterie',
535
- 'it': 'Elenco dei dispositivi con stato della batteria',
536
- 'es': 'Lista de dispositivos con estado de batería',
537
- 'pl': 'Lista urządzeń z baterią stanową',
538
- 'zh-cn': '电池国装置清单'
539
- },
540
- 'type': 'array',
541
- 'role': 'json',
542
- 'read': true,
543
- 'write': false,
544
- },
545
- 'native': {}
546
- });
620
+ // Get ID with short currDeviceString from datapoint
621
+ case 'mihomeVacuum':
622
+ case 'roomba':
623
+ deviceName = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].id);
624
+ break;
547
625
 
548
- await this.setObjectNotExistsAsync(`${adptName}.lowBatteryList`, {
549
- 'type': 'state',
550
- 'common': {
551
- 'name': {
552
- 'en': 'List of devices with low battery state',
553
- 'de': 'Liste der Geräte mit niedrigem Batteriezustand',
554
- 'ru': 'Список устройств с низким состоянием батареи',
555
- 'pt': 'Lista de dispositivos com baixo estado da bateria',
556
- 'nl': 'List van apparaten met lage batterij staat',
557
- 'fr': 'Liste des appareils à faible état de batterie',
558
- 'it': 'Elenco di dispositivi con stato di batteria basso',
559
- 'es': 'Lista de dispositivos con estado de batería bajo',
560
- 'pl': 'Lista urządzeń o niskim stanie baterii',
561
- 'zh-cn': '低电池国家装置清单'
562
- },
563
- 'type': 'array',
564
- 'role': 'json',
565
- 'read': true,
566
- 'write': false,
567
- },
568
- 'native': {}
569
- });
570
-
571
- await this.setObjectNotExistsAsync(`${adptName}.lowBatteryCount`, {
572
- 'type': 'state',
573
- 'common': {
574
- 'name': {
575
- 'en': 'Number of devices with low battery',
576
- 'de': 'Anzahl der Geräte mit niedriger Batterie',
577
- 'ru': 'Количество устройств c низкой батареей',
578
- 'pt': 'Número de dispositivos com bateria baixa',
579
- 'nl': 'Nummer van apparaten met lage batterij',
580
- 'fr': 'Nombre de dispositifs avec batterie basse',
581
- 'it': 'Numero di dispositivi con batteria bassa',
582
- 'es': 'Número de dispositivos con batería baja',
583
- 'pl': 'Liczba urządzeń z niską baterią',
584
- 'zh-cn': '低电池的装置数量'
585
- },
586
- 'type': 'number',
587
- 'role': 'value',
588
- 'read': true,
589
- 'write': false,
590
- },
591
- 'native': {}
592
- });
593
-
594
- await this.setObjectNotExistsAsync(`${adptName}.batteryCount`, {
595
- 'type': 'state',
596
- 'common': {
597
- 'name': {
598
- 'en': 'Number of devices with battery',
599
- 'de': 'Anzahl der Geräte mit Batterie',
600
- 'ru': 'Количество устройств c батареей',
601
- 'pt': 'Número de dispositivos com bateria',
602
- 'nl': 'Nummer van apparaten met batterij',
603
- 'fr': 'Nombre de dispositifs avec batterie',
604
- 'it': 'Numero di dispositivi con batteria',
605
- 'es': 'Número de dispositivos con batería',
606
- 'pl': 'Liczba urządzeń z baterią',
607
- 'zh-cn': '电池的装置数量'
608
- },
609
- 'type': 'number',
610
- 'role': 'value',
611
- 'read': true,
612
- 'write': false,
613
- },
614
- 'native': {}
615
- });
616
- }
617
-
618
- /**
619
- * @param {object} [adptName] - Adaptername of devices
620
- **/
621
- async createHtmlListDatapoints(adptName) {
622
-
623
- let dpSubFolder;
624
- //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
625
- if (adptName) {
626
- dpSubFolder = `${adptName}.`;
627
- } else {
628
- dpSubFolder = '';
629
- }
630
-
631
- await this.setObjectNotExistsAsync(`${dpSubFolder}offlineListHTML`, {
632
- 'type': 'state',
633
- 'common': {
634
- 'name': {
635
- 'en': 'HTML List of offline devices',
636
- 'de': 'HTML Liste der Offline-Geräte',
637
- 'ru': 'HTML Список оффлайн устройств',
638
- 'pt': 'HTML Lista de dispositivos off-line',
639
- 'nl': 'HTML List van offline apparatuur',
640
- 'fr': 'HTML Liste des dispositifs hors ligne',
641
- 'it': 'HTML Elenco dei dispositivi offline',
642
- 'es': 'HTML Lista de dispositivos sin conexión',
643
- 'pl': 'HTML Lista urządzeń offline',
644
- 'zh-cn': 'HTML 线装置清单'
645
- },
646
- 'type': 'string',
647
- 'role': 'html',
648
- 'read': true,
649
- 'write': false,
650
- },
651
- 'native': {}
652
- });
653
-
654
- await this.setObjectNotExistsAsync(`${dpSubFolder}linkQualityListHTML`, {
655
- 'type': 'state',
656
- 'common': {
657
- 'name': {
658
- 'en': 'HTML List of devices with signal strength',
659
- 'de': 'HTML Liste der Geräte mit Signalstärke',
660
- 'ru': 'HTML Список устройств с силой сигнала',
661
- 'pt': 'HTML Lista de dispositivos com força de sinal',
662
- 'nl': 'HTML List van apparaten met signaalkracht',
663
- 'fr': 'HTML Liste des dispositifs avec force de signal',
664
- 'it': 'HTML Elenco dei dispositivi con forza del segnale',
665
- 'es': 'HTML Lista de dispositivos con fuerza de señal',
666
- 'pl': 'HTML Lista urządzeń z siłą sygnałową',
667
- 'zh-cn': 'HTML 具有信号实力的装置清单'
668
- },
669
- 'type': 'string',
670
- 'role': 'value',
671
- 'read': true,
672
- 'write': false,
673
- },
674
- 'native': {}
675
- });
676
-
677
- await this.setObjectNotExistsAsync(`${dpSubFolder}batteryListHTML`, {
678
- 'type': 'state',
679
- 'common': {
680
- 'name': {
681
- 'en': 'HTML List of devices with battery state',
682
- 'de': 'HTML Liste der Geräte mit Batteriezustand',
683
- 'ru': 'HTML Список устройств с состоянием батареи',
684
- 'pt': 'HTML Lista de dispositivos com estado da bateria',
685
- 'nl': 'HTML List van apparaten met batterij staat',
686
- 'fr': 'HTML Liste des appareils avec état de batterie',
687
- 'it': 'HTML Elenco dei dispositivi con stato della batteria',
688
- 'es': 'HTML Lista de dispositivos con estado de batería',
689
- 'pl': 'HTML Lista urządzeń z baterią stanową',
690
- 'zh-cn': 'HTML 电池国装置清单'
691
- },
692
- 'type': 'string',
693
- 'role': 'html',
694
- 'read': true,
695
- 'write': false,
696
- },
697
- 'native': {}
698
- });
626
+ //Get ID of foldername
627
+ case 'tado':
628
+ deviceName = currDeviceString.slice(currDeviceString.lastIndexOf('.') + 1);
629
+ break;
699
630
 
700
- await this.setObjectNotExistsAsync(`${dpSubFolder}lowBatteryListHTML`, {
701
- 'type': 'state',
702
- 'common': {
703
- 'name': {
704
- 'en': 'HTML List of devices with low battery state',
705
- 'de': 'HTML Liste der Geräte mit niedrigem Batteriezustand',
706
- 'ru': 'HTML Список устройств с низким состоянием батареи',
707
- 'pt': 'HTML Lista de dispositivos com baixo estado da bateria',
708
- 'nl': 'HTML List van apparaten met lage batterij staat',
709
- 'fr': 'HTML Liste des appareils à faible état de batterie',
710
- 'it': 'HTML Elenco di dispositivi con stato di batteria basso',
711
- 'es': 'HTML Lista de dispositivos con estado de batería bajo',
712
- 'pl': 'HTML Lista urządzeń o niskim stanie baterii',
713
- 'zh-cn': 'HTML 低电池国家装置清单'
714
- },
715
- 'type': 'string',
716
- 'role': 'html',
717
- 'read': true,
718
- 'write': false,
719
- },
720
- 'native': {}
721
- });
722
- }
631
+ //Get ID of foldername
632
+ case 'yeelight-2':
633
+ deviceName = shortCurrDeviceString.slice(shortCurrDeviceString.lastIndexOf('.') + 1);
634
+ break;
723
635
 
724
- async createBlacklist() {
725
- this.log.debug(`Function started: ${this.createBlacklist.name}`);
636
+ // Get ID with main selektor from objectjson
637
+ default:
638
+ if (deviceObject && typeof deviceObject === 'object') {
639
+ deviceName = deviceObject.common.name;
640
+ }
641
+ break;
642
+ }
726
643
 
727
- const myBlacklist = this.config.tableBlacklist;
644
+ const deviceMainSelector = await this.getForeignStateAsync(id);
645
+ const deviceStateSelector = await this.getForeignStateAsync(shortCurrDeviceString + this.arrDev[i].stateValue); // for homematic devices
728
646
 
729
- for (const i in myBlacklist) {
730
- this.blacklistArr.push(myBlacklist[i].device);
731
- }
732
- this.log.info(`Found items on the blacklist: ${this.blacklistArr}`);
733
- this.log.debug(`Function finished: ${this.createBlacklist.name}`);
734
- }
647
+ // Get battery states
648
+ const deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery);
649
+ const shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery);
650
+ const shortDeviceBatteryState2 = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery2);
735
651
 
736
- /**
737
- * @param {object} i - Device Object
738
- **/
739
- async createData(i) {
740
- const devices = await this.getForeignStatesAsync(this.arrDev[i].Selektor);
741
- const deviceAdapterName = await this.capitalize(this.arrDev[i].adapter);
652
+ this.devices.set(deviceName, currDeviceString + this.arrDev[i].reach);
653
+ // List all entries
654
+ //let text = '';
655
+ //this.devices.forEach (function(value, key) {
656
+ // text += key + ' : ' + value;
657
+ // });
658
+ // this.log.warn(text);
742
659
 
743
- /*---------- Start of second main loop ----------*/
744
- for (const [id] of Object.entries(devices)) {
745
- if (!this.blacklistArr.includes(id)) {
746
-
747
- const currDeviceString = id.slice(0, (id.lastIndexOf('.') + 1) - 1);
748
- const shortCurrDeviceString = currDeviceString.slice(0, (currDeviceString.lastIndexOf('.') + 1) - 1);
749
-
750
- // Get device name
751
- const deviceObject = await this.getForeignObjectAsync(currDeviceString);
752
- const shortDeviceObject = await this.getForeignObjectAsync(shortCurrDeviceString);
753
- let deviceName;
754
-
755
- switch (this.arrDev[i].adapter) {
756
- case 'switchbotBle': // Get ID for Switchbot and ESPHome Devices
757
- case 'esphome':
758
- deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
759
- break;
760
-
761
- case 'hue-extended':
762
- case 'homematic':
763
- case 'nuki-extended':
764
- if (shortDeviceObject && typeof shortDeviceObject === 'object') {
765
- deviceName = shortDeviceObject.common.name;
766
- }
767
- break;
660
+ // Get link quality
661
+ let deviceQualityState;
662
+ let linkQuality;
768
663
 
769
- case 'mihomeVacuum':
770
- deviceName = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].id);
771
- break;
664
+ switch (this.arrDev[i].adapter) {
665
+ case 'sonoff':
666
+ case 'hmiP':
667
+ case 'homematic':
668
+ case 'wled':
669
+ case 'shelly':
670
+ deviceQualityState = await this.getForeignStateAsync(currDeviceString + this.arrDev[i].rssiState);
671
+ break;
772
672
 
773
- default:
774
- if (deviceObject && typeof deviceObject === 'object') {
775
- deviceName = deviceObject.common.name;
776
- }
777
- break;
778
- }
673
+ case 'mihomeVacuum':
674
+ deviceQualityState = await this.getForeignStateAsync(shortCurrDeviceString + this.arrDev[i].rssiState);
675
+ break;
779
676
 
780
- const deviceMainSelector = await this.getForeignStateAsync(id);
677
+ case 'tradfri':
678
+ case 'ham':
679
+ case 'meross':
680
+ case 'nut':
681
+ case 'miHome':
682
+ case 'unifi':
683
+ deviceQualityState;
684
+ break;
781
685
 
782
- // Get battery states
783
- const deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery);
784
- const shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery);
785
- const shortDeviceBatteryState2 = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery2);
686
+ case 'netatmo':
687
+ deviceQualityState = await this.getForeignStateAsync(currDeviceString + this.arrDev[i].rssiState);
688
+ if (!deviceQualityState) {
689
+ deviceQualityState = await this.getForeignStateAsync(currDeviceString + this.arrDev[i].rfState);
690
+ }
691
+ break;
786
692
 
787
- // Get link quality
788
- let deviceQualityState;
789
- let linkQuality;
693
+ default:
694
+ deviceQualityState = await this.getForeignStateAsync(id);
695
+ break;
696
+ }
790
697
 
791
- switch (this.arrDev[i].adapter) {
792
- case 'sonoff':
793
- case 'homematic':
794
- deviceQualityState = await this.getForeignStateAsync(currDeviceString + this.arrDev[i].rssiState);
795
- break;
698
+ if ((deviceQualityState) && (typeof deviceQualityState.val === 'number')) {
699
+ if (this.config.trueState) {
700
+ linkQuality = deviceQualityState.val;
701
+ } else {
702
+ // If Quality State is already an percent value
703
+ switch (this.arrDev[i].adapter) {
704
+ case 'roomba':
705
+ linkQuality = deviceQualityState.val + '%';
706
+ break;
796
707
 
797
- case 'mihomeVacuum':
798
- deviceQualityState = await this.getForeignStateAsync(shortCurrDeviceString + this.arrDev[i].rssiState);
799
- break;
708
+ default:
709
+ // If Quality State is an RSSI vaulue calculate in percent:
710
+ if (deviceQualityState.val == -255) {
711
+ linkQuality = ' - ';
712
+ } else if (deviceQualityState.val < 0) {
713
+ linkQuality = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100) + '%';
800
714
 
801
- default:
802
- deviceQualityState = await this.getForeignStateAsync(id);
803
- break;
804
- }
715
+ // If Quality State is an value between 0-255 (zigbee) calculate in percent:
716
+ } else if ((deviceQualityState.val) >= 0) {
717
+ linkQuality = parseFloat((100 / 255 * deviceQualityState.val).toFixed(0)) + '%';
718
+ }
719
+ break;
720
+ }
805
721
 
806
- if ((deviceQualityState) && (typeof deviceQualityState.val === 'number')) {
807
- if (this.config.trueState) {
808
- linkQuality = deviceQualityState.val;
809
- } else {
810
- if (deviceQualityState.val < 0) {
811
- linkQuality = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100) + '%';
812
- } else if ((deviceQualityState.val) >= 0) {
813
- linkQuality = parseFloat((100 / 255 * deviceQualityState.val).toFixed(0)) + '%';
814
722
  }
815
- }
816
- if (this.config.listOnlyBattery) {
817
- if (deviceBatteryState || shortDeviceBatteryState) {
723
+ if (this.config.listOnlyBattery) {
724
+ if (deviceBatteryState || shortDeviceBatteryState) {
725
+ this.linkQualityDevices.push(
726
+ {
727
+ 'Device': deviceName,
728
+ 'Adapter': deviceAdapterName,
729
+ 'Signal strength': linkQuality
730
+ }
731
+ );
732
+ }
733
+ } else {
818
734
  this.linkQualityDevices.push(
819
735
  {
820
736
  'Device': deviceName,
@@ -823,85 +739,136 @@ class DeviceWatcher extends utils.Adapter {
823
739
  }
824
740
  );
825
741
  }
826
- } else {
827
- this.linkQualityDevices.push(
828
- {
829
- 'Device': deviceName,
830
- 'Adapter': deviceAdapterName,
831
- 'Signal strength': linkQuality
742
+ } else if ((deviceQualityState) && (typeof deviceQualityState.val === 'string')) {
743
+ switch (this.arrDev[i].adapter) {
744
+ case 'netatmo':
745
+ // for Netatmo devices
746
+ linkQuality = deviceQualityState.val;
747
+ break;
748
+ case 'nuki-extended':
749
+ linkQuality = ' - ';
750
+ break;
751
+ }
752
+
753
+ if (this.config.listOnlyBattery) {
754
+ if (deviceBatteryState || shortDeviceBatteryState) {
755
+ this.linkQualityDevices.push(
756
+ {
757
+ 'Device': deviceName,
758
+ 'Adapter': deviceAdapterName,
759
+ 'Signal strength': linkQuality
760
+ }
761
+ );
832
762
  }
833
- );
763
+ } else {
764
+ this.linkQualityDevices.push(
765
+ {
766
+ 'Device': deviceName,
767
+ 'Adapter': deviceAdapterName,
768
+ 'Signal strength': linkQuality
769
+ }
770
+ );
771
+ }
772
+ }
773
+ else {
774
+ linkQuality = ' - '; // no linkQuality available for powered devices
834
775
  }
835
- } else {
836
- linkQuality = ' - '; // no linkQuality available for powered devices
837
- }
838
776
 
839
- // Count how many devices with link Quality
840
- this.linkQualityCount = this.linkQualityDevices.length;
841
-
842
- // When was the last contact to the device?
843
- let lastContactString;
844
-
845
- let deviceState = 'Online';
846
- if (deviceMainSelector) {
847
- try {
848
- const time = new Date();
849
- const lastContact = Math.round((time.getTime() - deviceMainSelector.ts) / 1000 / 60);
850
- const lastStateChange = Math.round((time.getTime() - deviceMainSelector.lc) / 1000 / 60);
851
- const deviceUnreachState = await this.getInitValue(currDeviceString + this.arrDev[i].reach);
852
- const shortDeviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].reach);
853
-
854
- const getLastContact = async () => {
855
- lastContactString = this.formatDate(new Date((deviceMainSelector.ts)), 'hh:mm') + ' Uhr';
856
- if (Math.round(lastContact) > 100) {
857
- lastContactString = Math.round(lastContact / 60) + ' Stunden';
858
- }
859
- if (Math.round(lastContact / 60) > 48) {
860
- lastContactString = Math.round(lastContact / 60 / 24) + ' Tagen';
861
- }
862
- return lastContactString;
863
- };
777
+ // Count how many devices with link Quality
778
+ this.linkQualityCount = this.linkQualityDevices.length;
864
779
 
865
- const getLastStateChange = async () => {
866
- lastContactString = this.formatDate(new Date((deviceMainSelector.lc)), 'hh:mm') + ' Uhr';
867
- if (Math.round(lastStateChange) > 100) {
868
- lastContactString = Math.round(lastStateChange / 60) + ' Stunden';
869
- }
870
- if (Math.round(lastStateChange / 60) > 48) {
871
- lastContactString = Math.round(lastStateChange / 60 / 24) + ' Tagen';
872
- }
873
- return lastContactString;
874
- };
875
-
876
- // If there is no contact since user sets minutes add device in offline list
877
- // calculate to days after 48 hours
878
- switch (this.arrDev[i].reach) {
879
- case 'none':
880
- await getLastContact();
881
- break;
780
+ // When was the last contact to the device?
781
+ let lastContactString;
882
782
 
883
- default:
783
+ let deviceState = 'Online';
784
+ if (deviceMainSelector) {
785
+ try {
786
+ const time = new Date();
787
+ const lastContact = Math.round((time.getTime() - deviceMainSelector.ts) / 1000 / 60);
788
+ const lastStateChange = Math.round((time.getTime() - deviceMainSelector.lc) / 1000 / 60);
789
+ const deviceUnreachState = await this.getInitValue(currDeviceString + this.arrDev[i].reach);
790
+ const shortDeviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].reach);
791
+
792
+
793
+ const getLastContact = async () => {
794
+ lastContactString = this.formatDate(new Date((deviceMainSelector.ts)), 'hh:mm') + ' Uhr';
795
+ if (Math.round(lastContact) > 100) {
796
+ lastContactString = Math.round(lastContact / 60) + ' Stunden';
797
+ }
798
+ if (Math.round(lastContact / 60) > 48) {
799
+ lastContactString = Math.round(lastContact / 60 / 24) + ' Tagen';
800
+ }
801
+ return lastContactString;
802
+ };
803
+
804
+ const getLastStateChange = async () => {
805
+ lastContactString = this.formatDate(new Date((deviceMainSelector.lc)), 'hh:mm') + ' Uhr';
806
+ if (Math.round(lastStateChange) > 100) {
807
+ lastContactString = Math.round(lastStateChange / 60) + ' Stunden';
808
+ }
809
+ if (Math.round(lastStateChange / 60) > 48) {
810
+ lastContactString = Math.round(lastStateChange / 60 / 24) + ' Tagen';
811
+ }
812
+ return lastContactString;
813
+ };
814
+
815
+
816
+ // If there is no contact since user sets minutes add device in offline list
817
+ // calculate to days after 48 hours
818
+ switch (this.arrDev[i].reach) {
819
+ case 'none':
820
+ await getLastContact();
821
+ break;
822
+
823
+ default:
884
824
  //State changed
885
- if (this.arrDev[i].adapter == 'homematic') {
886
- if (deviceUnreachState) {
887
- await getLastStateChange();
888
- } else {
889
- await getLastContact();
890
- }
891
- } else {
892
- if ((!deviceUnreachState)) {
893
- await getLastStateChange();
825
+ if (this.arrDev[i].adapter == 'homematic') {
826
+ if (linkQuality != ' - ') {
827
+ if (deviceUnreachState) {
828
+ await getLastStateChange();
829
+ } else {
830
+ await getLastContact();
831
+ }
832
+ } else {
833
+ if (deviceStateSelector) { // because old hm devices don't send rssi states
834
+ const lastContactOfState = Math.round((time.getTime() - deviceStateSelector.ts) / 1000 / 60);
835
+ const getLastContactOfState = async () => {
836
+ lastContactString = this.formatDate(new Date((deviceStateSelector.ts)), 'hh:mm') + ' Uhr';
837
+ if (Math.round(lastContactOfState) > 100) {
838
+ lastContactString = Math.round(lastContactOfState / 60) + ' Stunden';
839
+ }
840
+ if (Math.round(lastContactOfState / 60) > 48) {
841
+ lastContactString = Math.round(lastContactOfState / 60 / 24) + ' Tagen';
842
+ }
843
+ return lastContactString;
844
+ };
845
+ await getLastContactOfState();
846
+ }
847
+ }
848
+
894
849
  } else {
895
- await getLastContact();
850
+ if ((!deviceUnreachState)) {
851
+ await getLastStateChange();
852
+ } else {
853
+ await getLastContact();
854
+ }
855
+ break;
896
856
  }
897
- break;
898
- }
899
- }
857
+ }
900
858
 
901
- const pushOfflineDevice = async () => {
902
- if (this.config.listOnlyBattery) { //if checked, list only battery devices
903
- if (deviceBatteryState || shortDeviceBatteryState) {
904
- this.offlineDevices.push(
859
+ const pushOfflineDevice = async () => {
860
+ if (this.config.listOnlyBattery) { //if checked, list only battery devices
861
+ if (deviceBatteryState || shortDeviceBatteryState) {
862
+ this.offlineDevices.push(
863
+ {
864
+ 'Device': deviceName,
865
+ 'Adapter': deviceAdapterName,
866
+ 'Last contact': lastContactString
867
+ }
868
+ );
869
+ }
870
+ } else {
871
+ this.offlineDevices.push( //else push all devices
905
872
  {
906
873
  'Device': deviceName,
907
874
  'Adapter': deviceAdapterName,
@@ -909,312 +876,414 @@ class DeviceWatcher extends utils.Adapter {
909
876
  }
910
877
  );
911
878
  }
912
- } else {
913
- this.offlineDevices.push( //else push all devices
914
- {
915
- 'Device': deviceName,
916
- 'Adapter': deviceAdapterName,
917
- 'Last contact': lastContactString
879
+ };
880
+
881
+ switch (this.arrDev[i].adapter) {
882
+ case 'alexa2':
883
+ if (this.config.alexa2MaxMinutes === -1) {
884
+ if (!deviceUnreachState) {
885
+ deviceState = 'Offline'; //set online state to offline
886
+ await pushOfflineDevice();
887
+ }
888
+ } else if (lastContact > this.config.alexa2MaxMinutes) {
889
+ deviceState = 'Offline'; //set online state to offline
890
+ await pushOfflineDevice();
918
891
  }
919
- );
920
- }
921
- };
922
-
923
- // await this.subscribeForeignStatesAsync(currDeviceString + this.arrDev[i].reach);
924
-
925
- switch (this.arrDev[i].adapter) {
926
- case 'alexa2':
927
- if (this.config.alexa2MaxMinutes === -1) {
928
- if (!deviceUnreachState) {
892
+ break;
893
+ case 'ble':
894
+ if (this.config.bleMaxMinutes === -1) {
895
+ if (!deviceUnreachState) {
896
+ deviceState = 'Offline'; //set online state to offline
897
+ await pushOfflineDevice();
898
+ }
899
+ } else if (lastContact > this.config.bleMaxMinutes) {
900
+ deviceState = 'Offline'; //set online state to offline
901
+ await pushOfflineDevice();
902
+ }
903
+ break;
904
+ case 'deconz':
905
+ if (this.config.deconzMaxMinutes === -1) {
906
+ if (!deviceUnreachState) {
907
+ deviceState = 'Offline'; //set online state to offline
908
+ await pushOfflineDevice();
909
+ }
910
+ } else if (lastContact > this.config.deconzMaxMinutes) {
911
+ deviceState = 'Offline'; //set online state to offline
912
+ await pushOfflineDevice();
913
+ }
914
+ break;
915
+ case 'enocean':
916
+ if (this.config.enoceanMaxMinutes === -1) {
917
+ if (!deviceUnreachState) {
918
+ deviceState = 'Offline'; //set online state to offline
919
+ await pushOfflineDevice();
920
+ }
921
+ } else if (lastContact > this.config.enoceanMaxMinutes) {
922
+ deviceState = 'Offline'; //set online state to offline
923
+ await pushOfflineDevice();
924
+ }
925
+ break;
926
+ case 'esphome':
927
+ if (this.config.esphomeMaxMinutes === -1) {
928
+ if (!deviceUnreachState) {
929
+ deviceState = 'Offline'; //set online state to offline
930
+ await pushOfflineDevice();
931
+ }
932
+ } else if (lastContact > this.config.esphomeMaxMinutes) {
933
+ deviceState = 'Offline'; //set online state to offline
934
+ await pushOfflineDevice();
935
+ }
936
+ break;
937
+ case 'fritzDect':
938
+ if (this.config.fritzdectMaxMinutes === -1) {
939
+ if (!deviceUnreachState) {
940
+ deviceState = 'Offline'; //set online state to offline
941
+ await pushOfflineDevice();
942
+ }
943
+ } else if (lastContact > this.config.fritzdectMaxMinutes) {
944
+ deviceState = 'Offline'; //set online state to offline
945
+ await pushOfflineDevice();
946
+ }
947
+ break;
948
+ case 'harmony':
949
+ if (this.config.harmonyMaxMinutes === -1) {
950
+ if (!deviceUnreachState) {
951
+ deviceState = 'Offline'; //set online state to offline
952
+ await pushOfflineDevice();
953
+ }
954
+ } else if (lastContact > this.config.harmonyMaxMinutes) {
955
+ deviceState = 'Offline'; //set online state to offline
956
+ await pushOfflineDevice();
957
+ }
958
+ break;
959
+ case 'ham':
960
+ if (this.config.hamMaxMinutes === -1) {
961
+ if (!deviceUnreachState) {
962
+ deviceState = 'Offline'; //set online state to offline
963
+ await pushOfflineDevice();
964
+ }
965
+ } else if (lastContact > this.config.hamMaxMinutes) {
966
+ deviceState = 'Offline'; //set online state to offline
967
+ await pushOfflineDevice();
968
+ }
969
+ break;
970
+ case 'hmiP':
971
+ if (this.config.hmiPMaxMinutes === -1) {
972
+ if (deviceUnreachState) {
973
+ deviceState = 'Offline'; //set online state to offline
974
+ await pushOfflineDevice();
975
+ }
976
+ } else if (lastContact > this.config.hmiPMaxMinutes) {
977
+ deviceState = 'Offline'; //set online state to offline
978
+ await pushOfflineDevice();
979
+ }
980
+ break;
981
+ case 'homematic':
982
+ if (this.config.homematicMaxMinutes === -1) {
983
+ if (deviceUnreachState) {
984
+ deviceState = 'Offline'; //set online state to offline
985
+ await pushOfflineDevice();
986
+ }
987
+ } else if (lastContact > this.config.homematicMaxMinutes) {
988
+ deviceState = 'Offline'; //set online state to offline
989
+ await pushOfflineDevice();
990
+ }
991
+ break;
992
+ case 'hue':
993
+ if (this.config.hueMaxMinutes === -1) {
994
+ if (!deviceUnreachState) {
995
+ deviceState = 'Offline'; //set online state to offline
996
+ await pushOfflineDevice();
997
+ }
998
+ } else if (lastContact > this.config.hueMaxMinutes) {
999
+ deviceState = 'Offline'; //set online state to offline
1000
+ await pushOfflineDevice();
1001
+ }
1002
+ break;
1003
+ case 'hue-extended':
1004
+ if (this.config.hueextMaxMinutes === -1) {
1005
+ if (!deviceUnreachState) {
1006
+ deviceState = 'Offline'; //set online state to offline
1007
+ await pushOfflineDevice();
1008
+ }
1009
+ } else if (lastContact > this.config.hueextMaxMinutes) {
1010
+ deviceState = 'Offline'; //set online state to offline
1011
+ await pushOfflineDevice();
1012
+ }
1013
+ break;
1014
+ case 'jeelink':
1015
+ if (this.config.jeelinkMaxMinutes === -1) {
1016
+ if (!deviceUnreachState) {
1017
+ deviceState = 'Offline'; //set online state to offline
1018
+ await pushOfflineDevice();
1019
+ }
1020
+ } else if (lastContact > this.config.jeelinkMaxMinutes) {
929
1021
  deviceState = 'Offline'; //set online state to offline
930
1022
  await pushOfflineDevice();
931
1023
  }
932
- } else if ((lastStateChange > this.config.alexa2MaxMinutes) && (!deviceUnreachState)) {
933
- deviceState = 'Offline'; //set online state to offline
934
- await pushOfflineDevice();
935
- }
936
- break;
937
- case 'ble':
938
- if (this.config.bleMaxMinutes === -1) {
939
- if (!deviceUnreachState) {
1024
+ break;
1025
+ case 'meross':
1026
+ if (this.config.merossMaxMinutes === -1) {
1027
+ if (!deviceUnreachState) {
1028
+ deviceState = 'Offline'; //set online state to offline
1029
+ await pushOfflineDevice();
1030
+ }
1031
+ } else if (lastContact > this.config.merossMaxMinutes) {
940
1032
  deviceState = 'Offline'; //set online state to offline
941
1033
  await pushOfflineDevice();
942
1034
  }
943
- } else if (lastContact > this.config.bleMaxMinutes) {
944
- deviceState = 'Offline'; //set online state to offline
945
- await pushOfflineDevice();
946
- }
947
- break;
948
- case 'deconz':
949
- if (this.config.deconzMaxMinutes === -1) {
950
- if (!deviceUnreachState) {
1035
+ break;
1036
+ case 'miHome':
1037
+ if (this.config.mihomeMaxMinutes === -1) {
1038
+ if (!deviceUnreachState) {
1039
+ deviceState = 'Offline'; //set online state to offline
1040
+ await pushOfflineDevice();
1041
+ }
1042
+ } else if (lastContact > this.config.mihomeMaxMinutes) {
951
1043
  deviceState = 'Offline'; //set online state to offline
952
1044
  await pushOfflineDevice();
953
1045
  }
954
- } else if ((lastStateChange > this.config.deconzMaxMinutes) && (!deviceUnreachState)) {
955
- deviceState = 'Offline'; //set online state to offline
956
- await pushOfflineDevice();
957
- }
958
- break;
959
- case 'enocean':
960
- if (this.config.enoceanMaxMinutes === -1) {
961
- if (!deviceUnreachState) {
1046
+ break;
1047
+ case 'mihomeVacuum':
1048
+ if (this.config.mihomeVacuumMaxMinutes === -1) {
1049
+ if (!shortDeviceUnreachState) {
1050
+ deviceState = 'Offline'; //set online state to offline
1051
+ await pushOfflineDevice();
1052
+ }
1053
+ } else if (lastContact > this.config.mihomeVacuumMaxMinutes) {
962
1054
  deviceState = 'Offline'; //set online state to offline
963
1055
  await pushOfflineDevice();
964
1056
  }
965
- } else if (lastContact > this.config.enoceanMaxMinutes) {
966
- deviceState = 'Offline'; //set online state to offline
967
- await pushOfflineDevice();
968
- }
969
- break;
970
- case 'esphome':
971
- if (this.config.esphomeMaxMinutes === -1) {
972
- if (!deviceUnreachState) {
1057
+ break;
1058
+ case 'netatmo':
1059
+ if (this.config.netatmoMaxMinutes === -1) {
1060
+ if (!deviceUnreachState) {
1061
+ deviceState = 'Offline'; //set online state to offline
1062
+ await pushOfflineDevice();
1063
+ }
1064
+ } else if (lastContact > this.config.netatmoMaxMinutes) {
973
1065
  deviceState = 'Offline'; //set online state to offline
974
1066
  await pushOfflineDevice();
975
1067
  }
976
- } else if ((lastStateChange > this.config.esphomeMaxMinutes) && (!deviceUnreachState)) {
977
- deviceState = 'Offline'; //set online state to offline
978
- await pushOfflineDevice();
979
- }
980
- break;
981
- case 'fritzDect':
982
- if (this.config.fritzdectMaxMinutes === -1) {
983
- if (!deviceUnreachState) {
1068
+ break;
1069
+ case 'nuki-extended':
1070
+ if (this.config.nukiextendMaxMinutes === -1) {
1071
+ if (!deviceUnreachState) {
1072
+ deviceState = 'Offline'; //set online state to offline
1073
+ await pushOfflineDevice();
1074
+ }
1075
+ } else if (lastContact > this.config.nukiextendMaxMinutes) {
984
1076
  deviceState = 'Offline'; //set online state to offline
985
1077
  await pushOfflineDevice();
986
1078
  }
987
- } else if ((lastStateChange > this.config.fritzdectMaxMinutes) && (!deviceUnreachState)) {
988
- deviceState = 'Offline'; //set online state to offline
989
- await pushOfflineDevice();
990
- }
991
- break;
992
- case 'harmony':
993
- if (this.config.harmonyMaxMinutes === -1) {
994
- if (!deviceUnreachState) {
1079
+ break;
1080
+ case 'nut':
1081
+ if (this.config.nutMaxMinutes === -1) {
1082
+ if (!deviceUnreachState) {
1083
+ deviceState = 'Offline'; //set online state to offline
1084
+ await pushOfflineDevice();
1085
+ }
1086
+ } else if (lastContact > this.config.nutMaxMinutes) {
995
1087
  deviceState = 'Offline'; //set online state to offline
996
1088
  await pushOfflineDevice();
997
1089
  }
998
- } else if ((lastStateChange > this.config.harmonyMaxMinutes) && (!deviceUnreachState)) {
999
- deviceState = 'Offline'; //set online state to offline
1000
- await pushOfflineDevice();
1001
- }
1002
- break;
1003
- case 'homematic':
1004
- if (this.config.homematicMaxMinutes === -1) {
1005
- if (deviceUnreachState) {
1090
+ break;
1091
+ case 'ping':
1092
+ if (this.config.pingMaxMinutes === -1) {
1093
+ if (!deviceUnreachState) {
1094
+ deviceState = 'Offline'; //set online state to offline
1095
+ await pushOfflineDevice();
1096
+ }
1097
+ } else if ((lastStateChange > this.config.pingMaxMinutes) && (!deviceUnreachState)) {
1006
1098
  deviceState = 'Offline'; //set online state to offline
1007
1099
  await pushOfflineDevice();
1008
1100
  }
1009
- } else if ((lastStateChange > this.config.homematicMaxMinutes) && (deviceUnreachState)) {
1010
- deviceState = 'Offline'; //set online state to offline
1011
- await pushOfflineDevice();
1012
- }
1013
- break;
1014
- case 'hue':
1015
- if (this.config.hueMaxMinutes === -1) {
1016
- if (!deviceUnreachState) {
1101
+ break;
1102
+ case 'roomba':
1103
+ if (this.config.roombaMaxMinutes === -1) {
1104
+ if (!deviceUnreachState) {
1105
+ deviceState = 'Offline'; //set online state to offline
1106
+ await pushOfflineDevice();
1107
+ }
1108
+ } else if (lastContact > this.config.roombaMaxMinutes) {
1017
1109
  deviceState = 'Offline'; //set online state to offline
1018
1110
  await pushOfflineDevice();
1019
1111
  }
1020
- } else if ((lastStateChange > this.config.hueMaxMinutes) && (!deviceUnreachState)) {
1021
- deviceState = 'Offline'; //set online state to offline
1022
- await pushOfflineDevice();
1023
- }
1024
- break;
1025
- case 'hue-extended':
1026
- if (this.config.hueextMaxMinutes === -1) {
1027
- if (!deviceUnreachState) {
1112
+ break;
1113
+ case 'shelly':
1114
+ if (this.config.shellyMaxMinutes === -1) {
1115
+ if (!deviceUnreachState) {
1116
+ deviceState = 'Offline'; //set online state to offline
1117
+ await pushOfflineDevice();
1118
+ }
1119
+ } else if (lastContact > this.config.shellyMaxMinutes) {
1028
1120
  deviceState = 'Offline'; //set online state to offline
1029
1121
  await pushOfflineDevice();
1030
1122
  }
1031
- } else if ((lastStateChange > this.config.hueextMaxMinutes) && (!deviceUnreachState)) {
1032
- deviceState = 'Offline'; //set online state to offline
1033
- await pushOfflineDevice();
1034
- }
1035
- break;
1036
- case 'jeelink':
1037
- if (this.config.jeelinkMaxMinutes === -1) {
1038
- if (!deviceUnreachState) {
1123
+ break;
1124
+ case 'sonoff':
1125
+ if (this.config.sonoffMaxMinutes === -1) {
1126
+ if (!deviceUnreachState) {
1127
+ deviceState = 'Offline'; //set online state to offline
1128
+ await pushOfflineDevice();
1129
+ }
1130
+ } else if (lastContact > this.config.sonoffMaxMinutes) {
1039
1131
  deviceState = 'Offline'; //set online state to offline
1040
1132
  await pushOfflineDevice();
1041
1133
  }
1042
- } else if (lastContact > this.config.jeelinkMaxMinutes) {
1043
- deviceState = 'Offline'; //set online state to offline
1044
- await pushOfflineDevice();
1045
- }
1046
- break;
1047
- case 'miHome':
1048
- if (this.config.mihomeMaxMinutes === -1) {
1049
- if (!deviceUnreachState) {
1134
+ break;
1135
+ case 'sonos':
1136
+ if (this.config.sonosMaxMinutes === -1) {
1137
+ if (!deviceUnreachState) {
1138
+ deviceState = 'Offline'; //set online state to offline
1139
+ await pushOfflineDevice();
1140
+ }
1141
+ } else if (lastContact > this.config.sonosMaxMinutes) {
1050
1142
  deviceState = 'Offline'; //set online state to offline
1051
1143
  await pushOfflineDevice();
1052
1144
  }
1053
- } else if ((lastStateChange > this.config.mihomeMaxMinutes) && (!deviceUnreachState)) {
1054
- deviceState = 'Offline'; //set online state to offline
1055
- await pushOfflineDevice();
1056
- }
1057
- break;
1058
- case 'mihomeVacuum':
1059
- if (this.config.mihomeVacuumMaxMinutes === -1) {
1060
- if (!shortDeviceUnreachState) {
1145
+ break;
1146
+ case 'switchbotBle':
1147
+ if (this.config.switchbotMaxMinutes === -1) {
1148
+ if (!deviceUnreachState) {
1149
+ deviceState = 'Offline'; //set online state to offline
1150
+ await pushOfflineDevice();
1151
+ }
1152
+ } else if (lastContact > this.config.switchbotMaxMinutes) {
1061
1153
  deviceState = 'Offline'; //set online state to offline
1062
1154
  await pushOfflineDevice();
1063
1155
  }
1064
- } else if ((lastStateChange > this.config.mihomeVacuumMaxMinutes) && (!shortDeviceUnreachState)) {
1065
- deviceState = 'Offline'; //set online state to offline
1066
- await pushOfflineDevice();
1067
- }
1068
- break;
1069
- case 'nuki-extended':
1070
- if (this.config.nukiextendMaxMinutes === -1) {
1071
- if (!deviceUnreachState) {
1156
+ break;
1157
+ case 'tado':
1158
+ if (this.config.tadoMaxMinutes === -1) {
1159
+ if (!deviceUnreachState) {
1160
+ deviceState = 'Offline'; //set online state to offline
1161
+ await pushOfflineDevice();
1162
+ }
1163
+ } else if (lastContact > this.config.tadoMaxMinutes) {
1072
1164
  deviceState = 'Offline'; //set online state to offline
1073
1165
  await pushOfflineDevice();
1074
1166
  }
1075
- } else if (lastContact > this.config.nukiextendMaxMinutes) {
1076
- deviceState = 'Offline'; //set online state to offline
1077
- await pushOfflineDevice();
1078
- }
1079
- break;
1080
- case 'ping':
1081
- if (this.config.pingMaxMinutes === -1) {
1082
- if (!deviceUnreachState) {
1167
+ break;
1168
+ case 'tradfri':
1169
+ if (this.config.tradfriMaxMinutes === -1) {
1170
+ if (!deviceUnreachState) {
1171
+ deviceState = 'Offline'; //set online state to offline
1172
+ await pushOfflineDevice();
1173
+ }
1174
+ } else if (lastContact > this.config.tradfriMaxMinutes) {
1083
1175
  deviceState = 'Offline'; //set online state to offline
1084
1176
  await pushOfflineDevice();
1085
1177
  }
1086
- } else if ((lastStateChange > this.config.pingMaxMinutes) && (!deviceUnreachState)) {
1087
- deviceState = 'Offline'; //set online state to offline
1088
- await pushOfflineDevice();
1089
- }
1090
- break;
1091
- case 'shelly':
1092
- if (this.config.shellyMaxMinutes === -1) {
1093
- if (!deviceUnreachState) {
1178
+ break;
1179
+ case 'unifi':
1180
+ if (this.config.unifiMaxMinutes === -1) {
1181
+ if (deviceUnreachState === 0) {
1182
+ deviceState = 'Offline'; //set online state to offline
1183
+ await pushOfflineDevice();
1184
+ }
1185
+ } else if (lastContact > this.config.unifiMaxMinutes) {
1094
1186
  deviceState = 'Offline'; //set online state to offline
1095
1187
  await pushOfflineDevice();
1096
1188
  }
1097
- } else if ((lastStateChange > this.config.shellyMaxMinutes) && (!deviceUnreachState)) {
1098
- deviceState = 'Offline'; //set online state to offline
1099
- await pushOfflineDevice();
1100
- }
1101
- break;
1102
- case 'sonoff':
1103
- if (this.config.sonoffMaxMinutes === -1) {
1104
- if (!deviceUnreachState) {
1189
+ break;
1190
+ case 'wled':
1191
+ if (this.config.wledMaxMinutes === -1) {
1192
+ if (!deviceUnreachState) {
1193
+ deviceState = 'Offline'; //set online state to offline
1194
+ await pushOfflineDevice();
1195
+ }
1196
+ } else if (lastContact > this.config.wledMaxMinutes) {
1105
1197
  deviceState = 'Offline'; //set online state to offline
1106
1198
  await pushOfflineDevice();
1107
1199
  }
1108
- } else if ((lastStateChange > this.config.sonoffMaxMinutes) && (!deviceUnreachState)) {
1109
- deviceState = 'Offline'; //set online state to offline
1110
- await pushOfflineDevice();
1111
- }
1112
- break;
1113
- case 'sonos':
1114
- if (this.config.sonosMaxMinutes === -1) {
1115
- if (!deviceUnreachState) {
1200
+ break;
1201
+ case 'yeelight-2':
1202
+ if (this.config.yeelightMaxMinutes === -1) {
1203
+ if (!deviceUnreachState) {
1204
+ deviceState = 'Offline'; //set online state to offline
1205
+ await pushOfflineDevice();
1206
+ }
1207
+ } else if (lastContact > this.config.yeelightMaxMinutes) {
1116
1208
  deviceState = 'Offline'; //set online state to offline
1117
1209
  await pushOfflineDevice();
1118
1210
  }
1119
- } else if ((lastStateChange > this.config.sonosMaxMinutes) && (!deviceUnreachState)) {
1120
- deviceState = 'Offline'; //set online state to offline
1121
- await pushOfflineDevice();
1122
- }
1123
- break;
1124
- case 'switchbotBle':
1125
- if (this.config.switchbotMaxMinutes === -1) {
1126
- if (!deviceUnreachState) {
1211
+ break;
1212
+ case 'zigbee':
1213
+ if (this.config.zigbeeMaxMinutes === -1) {
1214
+ if (!deviceUnreachState) {
1215
+ deviceState = 'Offline'; //set online state to offline
1216
+ await pushOfflineDevice();
1217
+ }
1218
+ } else if (lastContact > this.config.zigbeeMaxMinutes) {
1127
1219
  deviceState = 'Offline'; //set online state to offline
1128
1220
  await pushOfflineDevice();
1129
1221
  }
1130
- } else if (lastContact > this.config.switchbotMaxMinutes) {
1131
- deviceState = 'Offline'; //set online state to offline
1132
- await pushOfflineDevice();
1133
- }
1134
- break;
1135
- case 'zigbee':
1136
- if (this.config.zigbeeMaxMinutes === -1) {
1137
- if (!deviceUnreachState) {
1222
+ break;
1223
+ case 'zigbee2MQTT':
1224
+ if (this.config.zigbee2mqttMaxMinutes === -1) {
1225
+ if (!deviceUnreachState) {
1226
+ deviceState = 'Offline'; //set online state to offline
1227
+ await pushOfflineDevice();
1228
+ }
1229
+ } else if (lastContact > this.config.zigbee2mqttMaxMinutes) {
1138
1230
  deviceState = 'Offline'; //set online state to offline
1139
1231
  await pushOfflineDevice();
1140
1232
  }
1141
- } else if ((lastStateChange > this.config.zigbeeMaxMinutes) && (!deviceUnreachState)) {
1142
- deviceState = 'Offline'; //set online state to offline
1143
- await pushOfflineDevice();
1144
- }
1145
- break;
1146
- case 'zwave':
1147
- if (this.config.zwaveMaxMinutes === -1) {
1148
- if (!deviceUnreachState) {
1233
+ break;
1234
+ case 'zwave':
1235
+ if (this.config.zwaveMaxMinutes === -1) {
1236
+ if (!deviceUnreachState) {
1237
+ deviceState = 'Offline'; //set online state to offline
1238
+ await pushOfflineDevice();
1239
+ }
1240
+ } else if (lastContact > this.config.zwaveMaxMinutes) {
1149
1241
  deviceState = 'Offline'; //set online state to offline
1150
1242
  await pushOfflineDevice();
1151
1243
  }
1152
- } else if ((lastStateChange > this.config.zwaveMaxMinutes) && (!deviceUnreachState)) {
1153
- deviceState = 'Offline'; //set online state to offline
1154
- await pushOfflineDevice();
1155
- }
1156
- break;
1244
+ break;
1245
+ }
1246
+ } catch (error) {
1247
+ this.errorReporting('[getLastContact]', error);
1157
1248
  }
1158
- } catch (error) {
1159
- this.errorReporting('[getLastContact]', error);
1160
1249
  }
1161
- }
1162
1250
 
1163
1251
 
1164
1252
 
1165
- // Count how many devcies are offline
1166
- this.offlineDevicesCount = this.offlineDevices.length;
1253
+ // Count how many devcies are offline
1254
+ this.offlineDevicesCount = this.offlineDevices.length;
1167
1255
 
1168
- // Get battery states
1169
- let batteryHealth;
1170
- const deviceLowBatState = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat);
1171
- const deviceLowBatStateHM = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat2);
1256
+ // Get battery states
1257
+ let batteryHealth;
1258
+ const deviceLowBatState = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat);
1259
+ const deviceLowBatStateHM = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat2);
1172
1260
 
1173
- if ((!deviceBatteryState) && (!shortDeviceBatteryState) && (!shortDeviceBatteryState2)) {
1174
- if ((deviceLowBatState !== undefined) || (deviceLowBatState !== undefined) || (deviceLowBatStateHM !== undefined)) {
1175
- switch (this.arrDev[i].isLowBat) {
1176
- case 'none':
1177
- batteryHealth = ' - ';
1178
- break;
1179
- default:
1180
- if (!deviceLowBatState) {
1181
- batteryHealth = 'ok';
1182
- } else {
1183
- batteryHealth = 'low';
1184
- }
1185
- break;
1186
- }
1187
- switch (this.arrDev[i].isLowBat2) {
1188
- case 'none':
1189
- batteryHealth = ' - ';
1190
- break;
1191
- default:
1192
- if (!deviceLowBatState) {
1193
- batteryHealth = 'ok';
1194
- } else {
1195
- batteryHealth = 'low';
1196
- }
1197
- break;
1198
- }
1199
- this.batteryPowered.push(
1200
- {
1201
- 'Device': deviceName,
1202
- 'Adapter': deviceAdapterName,
1203
- 'Battery': batteryHealth
1261
+ if ((!deviceBatteryState) && (!shortDeviceBatteryState) && (!shortDeviceBatteryState2)) {
1262
+ if ((deviceLowBatState !== undefined) || (deviceLowBatState !== undefined) || (deviceLowBatStateHM !== undefined)) {
1263
+ switch (this.arrDev[i].isLowBat) {
1264
+ case 'none':
1265
+ batteryHealth = ' - ';
1266
+ break;
1267
+ default:
1268
+ if ((!deviceLowBatState) || (deviceLowBatState == 'NORMAL')) {
1269
+ batteryHealth = 'ok';
1270
+ } else {
1271
+ batteryHealth = 'low';
1272
+ }
1273
+ break;
1204
1274
  }
1205
- );
1206
- } else {
1207
- batteryHealth = ' - ';
1208
- }
1209
- } else {
1210
- switch (this.arrDev[i].adapter) {
1211
- case 'homematic':
1212
- if (deviceBatteryState === 0) {
1213
- batteryHealth = ' - ';
1214
- } else {
1215
- batteryHealth = deviceBatteryState + 'V';
1275
+ switch (this.arrDev[i].isLowBat2) {
1276
+ case 'none':
1277
+ batteryHealth = ' - ';
1278
+ break;
1279
+ default:
1280
+ if ((!deviceLowBatState) || (deviceLowBatState == 'NORMAL')) {
1281
+ batteryHealth = 'ok';
1282
+ } else {
1283
+ batteryHealth = 'low';
1284
+ }
1285
+ break;
1216
1286
  }
1217
-
1218
1287
  this.batteryPowered.push(
1219
1288
  {
1220
1289
  'Device': deviceName,
@@ -1222,10 +1291,18 @@ class DeviceWatcher extends utils.Adapter {
1222
1291
  'Battery': batteryHealth
1223
1292
  }
1224
1293
  );
1225
- break;
1226
- case 'hue-extended':
1227
- if (shortDeviceBatteryState) {
1228
- batteryHealth = shortDeviceBatteryState + '%';
1294
+ } else {
1295
+ batteryHealth = ' - ';
1296
+ }
1297
+ } else {
1298
+ switch (this.arrDev[i].adapter) {
1299
+ case 'homematic':
1300
+ if (deviceBatteryState === 0) {
1301
+ batteryHealth = ' - ';
1302
+ } else {
1303
+ batteryHealth = deviceBatteryState + 'V';
1304
+ }
1305
+
1229
1306
  this.batteryPowered.push(
1230
1307
  {
1231
1308
  'Device': deviceName,
@@ -1233,11 +1310,42 @@ class DeviceWatcher extends utils.Adapter {
1233
1310
  'Battery': batteryHealth
1234
1311
  }
1235
1312
  );
1236
- }
1237
- break;
1238
- case 'mihomeVacuum':
1239
- if (shortDeviceBatteryState) {
1240
- batteryHealth = shortDeviceBatteryState + '%';
1313
+ break;
1314
+ case 'hue-extended':
1315
+ if (shortDeviceBatteryState) {
1316
+ batteryHealth = shortDeviceBatteryState + '%';
1317
+ this.batteryPowered.push(
1318
+ {
1319
+ 'Device': deviceName,
1320
+ 'Adapter': deviceAdapterName,
1321
+ 'Battery': batteryHealth
1322
+ }
1323
+ );
1324
+ }
1325
+ break;
1326
+ case 'mihomeVacuum':
1327
+ if (shortDeviceBatteryState) {
1328
+ batteryHealth = shortDeviceBatteryState + '%';
1329
+ this.batteryPowered.push(
1330
+ {
1331
+ 'Device': deviceName,
1332
+ 'Adapter': deviceAdapterName,
1333
+ 'Battery': batteryHealth
1334
+ }
1335
+ );
1336
+ } else if (shortDeviceBatteryState2) {
1337
+ batteryHealth = shortDeviceBatteryState2 + '%';
1338
+ this.batteryPowered.push(
1339
+ {
1340
+ 'Device': deviceName,
1341
+ 'Adapter': deviceAdapterName,
1342
+ 'Battery': batteryHealth
1343
+ }
1344
+ );
1345
+ }
1346
+ break;
1347
+ default:
1348
+ batteryHealth = (deviceBatteryState) + '%';
1241
1349
  this.batteryPowered.push(
1242
1350
  {
1243
1351
  'Device': deviceName,
@@ -1245,9 +1353,20 @@ class DeviceWatcher extends utils.Adapter {
1245
1353
  'Battery': batteryHealth
1246
1354
  }
1247
1355
  );
1248
- } else if (shortDeviceBatteryState2) {
1249
- batteryHealth = shortDeviceBatteryState2 + '%';
1250
- this.batteryPowered.push(
1356
+ }
1357
+ }
1358
+
1359
+ // Count how many devices are with battery
1360
+ this.batteryPoweredCount = this.batteryPowered.length;
1361
+
1362
+ // Count how many devices are with low battery
1363
+ const batteryWarningMin = this.config.minWarnBatterie;
1364
+
1365
+ // fill list with low battery devices
1366
+ switch (this.arrDev[i].adapter) {
1367
+ case 'homematic': // there are differnt low bat states between hm and hmIp devices
1368
+ if (deviceLowBatState || deviceLowBatStateHM) {
1369
+ this.batteryLowPowered.push(
1251
1370
  {
1252
1371
  'Device': deviceName,
1253
1372
  'Adapter': deviceAdapterName,
@@ -1256,63 +1375,56 @@ class DeviceWatcher extends utils.Adapter {
1256
1375
  );
1257
1376
  }
1258
1377
  break;
1259
- default:
1260
- batteryHealth = (deviceBatteryState) + '%';
1261
- this.batteryPowered.push(
1262
- {
1263
- 'Device': deviceName,
1264
- 'Adapter': deviceAdapterName,
1265
- 'Battery': batteryHealth
1266
- }
1267
- );
1268
- }
1269
- }
1270
1378
 
1271
- // Count how many devices are with battery
1272
- this.batteryPoweredCount = this.batteryPowered.length;
1379
+ case 'tado': // there is an string as indicator
1380
+ if (deviceLowBatState != 'NORMAL') {
1381
+ this.batteryLowPowered.push(
1382
+ {
1383
+ 'Device': deviceName,
1384
+ 'Adapter': deviceAdapterName,
1385
+ 'Battery': batteryHealth
1386
+ }
1387
+ );
1388
+ }
1389
+ break;
1273
1390
 
1274
- // Count how many devices are with low battery
1275
- const batteryWarningMin = this.config.minWarnBatterie;
1391
+ default: // for all other devices with low bat states
1392
+ if (deviceLowBatState) {
1393
+ this.batteryLowPowered.push(
1394
+ {
1395
+ 'Device': deviceName,
1396
+ 'Adapter': deviceAdapterName,
1397
+ 'Battery': batteryHealth
1398
+ }
1399
+ );
1400
+ } else if (deviceBatteryState && (deviceBatteryState < batteryWarningMin)) { // if the battery state is under the set limit
1401
+ this.batteryLowPowered.push(
1402
+ {
1403
+ 'Device': deviceName,
1404
+ 'Adapter': deviceAdapterName,
1405
+ 'Battery': batteryHealth
1406
+ }
1407
+ );
1408
+ }
1409
+ }
1276
1410
 
1277
- // fill list with low battery devices
1278
- switch (this.arrDev[i].adapter) {
1279
- case 'homematic': // there are differnt low bat states between hm and hmIp devices
1280
- if (deviceLowBatState || deviceLowBatStateHM) {
1281
- this.batteryLowPowered.push(
1282
- {
1283
- 'Device': deviceName,
1284
- 'Adapter': deviceAdapterName,
1285
- 'Battery': batteryHealth
1286
- }
1287
- );
1288
- }
1289
- break;
1411
+ // 3d. Count how many devices are with low battery
1412
+ this.lowBatteryPoweredCount = this.batteryLowPowered.length;
1290
1413
 
1291
- default: // for all other devices with low bat states
1292
- if (deviceLowBatState) {
1293
- this.batteryLowPowered.push(
1294
- {
1295
- 'Device': deviceName,
1296
- 'Adapter': deviceAdapterName,
1297
- 'Battery': batteryHealth
1298
- }
1299
- );
1300
- } else if (deviceBatteryState && (deviceBatteryState < batteryWarningMin)) { // if the battery state is under the set limit
1301
- this.batteryLowPowered.push(
1414
+ if (this.config.listOnlyBattery) { // 4. Add only devices with battery in the list
1415
+ if (deviceBatteryState || shortDeviceBatteryState) {
1416
+ this.listAllDevices.push(
1302
1417
  {
1303
1418
  'Device': deviceName,
1304
1419
  'Adapter': deviceAdapterName,
1305
- 'Battery': batteryHealth
1420
+ 'Battery': batteryHealth,
1421
+ 'Signal strength': linkQuality,
1422
+ 'Last contact': lastContactString,
1423
+ 'Status': deviceState
1306
1424
  }
1307
1425
  );
1308
1426
  }
1309
- }
1310
-
1311
- // 3d. Count how many devices are with low battery
1312
- this.lowBatteryPoweredCount = this.batteryLowPowered.length;
1313
-
1314
- if (this.config.listOnlyBattery) { // 4. Add only devices with battery in the list
1315
- if (deviceBatteryState || shortDeviceBatteryState) {
1427
+ } else if (!this.config.listOnlyBattery) { // 4. Add all devices
1316
1428
  this.listAllDevices.push(
1317
1429
  {
1318
1430
  'Device': deviceName,
@@ -1324,22 +1436,13 @@ class DeviceWatcher extends utils.Adapter {
1324
1436
  }
1325
1437
  );
1326
1438
  }
1327
- } else if (!this.config.listOnlyBattery) { // 4. Add all devices
1328
- this.listAllDevices.push(
1329
- {
1330
- 'Device': deviceName,
1331
- 'Adapter': deviceAdapterName,
1332
- 'Battery': batteryHealth,
1333
- 'Signal strength': linkQuality,
1334
- 'Last contact': lastContactString,
1335
- 'Status': deviceState
1336
- }
1337
- );
1338
- }
1339
1439
 
1340
1440
 
1341
- // 4a. Count how many devices are exists
1342
- this.deviceCounter = this.listAllDevices.length;
1441
+ // 4a. Count how many devices are exists
1442
+ this.deviceCounter = this.listAllDevices.length;
1443
+ }
1444
+ } else {
1445
+ return; // cancel run if unloaded was called.
1343
1446
  }
1344
1447
  } // <-- end of loop
1345
1448
  } // <-- end of createData
@@ -1377,15 +1480,18 @@ class DeviceWatcher extends utils.Adapter {
1377
1480
  await this.resetVars(); // reset the arrays and counts
1378
1481
 
1379
1482
  for (let i = 0; i < this.arrDev.length; i++) {
1380
-
1381
- await this.createData(i);
1382
-
1483
+ if (!isUnloaded) {
1484
+ await this.createData(i);
1485
+ } else {
1486
+ return; // cancel run if unloaded was called.
1487
+ }
1383
1488
  }
1384
1489
 
1385
- if (this.config.checkSendOfflineMsg) await this.sendOfflineNotifications(); // send message if new devices are offline
1386
- if (this.config.checkSendOfflineMsgDaily) await this.sendDailyOfflineNotifications(); // send daily overview of offline devices
1387
- if (this.config.checkSendBatteryMsg) await this.sendBatteryNotifications(); // send message for low battery devices
1388
- await this.writeDatapoints(); // fill the datapoints
1490
+ // send message if new devices are offline
1491
+ if (this.config.checkSendOfflineMsg) await this.sendOfflineNotifications();
1492
+
1493
+ // fill the datapoints
1494
+ await this.writeDatapoints();
1389
1495
  } catch (error) {
1390
1496
  this.errorReporting('[createDataOfAllAdapter]', error);
1391
1497
  }
@@ -1515,172 +1621,132 @@ class DeviceWatcher extends utils.Adapter {
1515
1621
  }
1516
1622
  } // <-- End of sendNotification function
1517
1623
 
1624
+ async sendBatteryNotifyShedule() {
1625
+ // send message for low battery devices
1518
1626
 
1519
- async sendOfflineNotifications() {
1520
- // send message if an device is offline
1521
-
1522
- this.log.debug(`Start the function: ${this.sendOfflineNotifications.name}`);
1523
-
1524
- try {
1525
- let msg = '';
1526
- const offlineDevicesCountOld = await this.getOwnInitValue('offlineCount');
1627
+ const time = (this.config.checkSendBatteryTime).split(':');
1527
1628
 
1528
- if ((this.offlineDevicesCount !== offlineDevicesCountOld)) {
1529
- if (this.offlineDevicesCount == 0) {
1530
- msg = 'Alle Geräte sind Online.';
1531
- } else if (this.offlineDevicesCount == 1) { // make singular if it is only one device
1532
- msg = 'Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n';
1533
- } else if (this.offlineDevicesCount >= 2) { //make plural if it is more than one device
1534
- msg = `Folgende ${this.offlineDevicesCount} Geräte sind seit einiger Zeit nicht erreichbar: \n`;
1535
- }
1629
+ const checkDays = []; // list of selected days
1536
1630
 
1537
- for (const id of this.offlineDevices) {
1538
- msg = `${msg} \n ${id['Device']} (${id['Last contact']})`;
1539
- }
1631
+ // push the selected days in list
1632
+ if (this.config.checkMonday) checkDays.push(1);
1633
+ if (this.config.checkTuesday) checkDays.push(2);
1634
+ if (this.config.checkWednesday) checkDays.push(3);
1635
+ if (this.config.checkThursday) checkDays.push(4);
1636
+ if (this.config.checkFriday) checkDays.push(5);
1637
+ if (this.config.checkSaturday) checkDays.push(6);
1638
+ if (this.config.checkSunday) checkDays.push(0);
1540
1639
 
1541
- this.log.info(msg);
1542
- await this.setStateAsync('lastNotification', msg, true);
1543
- await this.sendNotification(msg);
1544
- }
1545
- } catch (error) {
1546
- this.errorReporting('[sendOfflineMessage]', error);
1640
+ if (checkDays.length >= 1) { // check if an day is selected
1641
+ this.log.debug(`Number of selected days for daily battery message: ${checkDays.length}. Send Message on: ${(checkDays).join(', ')} ...`);
1642
+ } else {
1643
+ this.log.warn(`No days selected for daily battery message. Please check the instance configuration!`);
1644
+ return; // cancel function if no day is selected
1547
1645
  }
1548
1646
 
1549
- try {
1550
- // send daily an overview with offline devices
1551
- if (this.config.checkSendOfflineMsgDaily) {
1552
- // Check if the daily message for offline devices was already sent today
1553
- const lastOfflineNotifyIndicator = await this.getOwnInitValue('info.lastOfflineNotification');
1554
- const now = new Date(); // get date
1555
-
1556
- // set indicator for send message first to 'false', after sending to 'true'
1557
- if (now.getHours() < 11) await this.setStateAsync('info.lastOfflineNotification', false, true);
1558
-
1559
- // if time is > 11 (12:00 pm create message for offline devices devices)
1560
- if ((now.getHours() > 11) && (!lastOfflineNotifyIndicator)) {
1647
+ if (!isUnloaded) {
1648
+ const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
1649
+ schedule.scheduleJob(cron, () => {
1650
+ try {
1561
1651
  let msg = '';
1562
1652
 
1563
- for (const id of this.offlineDevices) {
1564
- msg = `${msg} \n ${id['Device']} (${id['Last contact']})`;
1653
+ for (const id of this.batteryLowPowered) {
1654
+ msg = `${msg}\n${id['Device']} (${id['Battery']})`;
1565
1655
  }
1566
1656
 
1567
- if (this.offlineDevicesCount > 0) {
1568
- this.log.info(`Geräte Offline: ${msg}`);
1569
- await this.setStateAsync('lastNotification', `Geräte Offline: ${msg}`, true);
1657
+ if (this.lowBatteryPoweredCount > 0) {
1658
+ this.log.info(`Niedrige Batteriezustände: ${msg}`);
1659
+ this.setStateAsync('lastNotification', `Niedrige Batteriezustände: ${msg}`, true);
1570
1660
 
1571
- await this.sendNotification(`Geräte Offline: ${msg}`);
1661
+ this.sendNotification(`Niedriege Batteriezustände: ${msg}`);
1572
1662
 
1573
- await this.setStateAsync('info.lastOfflineNotification', true, true);
1574
1663
  }
1664
+
1665
+ } catch (error) {
1666
+ this.errorReporting('[sendBatteryNotifyShedule]', error);
1575
1667
  }
1576
- }
1577
- } catch (error) {
1578
- this.errorReporting('[sendOfflineMessage - daily message]', error);
1668
+ });
1579
1669
  }
1580
- this.log.debug(`Finished the function: ${this.sendOfflineNotifications.name}`);
1581
- }//<--End of offline notification
1670
+ } //<--End of battery notification
1582
1671
 
1583
- async sendDailyOfflineNotifications() {
1584
- // send daily an overview with offline devices
1672
+ async sendOfflineNotifications() {
1673
+ // send message if an device is offline
1585
1674
 
1586
- this.log.debug(`Start the function: ${this.sendDailyOfflineNotifications.name}`);
1675
+ this.log.debug(`Start the function: ${this.sendOfflineNotifications.name}`);
1587
1676
 
1588
1677
  try {
1589
- // Check if the daily message for offline devices was already sent today
1590
- const lastOfflineNotifyIndicator = await this.getOwnInitValue('info.lastOfflineNotification');
1591
- const now = new Date(); // get date
1592
-
1593
- // set indicator for send message first to 'false', after sending to 'true'
1594
- if (now.getHours() < 11) await this.setStateAsync('info.lastOfflineNotification', false, true);
1678
+ let msg = '';
1679
+ const offlineDevicesCountOld = await this.getOwnInitValue('offlineCount');
1595
1680
 
1596
- // if time is > 11 (12:00 pm create message for offline devices devices)
1597
- if ((now.getHours() > 11) && (!lastOfflineNotifyIndicator)) {
1598
- let msg = '';
1681
+ if ((this.offlineDevicesCount !== offlineDevicesCountOld)) {
1682
+ if (this.offlineDevicesCount == 0) {
1683
+ msg = 'Alle Geräte sind Online.';
1684
+ } else if (this.offlineDevicesCount == 1) { // make singular if it is only one device
1685
+ msg = 'Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n';
1686
+ } else if (this.offlineDevicesCount >= 2) { //make plural if it is more than one device
1687
+ msg = `Folgende ${this.offlineDevicesCount} Geräte sind seit einiger Zeit nicht erreichbar: \n`;
1688
+ }
1599
1689
 
1600
1690
  for (const id of this.offlineDevices) {
1601
- msg = `${msg} \n ${id['Device']} (${id['Last contact']})`;
1691
+ msg = `${msg}\n${id['Device']} (${id['Last contact']})`;
1602
1692
  }
1603
1693
 
1604
- if (this.offlineDevicesCount > 0) {
1605
- this.log.info(`Geräte Offline: ${msg}`);
1606
- await this.setStateAsync('lastNotification', `Geräte Offline: ${msg}`, true);
1607
-
1608
- await this.sendNotification(`Geräte Offline: ${msg}`);
1609
-
1610
- await this.setStateAsync('info.lastOfflineNotification', true, true);
1611
- }
1694
+ this.log.info(msg);
1695
+ await this.setStateAsync('lastNotification', msg, true);
1696
+ await this.sendNotification(msg);
1612
1697
  }
1613
1698
  } catch (error) {
1614
- this.errorReporting('[sendDailyOfflineNotifications]', error);
1699
+ this.errorReporting('[sendOfflineMessage]', error);
1615
1700
  }
1616
- this.log.debug(`Finished the function: ${this.sendDailyOfflineNotifications.name}`);
1617
- }//<--End of daily offline notification
1618
-
1619
- async sendBatteryNotifications() {
1620
- // send message for low battery devices
1621
-
1622
- this.log.debug(`Start the function: ${this.sendBatteryNotifications.name}`);
1701
+ this.log.debug(`Finished the function: ${this.sendOfflineNotifications.name}`);
1702
+ }//<--End of offline notification
1623
1703
 
1624
- try {
1704
+ async sendOfflineNotificationsShedule() {
1705
+ // send daily an overview with offline devices
1625
1706
 
1626
- const now = new Date(); // get date
1627
- const today = now.getDay();
1628
- const checkDays = []; // list of selected days
1629
- let checkToday; // indicator if selected day is today
1630
-
1631
- // push the selected days in list
1632
- if (this.config.checkMonday) checkDays.push(1);
1633
- if (this.config.checkTuesday) checkDays.push(2);
1634
- if (this.config.checkWednesday) checkDays.push(3);
1635
- if (this.config.checkThursday) checkDays.push(4);
1636
- if (this.config.checkFriday) checkDays.push(5);
1637
- if (this.config.checkSaturday) checkDays.push(6);
1638
- if (this.config.checkSunday) checkDays.push(0);
1639
-
1640
- //Check if the message should be send today
1641
- checkDays.forEach(object => {
1642
- if ((object >= 0) && today == object) {
1643
- checkToday = true;
1644
- }
1645
- });
1707
+ const time = (this.config.checkSendOfflineTime).split(':');
1646
1708
 
1647
- if (checkDays.length >= 1) { // check if an day is selected
1648
- this.log.debug(`Number of selected days: ${checkDays.length}. Send Message on: ${(checkDays).join(', ')} ...`);
1649
- } else {
1650
- this.log.warn(`No days selected. Please check the instance configuration!`);
1651
- return; // break off function if no day is selected
1652
- }
1709
+ const checkDays = []; // list of selected days
1653
1710
 
1654
- // Check if the message for low battery was already sent today
1655
- const lastBatteryNotifyIndicator = await this.getOwnInitValue('info.lastBatteryNotification');
1711
+ // push the selected days in list
1712
+ if (this.config.checkOfflineMonday) checkDays.push(1);
1713
+ if (this.config.checkOfflineTuesday) checkDays.push(2);
1714
+ if (this.config.checkOfflineWednesday) checkDays.push(3);
1715
+ if (this.config.checkOfflineThursday) checkDays.push(4);
1716
+ if (this.config.checkOfflineFriday) checkDays.push(5);
1717
+ if (this.config.checkOfflineSaturday) checkDays.push(6);
1718
+ if (this.config.checkOfflineSunday) checkDays.push(0);
1656
1719
 
1657
- // set indicator for send message first to 'false', after sending to 'true'
1658
- if (now.getHours() < 11) await this.setStateAsync('info.lastBatteryNotification', false, true);
1720
+ if (checkDays.length >= 1) { // check if an day is selected
1721
+ this.log.debug(`Number of selected days for daily offline message: ${checkDays.length}. Send Message on: ${(checkDays).join(', ')} ...`);
1722
+ } else {
1723
+ this.log.warn(`No days selected for daily offline message. Please check the instance configuration!`);
1724
+ return; // cancel function if no day is selected
1725
+ }
1659
1726
 
1660
- // if time is > 11 (12:00 pm create message for low battery devices)
1661
- if ((now.getHours() > 11) && (!lastBatteryNotifyIndicator) && (checkToday != undefined)) {
1662
- let msg = '';
1727
+ if (!isUnloaded) {
1728
+ const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
1729
+ schedule.scheduleJob(cron, () => {
1730
+ try {
1731
+ let msg = '';
1663
1732
 
1664
- for (const id of this.batteryLowPowered) {
1665
- msg = '\n' + id['Device'] + ' (' + id['Battery'] + ')'.split(', ');
1666
- }
1733
+ for (const id of this.offlineDevices) {
1734
+ msg = `${msg}\n${id['Device']} (${id['Last contact']})`;
1735
+ }
1667
1736
 
1668
- if (this.lowBatteryPoweredCount > 0) {
1669
- this.log.info(`Niedrige Batteriezustände: ${msg}`);
1670
- await this.setStateAsync('lastNotification', `Niedrige Batteriezustände: ${msg}`, true);
1737
+ if (this.offlineDevicesCount > 0) {
1738
+ this.log.info(`Geräte Offline: ${msg}`);
1739
+ this.setStateAsync('lastNotification', `Geräte Offline: ${msg}`, true);
1671
1740
 
1672
- await this.sendNotification(`Niedriege Batteriezustände: ${msg}`);
1741
+ this.sendNotification(`Geräte Offline: ${msg}`);
1742
+ }
1673
1743
 
1674
- await this.setStateAsync('info.lastBatteryNotification', true, true);
1744
+ } catch (error) {
1745
+ this.errorReporting('[sendOfflineNotificationsShedule]', error);
1675
1746
  }
1676
- }
1677
- } catch (error) {
1678
- this.errorReporting('[sendOfflineMessage]', error);
1747
+ });
1679
1748
  }
1680
-
1681
- this.log.debug(`Finished the function: ${this.sendBatteryNotifications.name}`);
1682
- }//<--End of battery notification
1683
-
1749
+ }//<--End of daily offline notification
1684
1750
 
1685
1751
  async resetVars() {
1686
1752
  //Reset all arrays and counts
@@ -1809,79 +1875,407 @@ class DeviceWatcher extends utils.Adapter {
1809
1875
  </tr>`;
1810
1876
  }
1811
1877
 
1812
- html += '</table>';
1813
- return html;
1814
- }
1878
+ html += '</table>';
1879
+ return html;
1880
+ }
1881
+
1882
+ /**
1883
+ * @param {object} devices - Device
1884
+ * @param {number} deviceCount - Counted devices
1885
+ */
1886
+ async createOfflineListHTML(devices, deviceCount) {
1887
+ devices = devices.sort((a, b) => { return a.Device.localeCompare(b.Device); });
1888
+ let html = `<center>
1889
+ <b>Offline Devices: <font color=${deviceCount == 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
1890
+ <p></p>
1891
+ </center>
1892
+ <table width=100%>
1893
+ <tr>
1894
+ <th align=left>Device</th>
1895
+ <th align=center width=120>Adapter</th>
1896
+ <th align=center>Letzter Kontakt</th>
1897
+ </tr>
1898
+ <tr>
1899
+ <td colspan="5"><hr></td>
1900
+ </tr>`;
1901
+
1902
+ for (const device of devices) {
1903
+ html += `<tr>
1904
+ <td><font>${device.Device}</font></td>
1905
+ <td align=center><font>${device.Adapter}</font></td>
1906
+ <td align=center><font color=orange>${device['Last contact']}</font></td>
1907
+ </tr>`;
1908
+ }
1909
+
1910
+ html += '</table>';
1911
+ return html;
1912
+ }
1913
+
1914
+ /**
1915
+ * @param {object} [devices] - Device
1916
+ * @param {object} [deviceCount] - Counted devices
1917
+ * @param {object} [isLowBatteryList] - list Low Battery Devices
1918
+ */
1919
+ async createBatteryListHTML(devices, deviceCount, isLowBatteryList) {
1920
+ devices = devices.sort((a, b) => { return a.Device.localeCompare(b.Device); });
1921
+ let html = `<center>
1922
+ <b>${isLowBatteryList == true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList == true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
1923
+ <p></p>
1924
+ </center>
1925
+ <table width=100%>
1926
+ <tr>
1927
+ <th align=left>Device</th>
1928
+ <th align=center width=120>Adapter</th>
1929
+ <th align=${isLowBatteryList ? 'center' : 'right'}>Batterie</th>
1930
+ </tr>
1931
+ <tr>
1932
+ <td colspan="5"><hr></td>
1933
+ </tr>`;
1934
+
1935
+ for (const device of devices) {
1936
+ html += `<tr>
1937
+ <td><font>${device.Device}</font></td>
1938
+ <td align=center><font>${device.Adapter}</font></td>`;
1939
+
1940
+ if (isLowBatteryList) {
1941
+ html += `<td align=center><font color=orange>${device.Battery}</font></td>`;
1942
+ } else {
1943
+ html += `<td align=right><font color=#3bcf0e>${device.Battery}</font></td>`;
1944
+ }
1945
+
1946
+ html += `</tr>`;
1947
+ }
1948
+
1949
+ html += '</table>';
1950
+ return html;
1951
+ }
1952
+
1953
+ // create datapoints for each adapter
1954
+ /**
1955
+ * @param {object} adptName - Adaptername of devices
1956
+ **/
1957
+ async createDPsForEachAdapter(adptName) {
1958
+
1959
+ await this.setObjectNotExistsAsync(`${adptName}`, {
1960
+ type: 'channel',
1961
+ common: {
1962
+ name: adptName,
1963
+ },
1964
+ native: {},
1965
+ });
1966
+
1967
+ await this.setObjectNotExistsAsync(`${adptName}.offlineCount`, {
1968
+ 'type': 'state',
1969
+ 'common': {
1970
+ 'name': {
1971
+ 'en': 'Number of devices offline',
1972
+ 'de': 'Anzahl der Geräte offline',
1973
+ 'ru': 'Количество устройств offline',
1974
+ 'pt': 'Número de dispositivos offline',
1975
+ 'nl': 'Nummer van apparatuur offline',
1976
+ 'fr': 'Nombre de dispositifs hors ligne',
1977
+ 'it': 'Numero di dispositivi offline',
1978
+ 'es': 'Número de dispositivos sin conexión',
1979
+ 'pl': 'Ilość urządzeń offline',
1980
+ 'zh-cn': '线内装置数量'
1981
+ },
1982
+ 'type': 'number',
1983
+ 'role': 'value',
1984
+ 'read': true,
1985
+ 'write': false,
1986
+ },
1987
+ 'native': {}
1988
+ });
1989
+
1990
+ await this.setObjectNotExistsAsync(`${adptName}.offlineList`, {
1991
+ 'type': 'state',
1992
+ 'common': {
1993
+ 'name': {
1994
+ 'en': 'List of offline devices',
1995
+ 'de': 'Liste der Offline-Geräte',
1996
+ 'ru': 'Список оффлайн устройств',
1997
+ 'pt': 'Lista de dispositivos off-line',
1998
+ 'nl': 'List van offline apparatuur',
1999
+ 'fr': 'Liste des dispositifs hors ligne',
2000
+ 'it': 'Elenco dei dispositivi offline',
2001
+ 'es': 'Lista de dispositivos sin conexión',
2002
+ 'pl': 'Lista urządzeń offline',
2003
+ 'zh-cn': '线装置清单'
2004
+ },
2005
+ 'type': 'array',
2006
+ 'role': 'json',
2007
+ 'read': true,
2008
+ 'write': false,
2009
+ },
2010
+ 'native': {}
2011
+ });
2012
+
2013
+ await this.setObjectNotExistsAsync(`${adptName}.listAll`, {
2014
+ 'type': 'state',
2015
+ 'common': {
2016
+ 'name': {
2017
+ 'en': 'List of all devices',
2018
+ 'de': 'Liste aller Geräte',
2019
+ 'ru': 'Список всех устройств',
2020
+ 'pt': 'Lista de todos os dispositivos',
2021
+ 'nl': 'List van alle apparaten',
2022
+ 'fr': 'Liste de tous les dispositifs',
2023
+ 'it': 'Elenco di tutti i dispositivi',
2024
+ 'es': 'Lista de todos los dispositivos',
2025
+ 'pl': 'Lista wszystkich urządzeń',
2026
+ 'zh-cn': '所有装置清单'
2027
+ },
2028
+ 'type': 'array',
2029
+ 'role': 'json',
2030
+ 'read': true,
2031
+ 'write': false,
2032
+ },
2033
+ 'native': {}
2034
+ });
2035
+
2036
+ await this.setObjectNotExistsAsync(`${adptName}.linkQualityList`, {
2037
+ 'type': 'state',
2038
+ 'common': {
2039
+ 'name': {
2040
+ 'en': 'List of devices with signal strength',
2041
+ 'de': 'Liste der Geräte mit Signalstärke',
2042
+ 'ru': 'Список устройств с силой сигнала',
2043
+ 'pt': 'Lista de dispositivos com força de sinal',
2044
+ 'nl': 'List van apparaten met signaalkracht',
2045
+ 'fr': 'Liste des dispositifs avec force de signal',
2046
+ 'it': 'Elenco dei dispositivi con forza del segnale',
2047
+ 'es': 'Lista de dispositivos con fuerza de señal',
2048
+ 'pl': 'Lista urządzeń z siłą sygnałową',
2049
+ 'zh-cn': '具有信号实力的装置清单'
2050
+ },
2051
+ 'type': 'array',
2052
+ 'role': 'json',
2053
+ 'read': true,
2054
+ 'write': false,
2055
+ },
2056
+ 'native': {}
2057
+ });
2058
+
2059
+ await this.setObjectNotExistsAsync(`${adptName}.countAll`, {
2060
+ 'type': 'state',
2061
+ 'common': {
2062
+ 'name': {
2063
+ 'en': 'Number of all devices',
2064
+ 'de': 'Anzahl aller Geräte',
2065
+ 'ru': 'Количество всех устройств',
2066
+ 'pt': 'Número de todos os dispositivos',
2067
+ 'nl': 'Nummer van alle apparaten',
2068
+ 'fr': 'Nombre de tous les appareils',
2069
+ 'it': 'Numero di tutti i dispositivi',
2070
+ 'es': 'Número de todos los dispositivos',
2071
+ 'pl': 'Ilość wszystkich urządzeń',
2072
+ 'zh-cn': '所有装置的数目'
2073
+ },
2074
+ 'type': 'number',
2075
+ 'role': 'value',
2076
+ 'read': true,
2077
+ 'write': false,
2078
+ },
2079
+ 'native': {}
2080
+ });
2081
+
2082
+ await this.setObjectNotExistsAsync(`${adptName}.batteryList`, {
2083
+ 'type': 'state',
2084
+ 'common': {
2085
+ 'name': {
2086
+ 'en': 'List of devices with battery state',
2087
+ 'de': 'Liste der Geräte mit Batteriezustand',
2088
+ 'ru': 'Список устройств с состоянием батареи',
2089
+ 'pt': 'Lista de dispositivos com estado da bateria',
2090
+ 'nl': 'List van apparaten met batterij staat',
2091
+ 'fr': 'Liste des appareils avec état de batterie',
2092
+ 'it': 'Elenco dei dispositivi con stato della batteria',
2093
+ 'es': 'Lista de dispositivos con estado de batería',
2094
+ 'pl': 'Lista urządzeń z baterią stanową',
2095
+ 'zh-cn': '电池国装置清单'
2096
+ },
2097
+ 'type': 'array',
2098
+ 'role': 'json',
2099
+ 'read': true,
2100
+ 'write': false,
2101
+ },
2102
+ 'native': {}
2103
+ });
1815
2104
 
1816
- /**
1817
- * @param {object} devices - Device
1818
- * @param {number} deviceCount - Counted devices
1819
- */
1820
- async createOfflineListHTML(devices, deviceCount) {
1821
- devices = devices.sort((a, b) => { return a.Device.localeCompare(b.Device); });
1822
- let html = `<center>
1823
- <b>Offline Devices: <font color=${deviceCount == 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
1824
- <p></p>
1825
- </center>
1826
- <table width=100%>
1827
- <tr>
1828
- <th align=left>Device</th>
1829
- <th align=center width=120>Adapter</th>
1830
- <th align=center>Letzter Kontakt</th>
1831
- </tr>
1832
- <tr>
1833
- <td colspan="5"><hr></td>
1834
- </tr>`;
2105
+ await this.setObjectNotExistsAsync(`${adptName}.lowBatteryList`, {
2106
+ 'type': 'state',
2107
+ 'common': {
2108
+ 'name': {
2109
+ 'en': 'List of devices with low battery state',
2110
+ 'de': 'Liste der Geräte mit niedrigem Batteriezustand',
2111
+ 'ru': 'Список устройств с низким состоянием батареи',
2112
+ 'pt': 'Lista de dispositivos com baixo estado da bateria',
2113
+ 'nl': 'List van apparaten met lage batterij staat',
2114
+ 'fr': 'Liste des appareils à faible état de batterie',
2115
+ 'it': 'Elenco di dispositivi con stato di batteria basso',
2116
+ 'es': 'Lista de dispositivos con estado de batería bajo',
2117
+ 'pl': 'Lista urządzeń o niskim stanie baterii',
2118
+ 'zh-cn': '低电池国家装置清单'
2119
+ },
2120
+ 'type': 'array',
2121
+ 'role': 'json',
2122
+ 'read': true,
2123
+ 'write': false,
2124
+ },
2125
+ 'native': {}
2126
+ });
1835
2127
 
1836
- for (const device of devices) {
1837
- html += `<tr>
1838
- <td><font>${device.Device}</font></td>
1839
- <td align=center><font>${device.Adapter}</font></td>
1840
- <td align=center><font color=orange>${device['Last contact']}</font></td>
1841
- </tr>`;
1842
- }
2128
+ await this.setObjectNotExistsAsync(`${adptName}.lowBatteryCount`, {
2129
+ 'type': 'state',
2130
+ 'common': {
2131
+ 'name': {
2132
+ 'en': 'Number of devices with low battery',
2133
+ 'de': 'Anzahl der Geräte mit niedriger Batterie',
2134
+ 'ru': 'Количество устройств c низкой батареей',
2135
+ 'pt': 'Número de dispositivos com bateria baixa',
2136
+ 'nl': 'Nummer van apparaten met lage batterij',
2137
+ 'fr': 'Nombre de dispositifs avec batterie basse',
2138
+ 'it': 'Numero di dispositivi con batteria bassa',
2139
+ 'es': 'Número de dispositivos con batería baja',
2140
+ 'pl': 'Liczba urządzeń z niską baterią',
2141
+ 'zh-cn': '低电池的装置数量'
2142
+ },
2143
+ 'type': 'number',
2144
+ 'role': 'value',
2145
+ 'read': true,
2146
+ 'write': false,
2147
+ },
2148
+ 'native': {}
2149
+ });
1843
2150
 
1844
- html += '</table>';
1845
- return html;
2151
+ await this.setObjectNotExistsAsync(`${adptName}.batteryCount`, {
2152
+ 'type': 'state',
2153
+ 'common': {
2154
+ 'name': {
2155
+ 'en': 'Number of devices with battery',
2156
+ 'de': 'Anzahl der Geräte mit Batterie',
2157
+ 'ru': 'Количество устройств c батареей',
2158
+ 'pt': 'Número de dispositivos com bateria',
2159
+ 'nl': 'Nummer van apparaten met batterij',
2160
+ 'fr': 'Nombre de dispositifs avec batterie',
2161
+ 'it': 'Numero di dispositivi con batteria',
2162
+ 'es': 'Número de dispositivos con batería',
2163
+ 'pl': 'Liczba urządzeń z baterią',
2164
+ 'zh-cn': '电池的装置数量'
2165
+ },
2166
+ 'type': 'number',
2167
+ 'role': 'value',
2168
+ 'read': true,
2169
+ 'write': false,
2170
+ },
2171
+ 'native': {}
2172
+ });
1846
2173
  }
1847
2174
 
1848
2175
  /**
1849
- * @param {object} [devices] - Device
1850
- * @param {object} [deviceCount] - Counted devices
1851
- * @param {object} [isLowBatteryList] - list Low Battery Devices
1852
- */
1853
- async createBatteryListHTML(devices, deviceCount, isLowBatteryList) {
1854
- devices = devices.sort((a, b) => { return a.Device.localeCompare(b.Device); });
1855
- let html = `<center>
1856
- <b>${isLowBatteryList == true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList == true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
1857
- <p></p>
1858
- </center>
1859
- <table width=100%>
1860
- <tr>
1861
- <th align=left>Device</th>
1862
- <th align=center width=120>Adapter</th>
1863
- <th align=${isLowBatteryList ? 'center' : 'right'}>Batterie</th>
1864
- </tr>
1865
- <tr>
1866
- <td colspan="5"><hr></td>
1867
- </tr>`;
2176
+ * @param {object} [adptName] - Adaptername of devices
2177
+ **/
2178
+ async createHtmlListDatapoints(adptName) {
1868
2179
 
1869
- for (const device of devices) {
1870
- html += `<tr>
1871
- <td><font>${device.Device}</font></td>
1872
- <td align=center><font>${device.Adapter}</font></td>`;
2180
+ let dpSubFolder;
2181
+ //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
2182
+ if (adptName) {
2183
+ dpSubFolder = `${adptName}.`;
2184
+ } else {
2185
+ dpSubFolder = '';
2186
+ }
1873
2187
 
1874
- if (isLowBatteryList) {
1875
- html += `<td align=center><font color=orange>${device.Battery}</font></td>`;
1876
- } else {
1877
- html += `<td align=right><font color=#3bcf0e>${device.Battery}</font></td>`;
1878
- }
2188
+ await this.setObjectNotExistsAsync(`${dpSubFolder}offlineListHTML`, {
2189
+ 'type': 'state',
2190
+ 'common': {
2191
+ 'name': {
2192
+ 'en': 'HTML List of offline devices',
2193
+ 'de': 'HTML Liste der Offline-Geräte',
2194
+ 'ru': 'HTML Список оффлайн устройств',
2195
+ 'pt': 'HTML Lista de dispositivos off-line',
2196
+ 'nl': 'HTML List van offline apparatuur',
2197
+ 'fr': 'HTML Liste des dispositifs hors ligne',
2198
+ 'it': 'HTML Elenco dei dispositivi offline',
2199
+ 'es': 'HTML Lista de dispositivos sin conexión',
2200
+ 'pl': 'HTML Lista urządzeń offline',
2201
+ 'zh-cn': 'HTML 线装置清单'
2202
+ },
2203
+ 'type': 'string',
2204
+ 'role': 'html',
2205
+ 'read': true,
2206
+ 'write': false,
2207
+ },
2208
+ 'native': {}
2209
+ });
1879
2210
 
1880
- html += `</tr>`;
1881
- }
2211
+ await this.setObjectNotExistsAsync(`${dpSubFolder}linkQualityListHTML`, {
2212
+ 'type': 'state',
2213
+ 'common': {
2214
+ 'name': {
2215
+ 'en': 'HTML List of devices with signal strength',
2216
+ 'de': 'HTML Liste der Geräte mit Signalstärke',
2217
+ 'ru': 'HTML Список устройств с силой сигнала',
2218
+ 'pt': 'HTML Lista de dispositivos com força de sinal',
2219
+ 'nl': 'HTML List van apparaten met signaalkracht',
2220
+ 'fr': 'HTML Liste des dispositifs avec force de signal',
2221
+ 'it': 'HTML Elenco dei dispositivi con forza del segnale',
2222
+ 'es': 'HTML Lista de dispositivos con fuerza de señal',
2223
+ 'pl': 'HTML Lista urządzeń z siłą sygnałową',
2224
+ 'zh-cn': 'HTML 具有信号实力的装置清单'
2225
+ },
2226
+ 'type': 'string',
2227
+ 'role': 'value',
2228
+ 'read': true,
2229
+ 'write': false,
2230
+ },
2231
+ 'native': {}
2232
+ });
1882
2233
 
1883
- html += '</table>';
1884
- return html;
2234
+ await this.setObjectNotExistsAsync(`${dpSubFolder}batteryListHTML`, {
2235
+ 'type': 'state',
2236
+ 'common': {
2237
+ 'name': {
2238
+ 'en': 'HTML List of devices with battery state',
2239
+ 'de': 'HTML Liste der Geräte mit Batteriezustand',
2240
+ 'ru': 'HTML Список устройств с состоянием батареи',
2241
+ 'pt': 'HTML Lista de dispositivos com estado da bateria',
2242
+ 'nl': 'HTML List van apparaten met batterij staat',
2243
+ 'fr': 'HTML Liste des appareils avec état de batterie',
2244
+ 'it': 'HTML Elenco dei dispositivi con stato della batteria',
2245
+ 'es': 'HTML Lista de dispositivos con estado de batería',
2246
+ 'pl': 'HTML Lista urządzeń z baterią stanową',
2247
+ 'zh-cn': 'HTML 电池国装置清单'
2248
+ },
2249
+ 'type': 'string',
2250
+ 'role': 'html',
2251
+ 'read': true,
2252
+ 'write': false,
2253
+ },
2254
+ 'native': {}
2255
+ });
2256
+
2257
+ await this.setObjectNotExistsAsync(`${dpSubFolder}lowBatteryListHTML`, {
2258
+ 'type': 'state',
2259
+ 'common': {
2260
+ 'name': {
2261
+ 'en': 'HTML List of devices with low battery state',
2262
+ 'de': 'HTML Liste der Geräte mit niedrigem Batteriezustand',
2263
+ 'ru': 'HTML Список устройств с низким состоянием батареи',
2264
+ 'pt': 'HTML Lista de dispositivos com baixo estado da bateria',
2265
+ 'nl': 'HTML List van apparaten met lage batterij staat',
2266
+ 'fr': 'HTML Liste des appareils à faible état de batterie',
2267
+ 'it': 'HTML Elenco di dispositivi con stato di batteria basso',
2268
+ 'es': 'HTML Lista de dispositivos con estado de batería bajo',
2269
+ 'pl': 'HTML Lista urządzeń o niskim stanie baterii',
2270
+ 'zh-cn': 'HTML 低电池国家装置清单'
2271
+ },
2272
+ 'type': 'string',
2273
+ 'role': 'html',
2274
+ 'read': true,
2275
+ 'write': false,
2276
+ },
2277
+ 'native': {}
2278
+ });
1885
2279
  }
1886
2280
 
1887
2281
  /**
@@ -1909,12 +2303,13 @@ class DeviceWatcher extends utils.Adapter {
1909
2303
  */
1910
2304
  onUnload(callback) {
1911
2305
  try {
1912
- this.log.info('cleaned everything up...');
1913
-
1914
2306
  if (this.refreshDataTimeout) {
1915
2307
  this.log.debug('clearing refresh timeout');
1916
2308
  this.clearTimeout(this.refreshDataTimeout);
1917
2309
  }
2310
+ isUnloaded = true;
2311
+
2312
+ this.log.info('cleaned everything up...');
1918
2313
 
1919
2314
  callback();
1920
2315
  } catch (e) {