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/README.md +38 -45
- package/io-package.json +99 -82
- package/lib/arrApart.js +59 -1
- package/main.js +228 -54
- package/package.json +10 -11
- package/admin/i18n/de/translations.json +0 -80
- package/admin/i18n/en/translations.json +0 -80
- package/admin/i18n/es/translations.json +0 -80
- package/admin/i18n/fr/translations.json +0 -80
- package/admin/i18n/it/translations.json +0 -80
- package/admin/i18n/nl/translations.json +0 -80
- package/admin/i18n/pl/translations.json +0 -80
- package/admin/i18n/pt/translations.json +0 -80
- package/admin/i18n/ru/translations.json +0 -80
- package/admin/i18n/uk/translations.json +0 -80
- package/admin/i18n/zh-cn/translations.json +0 -80
- package/admin/index_m.html +0 -56
- package/admin/jsonConfig.json +0 -1302
- package/admin/style.css +0 -32
- package/admin/words.js +0 -41
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
|
-
|
|
227
|
-
|
|
228
|
-
this.log.
|
|
229
|
-
|
|
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
|
-
|
|
706
|
-
|
|
707
|
-
|
|
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 (
|
|
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
|
-
|
|
870
|
-
|
|
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
|
|
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 (
|
|
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 '
|
|
891
|
-
case 'sonoff':
|
|
939
|
+
case 'mqttClientZigbee2Mqtt':
|
|
892
940
|
if (this.maxMinutes[adapterID] <= 0) {
|
|
893
|
-
if (
|
|
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 (
|
|
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
|
-
|
|
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(`
|
|
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
|
-
|
|
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
|
|
1336
|
+
if (deviceList.length === 0) {
|
|
1242
1337
|
msg = 'Alle Geräte sind Online.';
|
|
1243
|
-
} else if (deviceList.length
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1691
|
+
a = a.Device || '';
|
|
1692
|
+
b = b.Device || '';
|
|
1693
|
+
return a.localeCompare(b);
|
|
1520
1694
|
});
|
|
1521
1695
|
let html = `<center>
|
|
1522
|
-
<b>${isLowBatteryList
|
|
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
|
|
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.
|
|
33
|
+
"@types/chai": "^4.3.4",
|
|
34
34
|
"@types/chai-as-promised": "^7.1.5",
|
|
35
|
-
"@types/mocha": "^10.0.
|
|
36
|
-
"@types/node": "^18.11.
|
|
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.
|
|
41
|
-
"chai": "^4.3.
|
|
40
|
+
"@types/sinon-chai": "^3.2.9",
|
|
41
|
+
"chai": "^4.3.7",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
|
-
"eslint": "^8.
|
|
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.
|
|
48
|
+
"prettier": "^2.8.0",
|
|
49
49
|
"proxyquire": "^2.1.3",
|
|
50
|
-
"sinon": "^
|
|
50
|
+
"sinon": "^15.0.0",
|
|
51
51
|
"sinon-chai": "^3.7.0",
|
|
52
|
-
"typescript": "~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/",
|