iobroker.device-watcher 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/main.js CHANGED
@@ -10,7 +10,7 @@ const schedule = require('node-schedule');
10
10
  const arrApart = require('./lib/arrApart.js'); // list of supported adapters
11
11
 
12
12
  // Sentry error reporting, disable when testing code!
13
- const enableSendSentry = false;
13
+ const enableSendSentry = true;
14
14
 
15
15
  // indicator if the adapter is running or not (for intervall/shedule)
16
16
  let isUnloaded = false;
@@ -32,7 +32,7 @@ class DeviceWatcher extends utils.Adapter {
32
32
  this.blacklistLists = [];
33
33
  this.blacklistAdapterLists = [];
34
34
  this.blacklistNotify = [];
35
- this.arrDev = [];
35
+ this.selAdapter = [];
36
36
  this.adapterSelected = [];
37
37
  this.upgradableList = [];
38
38
 
@@ -40,6 +40,7 @@ class DeviceWatcher extends utils.Adapter {
40
40
  this.listAllDevicesRaw = [];
41
41
  this.batteryLowPoweredRaw = [];
42
42
  this.offlineDevicesRaw = [];
43
+ this.upgradableDevicesRaw = [];
43
44
 
44
45
  // counts
45
46
  this.offlineDevicesCount = 0;
@@ -65,14 +66,12 @@ class DeviceWatcher extends utils.Adapter {
65
66
  async onReady() {
66
67
  this.log.debug(`Adapter ${adapterName} was started`);
67
68
 
68
- isUnloaded = false;
69
-
70
69
  try {
71
70
  this.listOnlyBattery = this.config.listOnlyBattery;
72
71
  this.createOwnFolder = this.config.createOwnFolder;
73
72
  this.createHtmlList = this.config.createHtmlList;
74
73
 
75
- this.supAdapter = {
74
+ this.configSetAdapter = {
76
75
  alexa2: this.config.alexa2Devices,
77
76
  apcups: this.config.apcupsDevices,
78
77
  ble: this.config.bleDevices,
@@ -86,6 +85,7 @@ class DeviceWatcher extends utils.Adapter {
86
85
  harmony: this.config.harmonyDevices,
87
86
  hmiP: this.config.hmiPDevices,
88
87
  hmrpc: this.config.hmrpcDevices,
88
+ homeconnect: this.config.homeconnectDevices,
89
89
  hs100: this.config.hs100Devices,
90
90
  hue: this.config.hueDevices,
91
91
  hueExt: this.config.hueExtDevices,
@@ -106,6 +106,7 @@ class DeviceWatcher extends utils.Adapter {
106
106
  ping: this.config.pingDevices,
107
107
  roomba: this.config.roombaDevices,
108
108
  shelly: this.config.shellyDevices,
109
+ smartgarden: this.config.smartgardenDevices,
109
110
  sonoff: this.config.sonoffDevices,
110
111
  sonos: this.config.sonosDevices,
111
112
  sureflap: this.config.sureflapDevices,
@@ -121,7 +122,7 @@ class DeviceWatcher extends utils.Adapter {
121
122
  zwave: this.config.zwaveDevices,
122
123
  };
123
124
 
124
- this.maxMinutes = {
125
+ this.configMaxMinutes = {
125
126
  alexa2: this.config.alexa2MaxMinutes,
126
127
  apcups: this.config.apcupsMaxMinutes,
127
128
  ble: this.config.bleMaxMinutes,
@@ -135,6 +136,7 @@ class DeviceWatcher extends utils.Adapter {
135
136
  harmony: this.config.harmonyMaxMinutes,
136
137
  hmiP: this.config.hmiPMaxMinutes,
137
138
  hmrpc: this.config.hmrpcMaxMinutes,
139
+ homeconnect: this.config.homeconnectMaxMinutes,
138
140
  hs100: this.config.hs100MaxMinutes,
139
141
  hue: this.config.hueMaxMinutes,
140
142
  hueExt: this.config.hueextMaxMinutes,
@@ -155,6 +157,7 @@ class DeviceWatcher extends utils.Adapter {
155
157
  ping: this.config.pingMaxMinutes,
156
158
  roomba: this.config.roombaMaxMinutes,
157
159
  shelly: this.config.shellyMaxMinutes,
160
+ smartgarden: this.config.smartgardenMaxMinutes,
158
161
  sonoff: this.config.sonoffMaxMinutes,
159
162
  sonos: this.config.sonosMaxMinutes,
160
163
  sureflap: this.config.sureflapMaxMinutes,
@@ -171,20 +174,16 @@ class DeviceWatcher extends utils.Adapter {
171
174
  };
172
175
 
173
176
  for (const [id] of Object.entries(arrApart)) {
174
- if (!isUnloaded) {
175
- if (this.supAdapter[id]) {
176
- this.arrDev.push(arrApart[id]);
177
- this.adapterSelected.push(await this.capitalize(id));
178
- }
179
- } else {
180
- return; // cancel run if unloaded was called.
177
+ if (this.configSetAdapter[id]) {
178
+ this.selAdapter.push(arrApart[id]);
179
+ this.adapterSelected.push(await this.capitalize(id));
181
180
  }
182
181
  }
183
182
 
184
183
  //Check if an Adapter is selected.
185
184
  if (this.adapterSelected.length >= 1) {
186
185
  // show list in debug log
187
- this.log.debug(JSON.stringify(this.arrDev));
186
+ this.log.debug(JSON.stringify(this.selAdapter));
188
187
 
189
188
  this.log.info(`Number of selected adapters: ${this.adapterSelected.length}. Loading data from: ${this.adapterSelected.join(', ')} ...`);
190
189
  } else {
@@ -203,7 +202,7 @@ class DeviceWatcher extends utils.Adapter {
203
202
  if (this.createOwnFolder) {
204
203
  try {
205
204
  for (const [id] of Object.entries(arrApart)) {
206
- if (this.supAdapter !== undefined && this.supAdapter[id]) {
205
+ if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
207
206
  await this.createDPsForEachAdapter(id);
208
207
  if (this.createHtmlList) await this.createHtmlListDatapoints(id);
209
208
  this.log.debug(`Created datapoints for ${this.capitalize(id)}`);
@@ -214,7 +213,7 @@ class DeviceWatcher extends utils.Adapter {
214
213
  }
215
214
  }
216
215
 
217
- // create HTML list
216
+ // create HTML list datapoints
218
217
  if (this.createHtmlList) await this.createHtmlListDatapoints();
219
218
 
220
219
  //read data first at start
@@ -251,15 +250,28 @@ class DeviceWatcher extends utils.Adapter {
251
250
  let contactData;
252
251
  let oldStatus;
253
252
  let isLowBatValue;
253
+ let instanceDeviceConnectionDpTS;
254
+ const instanceDeviceConnectionDpTSminTime = 5;
255
+
256
+ // Wait if the conection to device was lost to avoid multiple messages.
257
+ // const delay = (n) => new Promise((r) => setTimeout(r, n * 100));
254
258
 
255
259
  for (const device of this.listAllDevicesRaw) {
256
260
  // On statechange update available datapoint
257
261
  switch (id) {
262
+ case device.instanceDeviceConnectionDP:
263
+ if (state.val !== device.instancedeviceConnected) {
264
+ device.instancedeviceConnected = state.val;
265
+ }
266
+ break;
267
+
258
268
  case device.UpdateDP:
259
- if (state.val) {
269
+ if (state.val !== device.Upgradable) {
260
270
  device.Upgradable = state.val;
261
- if (!this.blacklistNotify.includes(device.Path)) {
262
- await this.sendDeviceUpdatesNotification(device.Device, device.Adapter);
271
+ if (state.val) {
272
+ if (!this.blacklistNotify.includes(device.Path)) {
273
+ await this.sendDeviceUpdatesNotification(device.Device, device.Adapter);
274
+ }
263
275
  }
264
276
  }
265
277
  break;
@@ -340,9 +352,17 @@ class DeviceWatcher extends utils.Adapter {
340
352
  device.Status = contactData[1];
341
353
  device.SignalStrength = contactData[2];
342
354
  }
343
-
344
- if (this.config.checkSendOfflineMsg && oldStatus !== device.Status && !this.blacklistNotify.includes(device.Path)) {
345
- await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
355
+ if (device.instanceDeviceConnectionDP !== undefined) {
356
+ instanceDeviceConnectionDpTS = await this.getTimestampConnectionDP(device.instanceDeviceConnectionDP);
357
+ if (device.instancedeviceConnected !== false && instanceDeviceConnectionDpTS && instanceDeviceConnectionDpTS >= instanceDeviceConnectionDpTSminTime) {
358
+ if (this.config.checkSendOfflineMsg && oldStatus !== device.Status && !this.blacklistNotify.includes(device.Path)) {
359
+ await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
360
+ }
361
+ }
362
+ } else {
363
+ if (this.config.checkSendOfflineMsg && oldStatus !== device.Status && !this.blacklistNotify.includes(device.Path)) {
364
+ await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
365
+ }
346
366
  }
347
367
  break;
348
368
  }
@@ -390,6 +410,37 @@ class DeviceWatcher extends utils.Adapter {
390
410
  }
391
411
  }
392
412
 
413
+ /**
414
+ * main function
415
+ */
416
+ async main() {
417
+ this.log.debug(`Function started: ${this.main.name}`);
418
+
419
+ // fill counts and lists of all selected adapter
420
+ try {
421
+ await this.createDataOfAllAdapter();
422
+ this.log.debug(`Created and filled data for all adapters`);
423
+ } catch (error) {
424
+ this.errorReporting('[main - create data of all adapter]', error);
425
+ }
426
+
427
+ // fill datapoints for each adapter if selected
428
+ if (this.createOwnFolder) {
429
+ try {
430
+ for (const [id] of Object.entries(arrApart)) {
431
+ if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
432
+ await this.createDataForEachAdapter(id);
433
+ this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
434
+ }
435
+ }
436
+ } catch (error) {
437
+ this.errorReporting('[main - create and fill datapoints for each adapter]', error);
438
+ }
439
+ }
440
+
441
+ this.log.debug(`Function finished: ${this.main.name}`);
442
+ } //<--End of main function
443
+
393
444
  /**
394
445
  * refresh data with interval
395
446
  * is neccessary to refresh lastContact data, especially of devices without state changes
@@ -403,7 +454,7 @@ class DeviceWatcher extends utils.Adapter {
403
454
 
404
455
  if (this.createOwnFolder) {
405
456
  for (const [id] of Object.entries(arrApart)) {
406
- if (this.supAdapter !== undefined && this.supAdapter[id]) {
457
+ if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
407
458
  await this.createLists(id);
408
459
  await this.writeDatapoints(id);
409
460
  this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
@@ -429,117 +480,286 @@ class DeviceWatcher extends utils.Adapter {
429
480
  } // <-- refreshData end
430
481
 
431
482
  /**
432
- * main function
483
+ * create blacklist
433
484
  */
434
- async main() {
435
- this.log.debug(`Function started: ${this.main.name}`);
485
+ async createBlacklist() {
486
+ this.log.debug(`Function started: ${this.createBlacklist.name}`);
436
487
 
437
- // fill counts and lists of all selected adapter
438
- try {
439
- await this.createDataOfAllAdapter();
440
- this.log.debug(`Created and filled data for all adapters`);
441
- } catch (error) {
442
- this.errorReporting('[main - create data of all adapter]', error);
443
- }
488
+ const myBlacklist = this.config.tableBlacklist;
444
489
 
445
- // fill datapoints for each adapter if selected
446
- if (this.createOwnFolder) {
490
+ for (const i in myBlacklist) {
447
491
  try {
448
- for (const [id] of Object.entries(arrApart)) {
449
- if (this.supAdapter !== undefined && this.supAdapter[id]) {
450
- await this.createDataForEachAdapter(id);
451
- this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
452
- }
492
+ const blacklistParse = await this.parseData(myBlacklist[i].devices);
493
+ // push devices in list to ignor device in lists
494
+ if (myBlacklist[i].checkIgnorLists) {
495
+ this.blacklistLists.push(blacklistParse.path);
496
+ }
497
+ if (myBlacklist[i].checkIgnorAdapterLists) {
498
+ this.blacklistAdapterLists.push(blacklistParse.path);
499
+ }
500
+ // push devices in list to ignor device in notifications
501
+ if (myBlacklist[i].checkIgnorNotify) {
502
+ this.blacklistNotify.push(blacklistParse.path);
453
503
  }
454
504
  } catch (error) {
455
- this.errorReporting('[main - create and fill datapoints for each adapter]', error);
505
+ this.errorReporting('[createBlacklist]', error);
456
506
  }
457
507
  }
458
508
 
459
- this.log.debug(`Function finished: ${this.main.name}`);
460
- } //<--End of main function
509
+ if (this.blacklistLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistLists}`);
510
+ if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistAdapterLists}`);
511
+ if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notificatioons: ${this.blacklistNotify}`);
461
512
 
462
- /**
463
- * @param {string} id - id which should be capitalize
464
- */
465
- capitalize(id) {
466
- //make the first letter uppercase
467
- return id && id[0].toUpperCase() + id.slice(1);
513
+ this.log.debug(`Function finished: ${this.createBlacklist.name}`);
468
514
  }
469
515
 
470
516
  /**
471
- * @param {number} dpValue - get Time of this datapoint
517
+ * @param {object} i - Device Object
472
518
  */
473
- async getTimestamp(dpValue) {
474
- const time = new Date();
475
- return (dpValue = Math.round((time.getTime() - dpValue) / 1000 / 60));
476
- }
519
+ async createData(i) {
520
+ const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
521
+ const adapterID = this.selAdapter[i].adapterID;
477
522
 
478
- /**
479
- * @param {object} obj - State of datapoint
480
- */
481
- async getInitValue(obj) {
482
- //state can be null or undefinded
483
- const foreignState = await this.getForeignStateAsync(obj);
484
- if (foreignState) return foreignState.val;
485
- }
523
+ /*---------- Start of loop ----------*/
524
+ for (const [id] of Object.entries(devices)) {
525
+ /*=============================================
526
+ = get Instanz =
527
+ =============================================*/
528
+ const instance = id.slice(0, id.indexOf('.') + 2);
529
+ const instanceDeviceConnectionDP = `${instance}.info.connection`;
530
+ const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
531
+ this.subscribeForeignStates(instanceDeviceConnectionDP);
486
532
 
487
- /**
488
- * @param {object} obj - State of own datapoint
489
- */
490
- async getOwnInitValue(obj) {
491
- //state can be null or undefinded for own states
492
- const stateVal = await this.getStateAsync(obj);
493
- if (stateVal) return stateVal.val;
494
- }
533
+ /*=============================================
534
+ = Get device name =
535
+ =============================================*/
536
+ const deviceName = await this.getDeviceName(id, i);
495
537
 
496
- /**
497
- * @param {object} data - object
498
- */
499
- async parseData(data) {
500
- if (!data) return {};
501
- if (typeof data === 'object') return data;
502
- if (typeof data === 'string') return JSON.parse(data);
503
- return {};
504
- }
538
+ /*=============================================
539
+ = Get adapter name =
540
+ =============================================*/
541
+ const adapter = this.selAdapter[i].adapter;
505
542
 
506
- /**
507
- * create blacklist
508
- */
509
- async createBlacklist() {
510
- this.log.debug(`Function started: ${this.createBlacklist.name}`);
543
+ /*=============================================
544
+ = Get path to datapoints =
545
+ =============================================*/
546
+ const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
547
+ const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
511
548
 
512
- if (!isUnloaded) {
513
- const myBlacklist = this.config.tableBlacklist;
549
+ /*=============================================
550
+ = Get signal strength =
551
+ =============================================*/
552
+ let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
553
+ let deviceQualityState;
514
554
 
515
- for (const i in myBlacklist) {
516
- try {
517
- const blacklistParse = await this.parseData(myBlacklist[i].devices);
518
- // push devices in list to ignor device in lists
519
- if (myBlacklist[i].checkIgnorLists) {
520
- this.blacklistLists.push(blacklistParse.path);
521
- }
522
- if (myBlacklist[i].checkIgnorAdapterLists) {
523
- this.blacklistAdapterLists.push(blacklistParse.path);
524
- }
525
- // push devices in list to ignor device in notifications
526
- if (myBlacklist[i].checkIgnorNotify) {
527
- this.blacklistNotify.push(blacklistParse.path);
555
+ switch (adapterID) {
556
+ case 'mihomeVacuum':
557
+ deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
558
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
559
+ break;
560
+
561
+ case 'netatmo':
562
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
563
+ if (!deviceQualityState) {
564
+ deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
565
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
528
566
  }
529
- } catch (error) {
530
- this.errorReporting('[createBlacklist]', error);
567
+ break;
568
+
569
+ default:
570
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
571
+ break;
572
+ }
573
+ //subscribe to states
574
+ this.subscribeForeignStates(deviceQualityDP);
575
+
576
+ let linkQuality = await this.calculateSignalStrength(deviceQualityState, adapterID);
577
+
578
+ /*=============================================
579
+ = Get battery data =
580
+ =============================================*/
581
+ let deviceBatteryStateDP;
582
+ let deviceBatteryState;
583
+ let batteryHealth;
584
+ let batteryHealthRaw;
585
+ let lowBatIndicator;
586
+ let isBatteryDevice;
587
+ let isLowBatDP;
588
+ let faultReportingDP;
589
+ let faultReportingState;
590
+
591
+ const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
592
+ const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
593
+
594
+ if (deviceChargerState === undefined || deviceChargerState === false) {
595
+ // Get battery states
596
+ switch (adapterID) {
597
+ case 'hueExt':
598
+ case 'mihomeVacuum':
599
+ case 'mqttNuki':
600
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
601
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
602
+ if (deviceBatteryState === undefined) {
603
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
604
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
605
+ }
606
+ break;
607
+ default:
608
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
609
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
610
+ if (deviceBatteryState === undefined) {
611
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
612
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
613
+ }
614
+ break;
615
+ }
616
+
617
+ // Get low bat states
618
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
619
+ let deviceLowBatState = await this.getInitValue(isLowBatDP);
620
+ if (deviceLowBatState === undefined) {
621
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
622
+ deviceLowBatState = await this.getInitValue(isLowBatDP);
623
+ }
624
+ if (deviceLowBatState === undefined) isLowBatDP = 'none';
625
+
626
+ faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
627
+ faultReportingState = await this.getInitValue(faultReportingDP);
628
+
629
+ //subscribe to states
630
+ this.subscribeForeignStates(deviceBatteryStateDP);
631
+ this.subscribeForeignStates(isLowBatDP);
632
+ this.subscribeForeignStates(faultReportingDP);
633
+
634
+ const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, adapterID);
635
+ batteryHealth = batteryData[0];
636
+ batteryHealthRaw = batteryData[2];
637
+ isBatteryDevice = batteryData[1];
638
+
639
+ if (isBatteryDevice) {
640
+ lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
531
641
  }
532
642
  }
533
643
 
534
- if (this.blacklistLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistLists}`);
535
- if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistAdapterLists}`);
536
- if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notificatioons: ${this.blacklistNotify}`);
537
- } else {
538
- return; // cancel run if unloaded was called.
539
- }
644
+ /*=============================================
645
+ = Get last contact of device =
646
+ =============================================*/
647
+ let unreachDP = currDeviceString + this.selAdapter[i].reach;
648
+ const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
649
+ const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
650
+ const timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
651
+
652
+ let deviceUnreachState = await this.getInitValue(unreachDP);
653
+ if (deviceUnreachState === undefined) {
654
+ unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
655
+ deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
656
+ }
540
657
 
541
- this.log.debug(`Function finished: ${this.createBlacklist.name}`);
542
- }
658
+ // subscribe to states
659
+ this.subscribeForeignStates(timeSelector);
660
+ this.subscribeForeignStates(unreachDP);
661
+ this.subscribeForeignStates(deviceStateSelectorDP);
662
+ this.subscribeForeignStates(rssiPeerSelectorDP);
663
+
664
+ const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
665
+ let deviceState;
666
+ let lastContactString;
667
+
668
+ if (onlineState) {
669
+ lastContactString = onlineState[0];
670
+ deviceState = onlineState[1];
671
+ linkQuality = onlineState[2];
672
+ }
673
+
674
+ /*=============================================
675
+ = Get update data =
676
+ =============================================*/
677
+ const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
678
+ let isUpgradable;
679
+
680
+ if (this.config.checkSendDeviceUpgrade) {
681
+ const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
682
+
683
+ if (deviceUpdateSelector) {
684
+ isUpgradable = true;
685
+ } else if (!deviceUpdateSelector) {
686
+ isUpgradable = false;
687
+ }
688
+ // subscribe to states
689
+ this.subscribeForeignStates(deviceUpdateDP);
690
+ }
691
+
692
+ /*=============================================
693
+ = Fill Raw Lists =
694
+ =============================================*/
695
+
696
+ /* Add only devices with battery in the rawlist */
697
+ if (this.listOnlyBattery) {
698
+ if (isBatteryDevice) {
699
+ this.listAllDevicesRaw.push({
700
+ Path: id,
701
+ instanceDeviceConnectionDP: instanceDeviceConnectionDP,
702
+ instancedeviceConnected: instancedeviceConnected,
703
+ Device: deviceName,
704
+ adapterID: adapterID,
705
+ Adapter: adapter,
706
+ timeSelector: timeSelector,
707
+ isBatteryDevice: isBatteryDevice,
708
+ Battery: batteryHealth,
709
+ BatteryRaw: batteryHealthRaw,
710
+ batteryDP: deviceBatteryStateDP,
711
+ LowBat: lowBatIndicator,
712
+ LowBatDP: isLowBatDP,
713
+ faultReport: faultReportingState,
714
+ faultReportDP: faultReportingDP,
715
+ SignalStrengthDP: deviceQualityDP,
716
+ SignalStrength: linkQuality,
717
+ UnreachState: deviceUnreachState,
718
+ UnreachDP: unreachDP,
719
+ DeviceStateSelectorDP: deviceStateSelectorDP,
720
+ rssiPeerSelectorDP: rssiPeerSelectorDP,
721
+ LastContact: lastContactString,
722
+ Status: deviceState,
723
+ UpdateDP: deviceUpdateDP,
724
+ Upgradable: isUpgradable,
725
+ });
726
+ }
727
+ } else {
728
+ /* Add all devices */
729
+ this.listAllDevicesRaw.push({
730
+ Path: id,
731
+ instanceDeviceConnectionDP: instanceDeviceConnectionDP,
732
+ instancedeviceConnected: instancedeviceConnected,
733
+ Device: deviceName,
734
+ adapterID: adapterID,
735
+ Adapter: adapter,
736
+ timeSelector: timeSelector,
737
+ isBatteryDevice: isBatteryDevice,
738
+ Battery: batteryHealth,
739
+ BatteryRaw: batteryHealthRaw,
740
+ batteryDP: deviceBatteryStateDP,
741
+ LowBat: lowBatIndicator,
742
+ LowBatDP: isLowBatDP,
743
+ faultReport: faultReportingState,
744
+ faultReportDP: faultReportingDP,
745
+ SignalStrengthDP: deviceQualityDP,
746
+ SignalStrength: linkQuality,
747
+ UnreachState: deviceUnreachState,
748
+ UnreachDP: unreachDP,
749
+ DeviceStateSelectorDP: deviceStateSelectorDP,
750
+ rssiPeerSelectorDP: rssiPeerSelectorDP,
751
+ LastContact: lastContactString,
752
+ Status: deviceState,
753
+ UpdateDP: deviceUpdateDP,
754
+ Upgradable: isUpgradable,
755
+ });
756
+ }
757
+ } // <-- end of loop
758
+ } // <-- end of createData
759
+
760
+ /*=============================================
761
+ = functions to get data =
762
+ =============================================*/
543
763
 
544
764
  /**
545
765
  * @param {object} id - deviceID
@@ -559,25 +779,9 @@ class DeviceWatcher extends utils.Adapter {
559
779
  let folderName;
560
780
  let deviceID;
561
781
 
562
- switch (this.arrDev[i].adapterID) {
563
- // Get ID with currDeviceString from datapoint
564
- case 'switchbotBle':
565
- case 'esphome':
566
- case 'apcups':
567
- deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
568
- break;
569
-
570
- case 'eusec':
571
- deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
572
- if (deviceName === null || deviceName === undefined) {
573
- if (deviceObject && typeof deviceObject === 'object') {
574
- deviceName = deviceObject.common.name;
575
- }
576
- }
577
- break;
578
-
782
+ switch (this.selAdapter[i].adapterID) {
579
783
  case 'fullybrowser':
580
- deviceName = (await this.getInitValue(currDeviceString + this.arrDev[i].id)) + ' ' + (await this.getInitValue(currDeviceString + this.arrDev[i].id2));
784
+ deviceName = (await this.getInitValue(currDeviceString + this.selAdapter[i].id)) + ' ' + (await this.getInitValue(currDeviceString + this.selAdapter[i].id2));
581
785
  break;
582
786
 
583
787
  // Get ID with short currDeviceString from objectjson
@@ -585,6 +789,7 @@ class DeviceWatcher extends utils.Adapter {
585
789
  case 'hmrpc':
586
790
  case 'nukiExt':
587
791
  case 'wled':
792
+ case 'mqttNuki':
588
793
  if (shortDeviceObject && typeof shortDeviceObject === 'object') {
589
794
  deviceName = shortDeviceObject.common.name;
590
795
  }
@@ -601,7 +806,7 @@ class DeviceWatcher extends utils.Adapter {
601
806
  case 'mihomeVacuum':
602
807
  case 'roomba':
603
808
  folderName = shortCurrDeviceString.slice(shortCurrDeviceString.lastIndexOf('.') + 1);
604
- deviceID = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].id);
809
+ deviceID = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].id);
605
810
  deviceName = `I${folderName} ${deviceID}`;
606
811
  break;
607
812
 
@@ -630,8 +835,11 @@ class DeviceWatcher extends utils.Adapter {
630
835
 
631
836
  // Get ID with main selektor from objectjson
632
837
  default:
633
- if (deviceObject && typeof deviceObject === 'object') {
634
- deviceName = deviceObject.common.name;
838
+ if (this.selAdapter[i].id !== 'none' || this.selAdapter[i].id !== undefined) deviceName = await this.getInitValue(currDeviceString + this.selAdapter[i].id);
839
+ if (deviceName === null || deviceName === undefined) {
840
+ if (deviceObject && typeof deviceObject === 'object') {
841
+ deviceName = deviceObject.common.name;
842
+ }
635
843
  }
636
844
  break;
637
845
  }
@@ -659,6 +867,7 @@ class DeviceWatcher extends utils.Adapter {
659
867
  switch (adapterID) {
660
868
  case 'roomba':
661
869
  case 'sonoff':
870
+ case 'smartgarden':
662
871
  linkQuality = deviceQualityState.val + '%'; // If quality state is already an percent value
663
872
  break;
664
873
  case 'lupusec':
@@ -775,8 +984,8 @@ class DeviceWatcher extends utils.Adapter {
775
984
  async setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportState, adapterID) {
776
985
  let lowBatIndicator = false;
777
986
  /*=============================================
778
- = Set Lowbat indicator =
779
- =============================================*/
987
+ = Set Lowbat indicator =
988
+ =============================================*/
780
989
  if (deviceLowBatState !== undefined || faultReportState !== undefined) {
781
990
  switch (adapterID) {
782
991
  case 'hmrpc':
@@ -890,29 +1099,29 @@ class DeviceWatcher extends utils.Adapter {
890
1099
  }
891
1100
 
892
1101
  /*=============================================
893
- = Set Online Status =
894
- =============================================*/
895
- if (this.maxMinutes !== undefined) {
1102
+ = Set Online Status =
1103
+ =============================================*/
1104
+ if (this.configMaxMinutes !== undefined) {
896
1105
  switch (adapterID) {
897
1106
  case 'hmrpc':
898
- if (this.maxMinutes[adapterID] <= 0) {
1107
+ if (this.configMaxMinutes[adapterID] <= 0) {
899
1108
  if (deviceUnreachState === 1) {
900
1109
  deviceState = 'Offline'; //set online state to offline
901
1110
  linkQuality = '0%'; // set linkQuality to nothing
902
1111
  }
903
- } else if (lastDeviceUnreachStateChange > this.maxMinutes[adapterID] && deviceUnreachState === 1) {
1112
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState === 1) {
904
1113
  deviceState = 'Offline'; //set online state to offline
905
1114
  linkQuality = '0%'; // set linkQuality to nothing
906
1115
  }
907
1116
  break;
908
1117
  case 'hmiP':
909
1118
  case 'maxcube':
910
- if (this.maxMinutes[adapterID] <= 0) {
1119
+ if (this.configMaxMinutes[adapterID] <= 0) {
911
1120
  if (deviceUnreachState) {
912
1121
  deviceState = 'Offline'; //set online state to offline
913
1122
  linkQuality = '0%'; // set linkQuality to nothing
914
1123
  }
915
- } else if (lastDeviceUnreachStateChange > this.maxMinutes[adapterID] && deviceUnreachState) {
1124
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState) {
916
1125
  deviceState = 'Offline'; //set online state to offline
917
1126
  linkQuality = '0%'; // set linkQuality to nothing
918
1127
  }
@@ -927,57 +1136,68 @@ class DeviceWatcher extends utils.Adapter {
927
1136
  case 'unifi':
928
1137
  case 'zigbee':
929
1138
  case 'zigbee2MQTT':
930
- if (this.maxMinutes[adapterID] <= 0) {
1139
+ if (this.configMaxMinutes[adapterID] <= 0) {
931
1140
  if (!deviceUnreachState) {
932
1141
  deviceState = 'Offline'; //set online state to offline
933
1142
  linkQuality = '0%'; // set linkQuality to nothing
934
1143
  }
935
- } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.maxMinutes[adapterID]) {
1144
+ } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
936
1145
  deviceState = 'Offline'; //set online state to offline
937
1146
  linkQuality = '0%'; // set linkQuality to nothing
938
1147
  }
939
1148
  break;
940
1149
  case 'mqttClientZigbee2Mqtt':
941
- if (this.maxMinutes[adapterID] <= 0) {
1150
+ if (this.configMaxMinutes[adapterID] <= 0) {
942
1151
  if (deviceUnreachState !== 'online') {
943
1152
  deviceState = 'Offline'; //set online state to offline
944
1153
  linkQuality = '0%'; // set linkQuality to nothing
945
1154
  }
946
- } else if (deviceUnreachState !== 'online' && lastDeviceUnreachStateChange > this.maxMinutes[adapterID]) {
1155
+ } else if (deviceUnreachState !== 'online' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
947
1156
  deviceState = 'Offline'; //set online state to offline
948
1157
  linkQuality = '0%'; // set linkQuality to nothing
949
1158
  }
950
1159
  break;
951
1160
  case 'mihome':
952
1161
  if (deviceUnreachState !== undefined) {
953
- if (this.maxMinutes[adapterID] <= 0) {
1162
+ if (this.configMaxMinutes[adapterID] <= 0) {
954
1163
  if (!deviceUnreachState) {
955
1164
  deviceState = 'Offline'; //set online state to offline
956
1165
  linkQuality = '0%'; // set linkQuality to nothing
957
1166
  }
958
- } else if (lastContact > this.maxMinutes[adapterID]) {
1167
+ } else if (lastContact > this.configMaxMinutes[adapterID]) {
959
1168
  deviceState = 'Offline'; //set online state to offline
960
1169
  linkQuality = '0%'; // set linkQuality to nothing
961
1170
  }
962
1171
  } else {
963
1172
  if (this.config.mihomeMaxMinutes <= 0) {
964
- if (this.maxMinutes[adapterID] <= 0) {
1173
+ if (this.configMaxMinutes[adapterID] <= 0) {
965
1174
  deviceState = 'Offline'; //set online state to offline
966
1175
  linkQuality = '0%'; // set linkQuality to nothing
967
1176
  }
968
- } else if (lastContact > this.maxMinutes[adapterID]) {
1177
+ } else if (lastContact > this.configMaxMinutes[adapterID]) {
1178
+ deviceState = 'Offline'; //set online state to offline
1179
+ linkQuality = '0%'; // set linkQuality to nothing
1180
+ }
1181
+ }
1182
+ break;
1183
+ case 'smartgarden':
1184
+ if (this.configMaxMinutes[adapterID] <= 0) {
1185
+ if (deviceUnreachState === 'OFFLINE') {
969
1186
  deviceState = 'Offline'; //set online state to offline
970
1187
  linkQuality = '0%'; // set linkQuality to nothing
971
1188
  }
1189
+ } else if (deviceUnreachState === 'OFFLINE' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1190
+ deviceState = 'Offline'; //set online state to offline
1191
+ linkQuality = '0%'; // set linkQuality to nothing
972
1192
  }
973
1193
  break;
974
1194
  default:
975
- if (this.maxMinutes[adapterID] <= 0) {
1195
+ if (this.configMaxMinutes[adapterID] <= 0) {
976
1196
  if (!deviceUnreachState) {
977
1197
  deviceState = 'Offline'; //set online state to offline
978
1198
  linkQuality = '0%'; // set linkQuality to nothing
979
1199
  }
980
- } else if (lastContact > this.maxMinutes[adapterID]) {
1200
+ } else if (lastContact > this.configMaxMinutes[adapterID]) {
981
1201
  deviceState = 'Offline'; //set online state to offline
982
1202
  linkQuality = '0%'; // set linkQuality to nothing
983
1203
  }
@@ -996,262 +1216,29 @@ class DeviceWatcher extends utils.Adapter {
996
1216
  */
997
1217
  async checkLastContact() {
998
1218
  for (const device of this.listAllDevicesRaw) {
999
- const oldContactState = device.Status;
1000
- device.UnreachState = await this.getInitValue(device.UnreachDP);
1001
- const contactData = await this.getOnlineState(
1002
- device.timeSelector,
1003
- device.adapterID,
1004
- device.UnreachDP,
1005
- device.SignalStrength,
1006
- device.UnreachState,
1007
- device.DeviceStateSelectorDP,
1008
- device.rssiPeerSelectorDP,
1009
- );
1010
- if (contactData !== undefined) {
1011
- device.LastContact = contactData[0];
1012
- device.Status = contactData[1];
1013
- device.linkQuality = contactData[2];
1014
- }
1015
- if (this.config.checkSendOfflineMsg && oldContactState !== device.Status && !this.blacklistNotify.includes(device.Path)) {
1016
- await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
1017
- }
1018
- }
1019
- }
1020
-
1021
- /**
1022
- * @param {object} i - Device Object
1023
- */
1024
- async createData(i) {
1025
- const devices = await this.getForeignStatesAsync(this.arrDev[i].Selektor);
1026
- const adapterID = this.arrDev[i].adapterID;
1027
-
1028
- /*---------- Start of loop ----------*/
1029
- for (const [id] of Object.entries(devices)) {
1030
- if (!isUnloaded) {
1031
- /*=============================================
1032
- = Get device name =
1033
- =============================================*/
1034
- const deviceName = await this.getDeviceName(id, i);
1035
-
1036
- /*=============================================
1037
- = Get adapter name =
1038
- =============================================*/
1039
- const adapter = this.arrDev[i].adapter;
1040
-
1041
- /*=============================================
1042
- = Get path to datapoints =
1043
- =============================================*/
1044
- const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
1045
- const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
1046
-
1047
- /*=============================================
1048
- = Get signal strength =
1049
- =============================================*/
1050
- let deviceQualityDP = currDeviceString + this.arrDev[i].rssiState;
1051
- let deviceQualityState;
1052
-
1053
- switch (adapterID) {
1054
- case 'mihomeVacuum':
1055
- deviceQualityDP = shortCurrDeviceString + this.arrDev[i].rssiState;
1056
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
1057
- break;
1058
-
1059
- case 'netatmo':
1060
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
1061
- if (!deviceQualityState) {
1062
- deviceQualityDP = currDeviceString + this.arrDev[i].rfState;
1063
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
1064
- }
1065
- break;
1066
-
1067
- default:
1068
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
1069
- break;
1070
- }
1071
- //subscribe to states
1072
- this.subscribeForeignStatesAsync(deviceQualityDP);
1073
-
1074
- let linkQuality = await this.calculateSignalStrength(deviceQualityState, adapterID);
1075
-
1076
- /*=============================================
1077
- = Get battery data =
1078
- =============================================*/
1079
- let deviceBatteryStateDP;
1080
- let deviceBatteryState;
1081
- let batteryHealth;
1082
- let batteryHealthRaw;
1083
- let lowBatIndicator;
1084
- let isBatteryDevice;
1085
- let isLowBatDP;
1086
- let faultReportingDP;
1087
- let faultReportingState;
1088
-
1089
- const deviceChargerStateDP = currDeviceString + this.arrDev[i].charger;
1090
- const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
1091
-
1092
- if (deviceChargerState === undefined || deviceChargerState === false) {
1093
- // Get battery states
1094
- switch (adapterID) {
1095
- case 'hueExt':
1096
- case 'mihomeVacuum':
1097
- case 'mqttNuki':
1098
- deviceBatteryStateDP = shortCurrDeviceString + this.arrDev[i].battery;
1099
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
1100
- if (deviceBatteryState === undefined) {
1101
- deviceBatteryStateDP = shortCurrDeviceString + this.arrDev[i].battery2;
1102
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
1103
- }
1104
- break;
1105
- default:
1106
- deviceBatteryStateDP = currDeviceString + this.arrDev[i].battery;
1107
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
1108
- if (deviceBatteryState === undefined) {
1109
- deviceBatteryStateDP = currDeviceString + this.arrDev[i].battery2;
1110
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
1111
- }
1112
- break;
1113
- }
1114
-
1115
- // Get low bat states
1116
- isLowBatDP = currDeviceString + this.arrDev[i].isLowBat;
1117
- let deviceLowBatState = await this.getInitValue(isLowBatDP);
1118
- if (deviceLowBatState === undefined) {
1119
- isLowBatDP = currDeviceString + this.arrDev[i].isLowBat2;
1120
- deviceLowBatState = await this.getInitValue(isLowBatDP);
1121
- }
1122
- if (deviceLowBatState === undefined) isLowBatDP = 'none';
1123
-
1124
- faultReportingDP = shortCurrDeviceString + this.arrDev[i].faultReporting;
1125
- faultReportingState = await this.getInitValue(faultReportingDP);
1126
-
1127
- //subscribe to states
1128
- this.subscribeForeignStatesAsync(deviceBatteryStateDP);
1129
- this.subscribeForeignStatesAsync(isLowBatDP);
1130
- this.subscribeForeignStatesAsync(faultReportingDP);
1131
-
1132
- const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, adapterID);
1133
- batteryHealth = batteryData[0];
1134
- batteryHealthRaw = batteryData[2];
1135
- isBatteryDevice = batteryData[1];
1136
-
1137
- if (isBatteryDevice) {
1138
- lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
1139
- }
1140
- }
1141
-
1142
- /*=============================================
1143
- = Get last contact of device =
1144
- =============================================*/
1145
- let unreachDP = currDeviceString + this.arrDev[i].reach;
1146
- const deviceStateSelectorDP = shortCurrDeviceString + this.arrDev[i].stateValue;
1147
- const rssiPeerSelectorDP = currDeviceString + this.arrDev[i].rssiPeerState;
1148
- const timeSelector = currDeviceString + this.arrDev[i].timeSelector;
1149
-
1150
- let deviceUnreachState = await this.getInitValue(unreachDP);
1151
- if (deviceUnreachState === undefined) {
1152
- unreachDP = shortCurrDeviceString + this.arrDev[i].reach;
1153
- deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].reach);
1154
- }
1155
-
1156
- // subscribe to states
1157
- this.subscribeForeignStatesAsync(timeSelector);
1158
- this.subscribeForeignStatesAsync(unreachDP);
1159
- this.subscribeForeignStatesAsync(deviceStateSelectorDP);
1160
- this.subscribeForeignStatesAsync(rssiPeerSelectorDP);
1161
-
1162
- const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
1163
- let deviceState;
1164
- let lastContactString;
1165
-
1166
- if (onlineState) {
1167
- lastContactString = onlineState[0];
1168
- deviceState = onlineState[1];
1169
- linkQuality = onlineState[2];
1170
- }
1171
-
1172
- /*=============================================
1173
- = Get update data =
1174
- =============================================*/
1175
- const deviceUpdateDP = currDeviceString + this.arrDev[i].upgrade;
1176
- let isUpgradable;
1177
-
1178
- if (this.config.checkSendDeviceUpgrade) {
1179
- const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
1180
-
1181
- if (deviceUpdateSelector) {
1182
- isUpgradable = true;
1183
- } else if (!deviceUpdateSelector) {
1184
- isUpgradable = false;
1185
- }
1186
- // subscribe to states
1187
- this.subscribeForeignStatesAsync(deviceUpdateDP);
1219
+ if (device.instancedeviceConnected !== false) {
1220
+ const oldContactState = device.Status;
1221
+ device.UnreachState = await this.getInitValue(device.UnreachDP);
1222
+ const contactData = await this.getOnlineState(
1223
+ device.timeSelector,
1224
+ device.adapterID,
1225
+ device.UnreachDP,
1226
+ device.SignalStrength,
1227
+ device.UnreachState,
1228
+ device.DeviceStateSelectorDP,
1229
+ device.rssiPeerSelectorDP,
1230
+ );
1231
+ if (contactData !== undefined) {
1232
+ device.LastContact = contactData[0];
1233
+ device.Status = contactData[1];
1234
+ device.linkQuality = contactData[2];
1188
1235
  }
1189
-
1190
- /*=============================================
1191
- = Fill Raw Lists =
1192
- =============================================*/
1193
-
1194
- /* Add only devices with battery in the rawlist */
1195
- if (this.listOnlyBattery && isBatteryDevice) {
1196
- this.listAllDevicesRaw.push({
1197
- Path: id,
1198
- Device: deviceName,
1199
- adapterID: adapterID,
1200
- Adapter: adapter,
1201
- timeSelector: timeSelector,
1202
- isBatteryDevice: isBatteryDevice,
1203
- Battery: batteryHealth,
1204
- BatteryRaw: batteryHealthRaw,
1205
- batteryDP: deviceBatteryStateDP,
1206
- LowBat: lowBatIndicator,
1207
- LowBatDP: isLowBatDP,
1208
- faultReport: faultReportingState,
1209
- faultReportDP: faultReportingDP,
1210
- SignalStrengthDP: deviceQualityDP,
1211
- SignalStrength: linkQuality,
1212
- UnreachState: deviceUnreachState,
1213
- UnreachDP: unreachDP,
1214
- DeviceStateSelectorDP: deviceStateSelectorDP,
1215
- rssiPeerSelectorDP: rssiPeerSelectorDP,
1216
- LastContact: lastContactString,
1217
- Status: deviceState,
1218
- UpdateDP: deviceUpdateDP,
1219
- Upgradable: isUpgradable,
1220
- });
1221
- } else {
1222
- /* Add all devices */
1223
- this.listAllDevicesRaw.push({
1224
- Path: id,
1225
- Device: deviceName,
1226
- adapterID: adapterID,
1227
- Adapter: adapter,
1228
- timeSelector: timeSelector,
1229
- isBatteryDevice: isBatteryDevice,
1230
- Battery: batteryHealth,
1231
- BatteryRaw: batteryHealthRaw,
1232
- batteryDP: deviceBatteryStateDP,
1233
- LowBat: lowBatIndicator,
1234
- LowBatDP: isLowBatDP,
1235
- faultReport: faultReportingState,
1236
- faultReportDP: faultReportingDP,
1237
- SignalStrengthDP: deviceQualityDP,
1238
- SignalStrength: linkQuality,
1239
- UnreachState: deviceUnreachState,
1240
- UnreachDP: unreachDP,
1241
- DeviceStateSelectorDP: deviceStateSelectorDP,
1242
- rssiPeerSelectorDP: rssiPeerSelectorDP,
1243
- LastContact: lastContactString,
1244
- Status: deviceState,
1245
- UpdateDP: deviceUpdateDP,
1246
- Upgradable: isUpgradable,
1247
- });
1236
+ if (this.config.checkSendOfflineMsg && oldContactState !== device.Status && !this.blacklistNotify.includes(device.Path)) {
1237
+ await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
1248
1238
  }
1249
- } else {
1250
- /* cancel run if unloaded was called. */
1251
- return;
1252
1239
  }
1253
- } // <-- end of loop
1254
- } // <-- end of createData
1240
+ }
1241
+ }
1255
1242
 
1256
1243
  /**
1257
1244
  * Create Lists
@@ -1264,6 +1251,7 @@ class DeviceWatcher extends utils.Adapter {
1264
1251
  this.offlineDevices = [];
1265
1252
  this.batteryLowPoweredRaw = [];
1266
1253
  this.offlineDevicesRaw = [];
1254
+ this.upgradableDevicesRaw = [];
1267
1255
  this.upgradableList = [];
1268
1256
 
1269
1257
  if (adptName === undefined) {
@@ -1291,6 +1279,15 @@ class DeviceWatcher extends utils.Adapter {
1291
1279
  });
1292
1280
  }
1293
1281
 
1282
+ // upgradable raw list
1283
+ if (device.Upgradable) {
1284
+ this.upgradableDevicesRaw.push({
1285
+ Path: device.Path,
1286
+ Device: device.Device,
1287
+ Adapter: device.Adapter,
1288
+ });
1289
+ }
1290
+
1294
1291
  if (adptName === '' && !this.blacklistLists.includes(device.Path)) {
1295
1292
  await this.theLists(device);
1296
1293
  }
@@ -1413,24 +1410,180 @@ class DeviceWatcher extends utils.Adapter {
1413
1410
  this.log.debug(`Function finished: ${this.createDataForEachAdapter.name}`);
1414
1411
  } // <-- end of createDataForEachAdapter
1415
1412
 
1416
- /**
1417
- * create Data of all selected adapter in one list
1418
- */
1419
- async createDataOfAllAdapter() {
1420
- this.log.debug(`Function started: ${this.createDataOfAllAdapter.name}`);
1413
+ /**
1414
+ * create Data of all selected adapter in one list
1415
+ */
1416
+ async createDataOfAllAdapter() {
1417
+ this.log.debug(`Function started: ${this.createDataOfAllAdapter.name}`);
1418
+
1419
+ try {
1420
+ for (let i = 0; i < this.selAdapter.length; i++) {
1421
+ await this.createData(i);
1422
+ await this.createLists();
1423
+ }
1424
+ await this.writeDatapoints(); // fill the datapoints
1425
+ } catch (error) {
1426
+ this.errorReporting('[createDataOfAllAdapter]', error);
1427
+ }
1428
+
1429
+ this.log.debug(`Function finished: ${this.createDataOfAllAdapter.name}`);
1430
+ } // <-- end of createDataOfAllAdapter
1431
+
1432
+ /**
1433
+ * @param {string} [adptName] - Adaptername
1434
+ */
1435
+ async writeDatapoints(adptName) {
1436
+ // fill the datapoints
1437
+
1438
+ this.log.debug(`Start the function: ${this.writeDatapoints.name}`);
1439
+
1440
+ try {
1441
+ let dpSubFolder;
1442
+ //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
1443
+ if (adptName) {
1444
+ dpSubFolder = adptName + '.';
1445
+ } else {
1446
+ dpSubFolder = '';
1447
+ }
1448
+
1449
+ // Write Datapoints for counts
1450
+ await this.setStateAsync(`${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1451
+ await this.setStateAsync(`${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1452
+ await this.setStateAsync(`${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1453
+ await this.setStateAsync(`${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1454
+ await this.setStateAsync(`${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1455
+
1456
+ // List all devices
1457
+ if (this.deviceCounter === 0) {
1458
+ // if no device is count, write the JSON List with default value
1459
+ this.listAllDevices = [{ Device: '--none--', Adapter: '', Battery: '', 'Last contact': '', 'Signal strength': '' }];
1460
+ }
1461
+ await this.setStateAsync(`${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1462
+
1463
+ // List link quality
1464
+ if (this.linkQualityCount === 0) {
1465
+ // if no device is count, write the JSON List with default value
1466
+ this.linkQualityDevices = [{ Device: '--none--', Adapter: '', 'Signal strength': '' }];
1467
+ }
1468
+ //write JSON list
1469
+ await this.setStateAsync(`${dpSubFolder}linkQualityList`, {
1470
+ val: JSON.stringify(this.linkQualityDevices),
1471
+ ack: true,
1472
+ });
1473
+
1474
+ // List offline devices
1475
+ if (this.offlineDevicesCount === 0) {
1476
+ // if no device is count, write the JSON List with default value
1477
+ this.offlineDevices = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1478
+ }
1479
+ //write JSON list
1480
+ await this.setStateAsync(`${dpSubFolder}offlineList`, {
1481
+ val: JSON.stringify(this.offlineDevices),
1482
+ ack: true,
1483
+ });
1484
+
1485
+ // List updatable
1486
+ if (this.upgradableDevicesCount === 0) {
1487
+ // if no device is count, write the JSON List with default value
1488
+ this.upgradableList = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1489
+ }
1490
+ //write JSON list
1491
+ await this.setStateAsync(`${dpSubFolder}upgradableList`, {
1492
+ val: JSON.stringify(this.upgradableList),
1493
+ ack: true,
1494
+ });
1495
+
1496
+ // List battery powered
1497
+ if (this.batteryPoweredCount === 0) {
1498
+ // if no device is count, write the JSON List with default value
1499
+ this.batteryPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1500
+ }
1501
+ //write JSON list
1502
+ await this.setStateAsync(`${dpSubFolder}batteryList`, {
1503
+ val: JSON.stringify(this.batteryPowered),
1504
+ ack: true,
1505
+ });
1506
+
1507
+ // list battery low powered
1508
+ if (this.lowBatteryPoweredCount === 0) {
1509
+ // if no device is count, write the JSON List with default value
1510
+ this.batteryLowPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1511
+ }
1512
+ //write JSON list
1513
+ await this.setStateAsync(`${dpSubFolder}lowBatteryList`, {
1514
+ val: JSON.stringify(this.batteryLowPowered),
1515
+ ack: true,
1516
+ });
1517
+
1518
+ // set booleans datapoints
1519
+ if (this.offlineDevicesCount === 0) {
1520
+ await this.setStateAsync(`${dpSubFolder}oneDeviceOffline`, {
1521
+ val: false,
1522
+ ack: true,
1523
+ });
1524
+ } else {
1525
+ await this.setStateAsync(`${dpSubFolder}oneDeviceOffline`, {
1526
+ val: true,
1527
+ ack: true,
1528
+ });
1529
+ }
1530
+
1531
+ if (this.lowBatteryPoweredCount === 0) {
1532
+ await this.setStateAsync(`${dpSubFolder}oneDeviceLowBat`, {
1533
+ val: false,
1534
+ ack: true,
1535
+ });
1536
+ } else {
1537
+ await this.setStateAsync(`${dpSubFolder}oneDeviceLowBat`, {
1538
+ val: true,
1539
+ ack: true,
1540
+ });
1541
+ }
1542
+
1543
+ if (this.upgradableDevicesCount === 0) {
1544
+ await this.setStateAsync(`${dpSubFolder}oneDeviceUpdatable`, {
1545
+ val: false,
1546
+ ack: true,
1547
+ });
1548
+ } else {
1549
+ await this.setStateAsync(`${dpSubFolder}oneDeviceUpdatable`, {
1550
+ val: true,
1551
+ ack: true,
1552
+ });
1553
+ }
1421
1554
 
1422
- try {
1423
- for (let i = 0; i < this.arrDev.length; i++) {
1424
- await this.createData(i);
1425
- await this.createLists();
1555
+ //write HTML list
1556
+ if (this.createHtmlList) {
1557
+ await this.setStateAsync(`${dpSubFolder}linkQualityListHTML`, {
1558
+ val: await this.creatLinkQualityListHTML(this.linkQualityDevices, this.linkQualityCount),
1559
+ ack: true,
1560
+ });
1561
+ await this.setStateAsync(`${dpSubFolder}offlineListHTML`, {
1562
+ val: await this.createOfflineListHTML(this.offlineDevices, this.offlineDevicesCount),
1563
+ ack: true,
1564
+ });
1565
+ await this.setStateAsync(`${dpSubFolder}batteryListHTML`, {
1566
+ val: await this.createBatteryListHTML(this.batteryPowered, this.batteryPoweredCount, false),
1567
+ ack: true,
1568
+ });
1569
+ await this.setStateAsync(`${dpSubFolder}lowBatteryListHTML`, {
1570
+ val: await this.createBatteryListHTML(this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1571
+ ack: true,
1572
+ });
1426
1573
  }
1427
- await this.writeDatapoints(); // fill the datapoints
1574
+
1575
+ // create timestamp of last run
1576
+ const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
1577
+ await this.setStateAsync('lastCheck', lastCheck, true);
1428
1578
  } catch (error) {
1429
- this.errorReporting('[createDataOfAllAdapter]', error);
1579
+ this.errorReporting('[writeDatapoints]', error);
1430
1580
  }
1581
+ this.log.debug(`Function finished: ${this.writeDatapoints.name}`);
1582
+ } //<--End of writing Datapoints
1431
1583
 
1432
- this.log.debug(`Function finished: ${this.createDataOfAllAdapter.name}`);
1433
- } // <-- end of createDataOfAllAdapter
1584
+ /*=============================================
1585
+ = functions to send notifications =
1586
+ =============================================*/
1434
1587
 
1435
1588
  /**
1436
1589
  * Notification service
@@ -1812,7 +1965,7 @@ class DeviceWatcher extends utils.Adapter {
1812
1965
  try {
1813
1966
  let deviceList = '';
1814
1967
 
1815
- for (const id of this.upgradableList) {
1968
+ for (const id of this.upgradableDevicesRaw) {
1816
1969
  if (!this.blacklistNotify.includes(id.Path)) {
1817
1970
  if (!this.config.showAdapterNameinMsg) {
1818
1971
  deviceList = `${deviceList}\n${id.Device}`;
@@ -1821,7 +1974,6 @@ class DeviceWatcher extends utils.Adapter {
1821
1974
  }
1822
1975
  }
1823
1976
  }
1824
-
1825
1977
  if (deviceList.length > 0) {
1826
1978
  this.log.info(`Geräte Upgrade: ${deviceList}`);
1827
1979
  this.setStateAsync('lastNotification', `Geräte Upgrade: ${deviceList}`, true);
@@ -1835,157 +1987,9 @@ class DeviceWatcher extends utils.Adapter {
1835
1987
  }
1836
1988
  } //<--End of daily offline notification
1837
1989
 
1838
- /**
1839
- * @param {string} [adptName] - Adaptername
1840
- */
1841
- async writeDatapoints(adptName) {
1842
- // fill the datapoints
1843
-
1844
- this.log.debug(`Start the function: ${this.writeDatapoints.name}`);
1845
-
1846
- try {
1847
- let dpSubFolder;
1848
- //write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
1849
- if (adptName) {
1850
- dpSubFolder = adptName + '.';
1851
- } else {
1852
- dpSubFolder = '';
1853
- }
1854
-
1855
- // Write Datapoints for counts
1856
- await this.setStateAsync(`${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1857
- await this.setStateAsync(`${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1858
- await this.setStateAsync(`${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1859
- await this.setStateAsync(`${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1860
- await this.setStateAsync(`${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1861
-
1862
- // List all devices
1863
- if (this.deviceCounter === 0) {
1864
- // if no device is count, write the JSON List with default value
1865
- this.listAllDevices = [{ Device: '--none--', Adapter: '', Battery: '', 'Last contact': '', 'Signal strength': '' }];
1866
- }
1867
- await this.setStateAsync(`${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1868
-
1869
- // List link quality
1870
- if (this.linkQualityCount === 0) {
1871
- // if no device is count, write the JSON List with default value
1872
- this.linkQualityDevices = [{ Device: '--none--', Adapter: '', 'Signal strength': '' }];
1873
- }
1874
- //write JSON list
1875
- await this.setStateAsync(`${dpSubFolder}linkQualityList`, {
1876
- val: JSON.stringify(this.linkQualityDevices),
1877
- ack: true,
1878
- });
1879
-
1880
- // List offline devices
1881
- if (this.offlineDevicesCount === 0) {
1882
- // if no device is count, write the JSON List with default value
1883
- this.offlineDevices = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1884
- }
1885
- //write JSON list
1886
- await this.setStateAsync(`${dpSubFolder}offlineList`, {
1887
- val: JSON.stringify(this.offlineDevices),
1888
- ack: true,
1889
- });
1890
-
1891
- // List updatable
1892
- if (this.upgradableDevicesCount === 0) {
1893
- // if no device is count, write the JSON List with default value
1894
- this.upgradableList = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1895
- }
1896
- //write JSON list
1897
- await this.setStateAsync(`${dpSubFolder}upgradableList`, {
1898
- val: JSON.stringify(this.upgradableList),
1899
- ack: true,
1900
- });
1901
-
1902
- // List battery powered
1903
- if (this.batteryPoweredCount === 0) {
1904
- // if no device is count, write the JSON List with default value
1905
- this.batteryPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1906
- }
1907
- //write JSON list
1908
- await this.setStateAsync(`${dpSubFolder}batteryList`, {
1909
- val: JSON.stringify(this.batteryPowered),
1910
- ack: true,
1911
- });
1912
-
1913
- // list battery low powered
1914
- if (this.lowBatteryPoweredCount === 0) {
1915
- // if no device is count, write the JSON List with default value
1916
- this.batteryLowPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1917
- }
1918
- //write JSON list
1919
- await this.setStateAsync(`${dpSubFolder}lowBatteryList`, {
1920
- val: JSON.stringify(this.batteryLowPowered),
1921
- ack: true,
1922
- });
1923
-
1924
- // set booleans datapoints
1925
- if (this.offlineDevicesCount === 0) {
1926
- await this.setStateAsync(`${dpSubFolder}oneDeviceOffline`, {
1927
- val: false,
1928
- ack: true,
1929
- });
1930
- } else {
1931
- await this.setStateAsync(`${dpSubFolder}oneDeviceOffline`, {
1932
- val: true,
1933
- ack: true,
1934
- });
1935
- }
1936
-
1937
- if (this.lowBatteryPoweredCount === 0) {
1938
- await this.setStateAsync(`${dpSubFolder}oneDeviceLowBat`, {
1939
- val: false,
1940
- ack: true,
1941
- });
1942
- } else {
1943
- await this.setStateAsync(`${dpSubFolder}oneDeviceLowBat`, {
1944
- val: true,
1945
- ack: true,
1946
- });
1947
- }
1948
-
1949
- if (this.upgradableDevicesCount === 0) {
1950
- await this.setStateAsync(`${dpSubFolder}oneDeviceUpdatable`, {
1951
- val: false,
1952
- ack: true,
1953
- });
1954
- } else {
1955
- await this.setStateAsync(`${dpSubFolder}oneDeviceUpdatable`, {
1956
- val: true,
1957
- ack: true,
1958
- });
1959
- }
1960
-
1961
- //write HTML list
1962
- if (this.createHtmlList) {
1963
- await this.setStateAsync(`${dpSubFolder}linkQualityListHTML`, {
1964
- val: await this.creatLinkQualityListHTML(this.linkQualityDevices, this.linkQualityCount),
1965
- ack: true,
1966
- });
1967
- await this.setStateAsync(`${dpSubFolder}offlineListHTML`, {
1968
- val: await this.createOfflineListHTML(this.offlineDevices, this.offlineDevicesCount),
1969
- ack: true,
1970
- });
1971
- await this.setStateAsync(`${dpSubFolder}batteryListHTML`, {
1972
- val: await this.createBatteryListHTML(this.batteryPowered, this.batteryPoweredCount, false),
1973
- ack: true,
1974
- });
1975
- await this.setStateAsync(`${dpSubFolder}lowBatteryListHTML`, {
1976
- val: await this.createBatteryListHTML(this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1977
- ack: true,
1978
- });
1979
- }
1980
-
1981
- // create timestamp of last run
1982
- const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
1983
- await this.setStateAsync('lastCheck', lastCheck, true);
1984
- } catch (error) {
1985
- this.errorReporting('[writeDatapoints]', error);
1986
- }
1987
- this.log.debug(`Function finished: ${this.writeDatapoints.name}`);
1988
- } //<--End of writing Datapoints
1990
+ /*=============================================
1991
+ = functions to create html lists =
1992
+ =============================================*/
1989
1993
 
1990
1994
  /**
1991
1995
  * @param {object} devices - Device
@@ -2100,7 +2104,10 @@ class DeviceWatcher extends utils.Adapter {
2100
2104
  return html;
2101
2105
  }
2102
2106
 
2103
- // create datapoints for each adapter
2107
+ /*=============================================
2108
+ = create datapoints for each adapter =
2109
+ =============================================*/
2110
+
2104
2111
  /**
2105
2112
  * @param {object} adptName - Adaptername of devices
2106
2113
  */
@@ -2549,6 +2556,66 @@ class DeviceWatcher extends utils.Adapter {
2549
2556
  });
2550
2557
  }
2551
2558
 
2559
+ /*=============================================
2560
+ = help functions =
2561
+ =============================================*/
2562
+
2563
+ /**
2564
+ * @param {string} id - id which should be capitalize
2565
+ */
2566
+ capitalize(id) {
2567
+ //make the first letter uppercase
2568
+ return id && id[0].toUpperCase() + id.slice(1);
2569
+ }
2570
+
2571
+ /**
2572
+ * @param {number} dpValue - get Time of this datapoint
2573
+ */
2574
+ async getTimestamp(dpValue) {
2575
+ const time = new Date();
2576
+ return (dpValue = Math.round((time.getTime() - dpValue) / 1000 / 60));
2577
+ }
2578
+
2579
+ /**
2580
+ * @param {string} dp - get Time of this datapoint
2581
+ */
2582
+ async getTimestampConnectionDP(dp) {
2583
+ const time = new Date();
2584
+ const dpValue = await this.getForeignStateAsync(dp);
2585
+ if (dpValue !== null && dpValue !== undefined) {
2586
+ const dpLastStateChange = Math.round((time.getTime() - dpValue.lc) / 1000);
2587
+ return dpLastStateChange;
2588
+ }
2589
+ }
2590
+
2591
+ /**
2592
+ * @param {object} obj - State of datapoint
2593
+ */
2594
+ async getInitValue(obj) {
2595
+ //state can be null or undefinded
2596
+ const foreignState = await this.getForeignStateAsync(obj);
2597
+ if (foreignState) return foreignState.val;
2598
+ }
2599
+
2600
+ /**
2601
+ * @param {object} obj - State of own datapoint
2602
+ */
2603
+ async getOwnInitValue(obj) {
2604
+ //state can be null or undefinded for own states
2605
+ const stateVal = await this.getStateAsync(obj);
2606
+ if (stateVal) return stateVal.val;
2607
+ }
2608
+
2609
+ /**
2610
+ * @param {object} data - object
2611
+ */
2612
+ async parseData(data) {
2613
+ if (!data) return {};
2614
+ if (typeof data === 'object') return data;
2615
+ if (typeof data === 'string') return JSON.parse(data);
2616
+ return {};
2617
+ }
2618
+
2552
2619
  /**
2553
2620
  * @param {string} codePart - Message Prefix
2554
2621
  * @param {object} error - Sentry message