iobroker.device-watcher 2.0.2 → 2.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
@@ -33,6 +33,7 @@ class DeviceWatcher extends utils.Adapter {
33
33
  this.blacklistNotify = [];
34
34
  this.arrDev = [];
35
35
  this.adapterSelected = [];
36
+ this.upgradableList = [];
36
37
 
37
38
  // raw arrays
38
39
  this.listAllDevicesRaw = [];
@@ -43,6 +44,7 @@ class DeviceWatcher extends utils.Adapter {
43
44
  this.offlineDevicesCountRaw = 0;
44
45
  this.offlineDevicesCountRawOld = 0;
45
46
  this.lowBatteryPoweredCountRaw = 0;
47
+ this.upgradableDevicesCountRawOld = 0;
46
48
 
47
49
  // counts
48
50
  this.offlineDevicesCount = 0;
@@ -74,11 +76,13 @@ class DeviceWatcher extends utils.Adapter {
74
76
 
75
77
  this.supAdapter = {
76
78
  alexa2: this.config.alexa2Devices,
79
+ apcups: this.config.apcupsDevices,
77
80
  ble: this.config.bleDevices,
78
81
  deconz: this.config.deconzDevices,
79
82
  enocean: this.config.enoceanDevices,
80
83
  esphome: this.config.esphomeDevices,
81
84
  fritzdect: this.config.fritzdectDevices,
85
+ fullybrowser: this.config.fullybrowserDevices,
82
86
  ham: this.config.hamDevices,
83
87
  harmony: this.config.harmonyDevices,
84
88
  hmiP: this.config.hmiPDevices,
@@ -93,6 +97,8 @@ class DeviceWatcher extends utils.Adapter {
93
97
  mihome: this.config.mihomeDevices,
94
98
  mihomeGW: this.config.mihomeDevices,
95
99
  mihomeVacuum: this.config.mihomeVacuumDevices,
100
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttDevices,
101
+ mqttNuki: this.config.mqttNukiDevices,
96
102
  netatmo: this.config.netatmoDevices,
97
103
  nukiExt: this.config.nukiExtDevices,
98
104
  nut: this.config.nutDevices,
@@ -101,8 +107,10 @@ class DeviceWatcher extends utils.Adapter {
101
107
  shelly: this.config.shellyDevices,
102
108
  sonoff: this.config.sonoffDevices,
103
109
  sonos: this.config.sonosDevices,
110
+ sureflap: this.config.sureflapDevices,
104
111
  switchbotBle: this.config.switchbotBleDevices,
105
112
  tado: this.config.tadoDevices,
113
+ tapo: this.config.tapoDevices,
106
114
  tradfri: this.config.tradfriDevices,
107
115
  unifi: this.config.unifiDevices,
108
116
  wled: this.config.wledDevices,
@@ -114,11 +122,13 @@ class DeviceWatcher extends utils.Adapter {
114
122
 
115
123
  this.maxMinutes = {
116
124
  alexa2: this.config.alexa2MaxMinutes,
125
+ apcups: this.config.apcupsMaxMinutes,
117
126
  ble: this.config.bleMaxMinutes,
118
127
  deconz: this.config.deconzMaxMinutes,
119
128
  enocean: this.config.enoceanMaxMinutes,
120
129
  esphome: this.config.esphomeMaxMinutes,
121
130
  fritzdect: this.config.fritzdectMaxMinutes,
131
+ fullybrowser: this.config.fullybrowserMaxMinutes,
122
132
  ham: this.config.hamMaxMinutes,
123
133
  harmony: this.config.harmonyMaxMinutes,
124
134
  hmiP: this.config.hmiPMaxMinutes,
@@ -133,6 +143,8 @@ class DeviceWatcher extends utils.Adapter {
133
143
  mihome: this.config.mihomeMaxMinutes,
134
144
  mihomeGW: this.config.mihomeMaxMinutes,
135
145
  mihomeVacuum: this.config.mihomeVacuumMaxMinutes,
146
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttMaxMinutes,
147
+ mqttNuki: this.config.mqttNukiMaxMinutes,
136
148
  netatmo: this.config.netatmoMaxMinutes,
137
149
  nukiExt: this.config.nukiextendMaxMinutes,
138
150
  nut: this.config.nutMaxMinutes,
@@ -141,8 +153,10 @@ class DeviceWatcher extends utils.Adapter {
141
153
  shelly: this.config.shellyMaxMinutes,
142
154
  sonoff: this.config.sonoffMaxMinutes,
143
155
  sonos: this.config.sonosMaxMinutes,
156
+ sureflap: this.config.sureflapMaxMinutes,
144
157
  switchbotBle: this.config.switchbotMaxMinutes,
145
158
  tado: this.config.tadoMaxMinutes,
159
+ tapo: this.config.tapoMaxMinutes,
146
160
  tradfri: this.config.tradfriMaxMinutes,
147
161
  unifi: this.config.unifiMaxMinutes,
148
162
  wled: this.config.wledMaxMinutes,
@@ -206,6 +220,12 @@ class DeviceWatcher extends utils.Adapter {
206
220
  // update data in interval
207
221
  await this.refreshData();
208
222
 
223
+ // trigger update notification on state change
224
+ /*
225
+ if (this.config.checkSendAdapterUpdateNotify) {
226
+ this.subscribeForeignStatesAsync(`admin.*.info.updatesJson`);
227
+ }*/
228
+
209
229
  // send overview for low battery devices
210
230
  if (this.config.checkSendBatteryMsg) await this.sendBatteryNotifyShedule();
211
231
 
@@ -223,12 +243,10 @@ class DeviceWatcher extends utils.Adapter {
223
243
  * @param {ioBroker.State | null | undefined} state
224
244
  */
225
245
  onStateChange(id, state) {
226
- if (state) {
227
- // The state was changed
228
- this.log.warn(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
229
- } else {
230
- // The state was deleted
231
- this.log.warn(`state ${id} deleted`);
246
+ // Admin JSON for Adapter updates
247
+ if (id && state) {
248
+ this.log.debug(`State changed: ${id} changed ${state.val}`);
249
+ //this.sendAdapterUpdatesNotification(id, state);
232
250
  }
233
251
  }
234
252
 
@@ -426,6 +444,8 @@ class DeviceWatcher extends utils.Adapter {
426
444
  // Get ID for Switchbot and ESPHome Devices
427
445
  case 'switchbotBle':
428
446
  case 'esphome':
447
+ case 'fullybrowser':
448
+ case 'apcups':
429
449
  deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
430
450
  break;
431
451
 
@@ -457,6 +477,19 @@ class DeviceWatcher extends utils.Adapter {
457
477
  deviceName = currDeviceString.slice(currDeviceString.lastIndexOf('.') + 1);
458
478
  break;
459
479
 
480
+ // Format Device name
481
+ case 'sureflap':
482
+ if (deviceObject && typeof deviceObject === 'object') {
483
+ deviceName = deviceObject.common.name
484
+ // @ts-ignore FIXME: fix syntax error
485
+ .replace(/'/g, '')
486
+ .replace(/\(\d+\)/g, '')
487
+ .trim()
488
+ .replace('Hub', 'Hub -')
489
+ .replace('Device', 'Device -');
490
+ }
491
+ break;
492
+
460
493
  //Get ID of foldername
461
494
  case 'yeelight':
462
495
  deviceName = shortCurrDeviceString.slice(shortCurrDeviceString.lastIndexOf('.') + 1);
@@ -504,6 +537,7 @@ class DeviceWatcher extends utils.Adapter {
504
537
  this.offlineDevices = [];
505
538
  this.batteryLowPoweredRaw = [];
506
539
  this.offlineDevicesRaw = [];
540
+ this.upgradableList = [];
507
541
 
508
542
  for (const device of this.listAllDevicesRaw) {
509
543
  /*---------- fill raw lists ----------*/
@@ -570,6 +604,14 @@ class DeviceWatcher extends utils.Adapter {
570
604
  'Last contact': device['Last contact'],
571
605
  });
572
606
  }
607
+
608
+ // Device update List
609
+ if (device['Upgradable']) {
610
+ this.upgradableList.push({
611
+ Device: device['Device'],
612
+ Adapter: device['Adapter'],
613
+ });
614
+ }
573
615
  }
574
616
  }
575
617
  }
@@ -630,6 +672,7 @@ class DeviceWatcher extends utils.Adapter {
630
672
  =============================================*/
631
673
  let deviceQualityState;
632
674
  let linkQuality;
675
+ let mqttNukiValue;
633
676
 
634
677
  switch (adapterID) {
635
678
  case 'mihomeVacuum':
@@ -687,6 +730,15 @@ class DeviceWatcher extends utils.Adapter {
687
730
  case 'nukiExt':
688
731
  linkQuality = ' - ';
689
732
  break;
733
+ case 'mqttNuki':
734
+ linkQuality = deviceQualityState.val;
735
+ mqttNukiValue = parseInt(linkQuality);
736
+ if (this.config.trueState) {
737
+ linkQuality = deviceQualityState.val;
738
+ } else if (mqttNukiValue < 0) {
739
+ linkQuality = Math.min(Math.max(2 * (mqttNukiValue + 100), 0), 100) + '%';
740
+ // If Quality State is an value between 0-255 (zigbee) calculate in percent:
741
+ }
690
742
  }
691
743
  break;
692
744
  }
@@ -702,9 +754,16 @@ class DeviceWatcher extends utils.Adapter {
702
754
  let isBatteryDevice;
703
755
 
704
756
  // Get battery states
705
- const deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery);
706
- const shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery);
707
- const shortDeviceBatteryState2 = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery2);
757
+ let deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery);
758
+ if (deviceBatteryState === undefined) {
759
+ deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery2);
760
+ }
761
+
762
+ // Get battery states with short path
763
+ let shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery);
764
+ if (shortDeviceBatteryState === undefined) {
765
+ shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery2);
766
+ }
708
767
 
709
768
  // Get low bat states
710
769
  let deviceLowBatState = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat);
@@ -712,7 +771,7 @@ class DeviceWatcher extends utils.Adapter {
712
771
  deviceLowBatState = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat2);
713
772
  }
714
773
 
715
- if (!deviceBatteryState && !shortDeviceBatteryState && !shortDeviceBatteryState2) {
774
+ if (deviceBatteryState === undefined && shortDeviceBatteryState === undefined) {
716
775
  if (deviceLowBatState !== undefined) {
717
776
  switch (this.arrDev[i].isLowBat || this.arrDev[i].isLowBat2) {
718
777
  case 'none':
@@ -734,7 +793,7 @@ class DeviceWatcher extends utils.Adapter {
734
793
  } else {
735
794
  switch (adapterID) {
736
795
  case 'hmrpc':
737
- if (deviceBatteryState === 0) {
796
+ if (deviceBatteryState === 0 || (deviceBatteryState && deviceBatteryState >= 6)) {
738
797
  batteryHealth = ' - ';
739
798
  } else {
740
799
  batteryHealth = deviceBatteryState + 'V';
@@ -743,20 +802,14 @@ class DeviceWatcher extends utils.Adapter {
743
802
  break;
744
803
 
745
804
  case 'hueExt':
746
- if (shortDeviceBatteryState) {
747
- batteryHealth = shortDeviceBatteryState + '%';
748
- isBatteryDevice = true;
749
- }
750
- break;
751
805
  case 'mihomeVacuum':
806
+ case 'mqttNuki':
752
807
  if (shortDeviceBatteryState) {
753
808
  batteryHealth = shortDeviceBatteryState + '%';
754
809
  isBatteryDevice = true;
755
- } else if (shortDeviceBatteryState2) {
756
- batteryHealth = shortDeviceBatteryState2 + '%';
757
- isBatteryDevice = true;
758
810
  }
759
811
  break;
812
+
760
813
  default:
761
814
  batteryHealth = deviceBatteryState + '%';
762
815
  isBatteryDevice = true;
@@ -810,7 +863,6 @@ class DeviceWatcher extends utils.Adapter {
810
863
  const deviceUnreachState = await this.getInitValue(currDeviceString + this.arrDev[i].reach);
811
864
  const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? await this.getTimestamp(deviceUnreachSelector.lc) : await this.getTimestamp(deviceMainSelector.ts);
812
865
  const shortDeviceUnreachState = await this.getForeignStateAsync(shortCurrDeviceString + this.arrDev[i].reach);
813
-
814
866
  // If there is no contact since user sets minutes add device in offline list
815
867
  // calculate to days after 48 hours
816
868
  switch (this.arrDev[i].reach) {
@@ -864,37 +916,33 @@ class DeviceWatcher extends utils.Adapter {
864
916
  linkQuality = '0%'; // set linkQuality to nothing
865
917
  }
866
918
  break;
919
+ case 'apcups':
920
+ case 'hue':
921
+ case 'hueExt':
867
922
  case 'ping':
868
923
  case 'deconz':
869
- if (this.maxMinutes[adapterID] <= 0) {
870
- if (!deviceUnreachState) {
871
- deviceState = 'Offline'; //set online state to offline
872
- linkQuality = '0%'; // set linkQuality to nothing
873
- }
874
- } else if (lastDeviceUnreachStateChange > this.maxMinutes[adapterID] && !deviceUnreachState) {
875
- deviceState = 'Offline'; //set online state to offline
876
- linkQuality = '0%'; // set linkQuality to nothing
877
- }
878
- break;
924
+ case 'shelly':
925
+ case 'sonoff':
879
926
  case 'unifi':
927
+ case 'zigbee':
928
+ case 'zigbee2MQTT':
880
929
  if (this.maxMinutes[adapterID] <= 0) {
881
- if (deviceUnreachState === 0) {
930
+ if (!deviceUnreachState) {
882
931
  deviceState = 'Offline'; //set online state to offline
883
932
  linkQuality = '0%'; // set linkQuality to nothing
884
933
  }
885
- } else if (this.maxMinutes !== undefined && lastContact > this.maxMinutes[adapterID]) {
934
+ } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.maxMinutes[adapterID]) {
886
935
  deviceState = 'Offline'; //set online state to offline
887
936
  linkQuality = '0%'; // set linkQuality to nothing
888
937
  }
889
938
  break;
890
- case 'shelly':
891
- case 'sonoff':
939
+ case 'mqttClientZigbee2Mqtt':
892
940
  if (this.maxMinutes[adapterID] <= 0) {
893
- if (!deviceUnreachState) {
941
+ if (deviceUnreachState !== 'online') {
894
942
  deviceState = 'Offline'; //set online state to offline
895
943
  linkQuality = '0%'; // set linkQuality to nothing
896
944
  }
897
- } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.maxMinutes[adapterID]) {
945
+ } else if (deviceUnreachState !== 'online' && lastDeviceUnreachStateChange > this.maxMinutes[adapterID]) {
898
946
  deviceState = 'Offline'; //set online state to offline
899
947
  linkQuality = '0%'; // set linkQuality to nothing
900
948
  }
@@ -950,6 +998,20 @@ class DeviceWatcher extends utils.Adapter {
950
998
  this.errorReporting('[getLastContact]', error);
951
999
  }
952
1000
  }
1001
+ /*=============================================
1002
+ = Get update data =
1003
+ =============================================*/
1004
+ let deviceUpdateSelector;
1005
+ let isUpgradable;
1006
+
1007
+ if (this.config.checkSendDeviceUpgrade) {
1008
+ deviceUpdateSelector = await this.getInitValue(currDeviceString + this.arrDev[i].upgrade);
1009
+ if (deviceUpdateSelector) {
1010
+ isUpgradable = true;
1011
+ } else {
1012
+ isUpgradable = false;
1013
+ }
1014
+ }
953
1015
 
954
1016
  /*=============================================
955
1017
  = Fill Raw Lists =
@@ -968,6 +1030,7 @@ class DeviceWatcher extends utils.Adapter {
968
1030
  'Signal strength': linkQuality,
969
1031
  'Last contact': lastContactString,
970
1032
  Status: deviceState,
1033
+ Upgradable: isUpgradable,
971
1034
  });
972
1035
  }
973
1036
  } else {
@@ -982,6 +1045,7 @@ class DeviceWatcher extends utils.Adapter {
982
1045
  'Signal strength': linkQuality,
983
1046
  'Last contact': lastContactString,
984
1047
  Status: deviceState,
1048
+ Upgradable: isUpgradable,
985
1049
  });
986
1050
  }
987
1051
  } else {
@@ -1038,6 +1102,9 @@ class DeviceWatcher extends utils.Adapter {
1038
1102
  // send message if new devices are offline
1039
1103
  if (this.config.checkSendOfflineMsg) await this.sendOfflineNotifications();
1040
1104
 
1105
+ // send overview of upgradable devices
1106
+ if (this.config.checkSendDeviceUpgrade) await this.sendDeviceUpdatesNotification();
1107
+
1041
1108
  await this.writeDatapoints(); // fill the datapoints
1042
1109
  } catch (error) {
1043
1110
  this.errorReporting('[createDataOfAllAdapter]', error);
@@ -1170,6 +1237,26 @@ class DeviceWatcher extends utils.Adapter {
1170
1237
  } catch (error) {
1171
1238
  this.errorReporting('[sendNotification Lovelace]', error);
1172
1239
  }
1240
+
1241
+ // Synochat Notification
1242
+ try {
1243
+ if (this.config.instanceSynochat) {
1244
+ //first check if instance is living
1245
+ const synochatAliveState = await this.getInitValue('system.adapter.' + this.config.instanceSynochat + '.alive');
1246
+
1247
+ if (!synochatAliveState) {
1248
+ this.log.warn('Synochat instance is not running. Message could not be sent. Please check your instance configuration.');
1249
+ } else {
1250
+ if (this.config.channelSynochat !== undefined) {
1251
+ await this.setForeignStateAsync(`${this.config.instanceSynochat}.${this.config.channelSynochat}.message`, text);
1252
+ } else {
1253
+ this.log.warn('Synochat channel is not set. Message could not be sent. Please check your instance configuration.');
1254
+ }
1255
+ }
1256
+ }
1257
+ } catch (error) {
1258
+ this.errorReporting('[sendNotification Synochat]', error);
1259
+ }
1173
1260
  } // <-- End of sendNotification function
1174
1261
 
1175
1262
  /**
@@ -1205,15 +1292,19 @@ class DeviceWatcher extends utils.Adapter {
1205
1292
 
1206
1293
  for (const id of this.batteryLowPoweredRaw) {
1207
1294
  if (!this.blacklistNotify.includes(id['Path'])) {
1208
- deviceList = `${deviceList}\n${id['Device']} (${id['Battery']})`;
1295
+ if (!this.config.showAdapterNameinMsg) {
1296
+ deviceList = `${deviceList}\n${id['Device']} (${id['Battery']})`;
1297
+ } else {
1298
+ // Add adaptername if checkbox is checked true in options by user
1299
+ deviceList = `${deviceList}\n${id['Adapter']}: ${id['Device']} (${id['Battery']})`;
1300
+ }
1209
1301
  }
1210
1302
  }
1211
-
1212
- if (this.lowBatteryPoweredCountRaw > 0 && deviceList.length > 0) {
1303
+ if (deviceList.length > 0) {
1213
1304
  this.log.info(`Niedrige Batteriezustände: ${deviceList}`);
1214
1305
  this.setStateAsync('lastNotification', `Niedrige Batteriezustände: ${deviceList}`, true);
1215
1306
 
1216
- this.sendNotification(`Niedriege Batteriezustände: ${deviceList}`);
1307
+ this.sendNotification(`Niedrige Batteriezustände: ${deviceList}`);
1217
1308
  }
1218
1309
  } catch (error) {
1219
1310
  this.errorReporting('[sendBatteryNotifyShedule]', error);
@@ -1234,13 +1325,17 @@ class DeviceWatcher extends utils.Adapter {
1234
1325
 
1235
1326
  for (const id of this.offlineDevicesRaw) {
1236
1327
  if (!this.blacklistNotify.includes(id['Path'])) {
1237
- deviceList = `${deviceList}\n${id['Device']} (${id['Last contact']})`;
1328
+ if (!this.config.showAdapterNameinMsg) {
1329
+ deviceList = `${deviceList}\n${id['Device']} (${id['Last contact']})`;
1330
+ } else {
1331
+ deviceList = `${deviceList}\n${id['Adapter']}: ${id['Device']} (${id['Last contact']})`;
1332
+ }
1238
1333
  }
1239
1334
  }
1240
1335
  if (deviceList.length !== this.offlineDevicesCountRawOld) {
1241
- if (deviceList.length == 0) {
1336
+ if (deviceList.length === 0) {
1242
1337
  msg = 'Alle Geräte sind Online.';
1243
- } else if (deviceList.length == 1) {
1338
+ } else if (deviceList.length === 1) {
1244
1339
  // make singular if it is only one device
1245
1340
  msg = 'Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n';
1246
1341
  } else if (deviceList.length >= 2) {
@@ -1292,7 +1387,11 @@ class DeviceWatcher extends utils.Adapter {
1292
1387
 
1293
1388
  for (const id of this.offlineDevicesRaw) {
1294
1389
  if (!this.blacklistNotify.includes(id['Path'])) {
1295
- deviceList = `${deviceList}\n${id['Device']} (${id['Last contact']})`;
1390
+ if (!this.config.showAdapterNameinMsg) {
1391
+ deviceList = `${deviceList}\n${id['Device']} (${id['Last contact']})`;
1392
+ } else {
1393
+ deviceList = `${deviceList}\n${id['Adapter']}: ${id['Device']} (${id['Last contact']})`;
1394
+ }
1296
1395
  }
1297
1396
  }
1298
1397
 
@@ -1309,6 +1408,75 @@ class DeviceWatcher extends utils.Adapter {
1309
1408
  }
1310
1409
  } //<--End of daily offline notification
1311
1410
 
1411
+ /**
1412
+ * check if adapter updates are available and send notification
1413
+ * @param {string} id
1414
+ * @param {ioBroker.State | null | undefined} state
1415
+ */
1416
+ /*
1417
+ async sendAdapterUpdatesNotification(id, state) {
1418
+ this.log.debug(`Start the function: ${this.sendAdapterUpdatesNotification.name}`);
1419
+
1420
+ try {
1421
+ if (state && state !== undefined) {
1422
+ const list = await this.parseData(state.val);
1423
+ let msg = '';
1424
+ let adapterList = '';
1425
+
1426
+ for (const [id] of Object.entries(list)) {
1427
+ adapterList = `${adapterList}\n${this.capitalize(id)} - Version: ${list[id].availableVersion}`;
1428
+ }
1429
+ if (adapterList.length !== 0) {
1430
+ msg = `Neue Adapter Updates vorhanden: \n`;
1431
+
1432
+ this.log.info(msg + adapterList);
1433
+ await this.setStateAsync('lastNotification', msg + adapterList, true);
1434
+ await this.sendNotification(msg + adapterList);
1435
+ }
1436
+ }
1437
+ } catch (error) {
1438
+ this.errorReporting('[sendAdapterUpdatesNotification]', error);
1439
+ }
1440
+ this.log.debug(`Finished the function: ${this.sendAdapterUpdatesNotification.name}`);
1441
+ }*/
1442
+
1443
+ /**
1444
+ * check if device updates are available and send notification
1445
+ **/
1446
+ async sendDeviceUpdatesNotification() {
1447
+ this.log.debug(`Start the function: ${this.sendDeviceUpdatesNotification.name}`);
1448
+
1449
+ try {
1450
+ let msg = '';
1451
+ let deviceList = '';
1452
+
1453
+ for (const id of this.upgradableList) {
1454
+ if (!this.blacklistNotify.includes(id['Path'])) {
1455
+ if (!this.config.showAdapterNameinMsg) {
1456
+ deviceList = `${deviceList}\n${id['Device']}`;
1457
+ } else {
1458
+ deviceList = `${deviceList}\n${id['Adapter']}: ${id['Device']}`;
1459
+ }
1460
+ }
1461
+ }
1462
+ if (deviceList.length !== this.upgradableDevicesCountRawOld) {
1463
+ if (deviceList.length >= 1) {
1464
+ msg = `Neue Geräte Updates vorhanden: \n`;
1465
+
1466
+ this.log.info(msg + deviceList);
1467
+ this.upgradableDevicesCountRawOld = deviceList.length;
1468
+ await this.setStateAsync('lastNotification', msg + deviceList, true);
1469
+ await this.sendNotification(msg + deviceList);
1470
+ } else {
1471
+ this.upgradableDevicesCountRawOld = deviceList.length;
1472
+ }
1473
+ }
1474
+ } catch (error) {
1475
+ this.errorReporting('[sendDeviceUpdatesNotification]', error);
1476
+ }
1477
+ this.log.debug(`Finished the function: ${this.sendDeviceUpdatesNotification.name}`);
1478
+ }
1479
+
1312
1480
  /**
1313
1481
  * reset arrays and counts
1314
1482
  */
@@ -1362,13 +1530,13 @@ class DeviceWatcher extends utils.Adapter {
1362
1530
  await this.setStateAsync(`${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1363
1531
  await this.setStateAsync(`${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1364
1532
 
1365
- if (this.deviceCounter == 0) {
1533
+ if (this.deviceCounter === 0) {
1366
1534
  // if no device is count, write the JSON List with default value
1367
1535
  this.listAllDevices = [{ Device: '--none--', Adapter: '', Battery: '', 'Last contact': '', 'Signal strength': '' }];
1368
1536
  }
1369
1537
  await this.setStateAsync(`${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1370
1538
 
1371
- if (this.linkQualityCount == 0) {
1539
+ if (this.linkQualityCount === 0) {
1372
1540
  // if no device is count, write the JSON List with default value
1373
1541
  this.linkQualityDevices = [{ Device: '--none--', Adapter: '', 'Signal strength': '' }];
1374
1542
  }
@@ -1384,7 +1552,7 @@ class DeviceWatcher extends utils.Adapter {
1384
1552
  ack: true,
1385
1553
  });
1386
1554
 
1387
- if (this.offlineDevicesCount == 0) {
1555
+ if (this.offlineDevicesCount === 0) {
1388
1556
  // if no device is count, write the JSON List with default value
1389
1557
  this.offlineDevices = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1390
1558
  }
@@ -1400,7 +1568,7 @@ class DeviceWatcher extends utils.Adapter {
1400
1568
  ack: true,
1401
1569
  });
1402
1570
 
1403
- if (this.batteryPoweredCount == 0) {
1571
+ if (this.batteryPoweredCount === 0) {
1404
1572
  // if no device is count, write the JSON List with default value
1405
1573
  this.batteryPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1406
1574
  }
@@ -1416,7 +1584,7 @@ class DeviceWatcher extends utils.Adapter {
1416
1584
  ack: true,
1417
1585
  });
1418
1586
 
1419
- if (this.lowBatteryPoweredCount == 0) {
1587
+ if (this.lowBatteryPoweredCount === 0) {
1420
1588
  // if no device is count, write the JSON List with default value
1421
1589
  this.batteryLowPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1422
1590
  }
@@ -1447,7 +1615,9 @@ class DeviceWatcher extends utils.Adapter {
1447
1615
  */
1448
1616
  async creatLinkQualityListHTML(devices, deviceCount) {
1449
1617
  devices = devices.sort((a, b) => {
1450
- return a.Device.localeCompare(b.Device);
1618
+ a = a.Device || '';
1619
+ b = b.Device || '';
1620
+ return a.localeCompare(b);
1451
1621
  });
1452
1622
  let html = `<center>
1453
1623
  <b>Link Quality Devices:<font> ${deviceCount}</b><small></small></font>
@@ -1481,10 +1651,12 @@ class DeviceWatcher extends utils.Adapter {
1481
1651
  */
1482
1652
  async createOfflineListHTML(devices, deviceCount) {
1483
1653
  devices = devices.sort((a, b) => {
1484
- return a.Device.localeCompare(b.Device);
1654
+ a = a.Device || '';
1655
+ b = b.Device || '';
1656
+ return a.localeCompare(b);
1485
1657
  });
1486
1658
  let html = `<center>
1487
- <b>Offline Devices: <font color=${deviceCount == 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
1659
+ <b>Offline Devices: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
1488
1660
  <p></p>
1489
1661
  </center>
1490
1662
  <table width=100%>
@@ -1516,10 +1688,12 @@ class DeviceWatcher extends utils.Adapter {
1516
1688
  */
1517
1689
  async createBatteryListHTML(devices, deviceCount, isLowBatteryList) {
1518
1690
  devices = devices.sort((a, b) => {
1519
- return a.Device.localeCompare(b.Device);
1691
+ a = a.Device || '';
1692
+ b = b.Device || '';
1693
+ return a.localeCompare(b);
1520
1694
  });
1521
1695
  let html = `<center>
1522
- <b>${isLowBatteryList == true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList == true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
1696
+ <b>${isLowBatteryList === true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
1523
1697
  <p></p>
1524
1698
  </center>
1525
1699
  <table width=100%>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.device-watcher",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Watchdog for devices",
5
5
  "author": {
6
6
  "name": "Christian Behrends",
@@ -30,30 +30,29 @@
30
30
  "@alcalzone/release-script-plugin-license": "^3.5.9",
31
31
  "@iobroker/adapter-dev": "^1.2.0",
32
32
  "@iobroker/testing": "^4.1.0",
33
- "@types/chai": "^4.3.3",
33
+ "@types/chai": "^4.3.4",
34
34
  "@types/chai-as-promised": "^7.1.5",
35
- "@types/mocha": "^10.0.0",
36
- "@types/node": "^18.11.8",
35
+ "@types/mocha": "^10.0.1",
36
+ "@types/node": "^18.11.10",
37
37
  "@types/node-schedule": "^2.1.0",
38
38
  "@types/proxyquire": "^1.3.28",
39
39
  "@types/sinon": "^10.0.13",
40
- "@types/sinon-chai": "^3.2.8",
41
- "chai": "^4.3.6",
40
+ "@types/sinon-chai": "^3.2.9",
41
+ "chai": "^4.3.7",
42
42
  "chai-as-promised": "^7.1.1",
43
- "eslint": "^8.26.0",
43
+ "eslint": "^8.28.0",
44
44
  "eslint-config-prettier": "^8.5.0",
45
45
  "eslint-plugin-prettier": "^4.2.1",
46
46
  "mocha": "^10.1.0",
47
47
  "node-schedule": "^2.1.0",
48
- "prettier": "^2.7.1",
48
+ "prettier": "^2.8.0",
49
49
  "proxyquire": "^2.1.3",
50
- "sinon": "^14.0.1",
50
+ "sinon": "^15.0.0",
51
51
  "sinon-chai": "^3.7.0",
52
- "typescript": "~4.8.4"
52
+ "typescript": "~4.9.3"
53
53
  },
54
54
  "main": "main.js",
55
55
  "files": [
56
- "admin{,/!(src)/**}/!(tsconfig|tsconfig.*).json",
57
56
  "admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}",
58
57
  "lib/",
59
58
  "www/",