iobroker.device-watcher 0.0.6 → 0.1.2

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
@@ -16,269 +16,542 @@ class DeviceWatcher extends utils.Adapter {
16
16
  useFormatDate: true,
17
17
  });
18
18
 
19
- this.refreshEverythingTimeout = null;
20
-
21
19
  this.on('ready', this.onReady.bind(this));
22
20
  //this.on('stateChange', this.onStateChange.bind(this));
23
21
  // this.on('objectChange', this.onObjectChange.bind(this));
24
22
  // this.on('message', this.onMessage.bind(this));
25
23
  this.on('unload', this.onUnload.bind(this));
24
+
25
+ // arrays
26
+ this.offlineDevices = [],
27
+ this.linkQualityDevices = [];
28
+ this.batteryPowered = [];
29
+ this.batteryLowPowered = [];
30
+ this.listAllDevices = [];
31
+ this.blacklistArr = [];
32
+ this.arrDev = [];
33
+ this.adapterSelected = [];
34
+
35
+ // counts
36
+ this.offlineDevicesCount = 0;
37
+ this.deviceCounter = 0;
38
+ this.linkQualityCount = 0;
39
+ this.batteryPoweredCount = 0;
40
+ this.lowBatteryPoweredCount = 0;
41
+
42
+ this.deviceReachable = '';
43
+
44
+ // arrays of supported adapters
45
+ this.arrApart = {
46
+ //**** This Datapoints are only for the dev ****//
47
+ test: {'Selektor':'0_userdata.*.UNREACH', 'adapter':'homematic', 'rssiState':'.RSSI_DEVICE', 'battery':'.OPERATING_VOLTAGE', 'reach':'.UNREACH'},
48
+ test2: {'Selektor':'0_userdata.*.alive', 'adapter':'esphome', 'rssiState': '.Wifi_RSSI', 'battery':'none', 'reach':'.alive', 'isLowBat':'none', 'id':'.name'},
49
+ test3: {'Selektor':'0_userdata.*.link_quality', 'adapter':'zigbee', 'battery':'.battery', 'reach':'available', 'isLowBat':'none'},
50
+ //**** End of Dev Datapoints ****//
51
+ alexa2: {
52
+ 'Selektor':'alexa2.*.online',
53
+ 'adapter':'alexa2',
54
+ 'battery':'none',
55
+ 'reach':'.online',
56
+ 'isLowBat':'none'
57
+ },
58
+ ble: {
59
+ 'Selektor':'ble.*.rssi',
60
+ 'adapter':'ble',
61
+ 'battery':'.battery',
62
+ 'reach':'none',
63
+ 'isLowBat':'none'
64
+ },
65
+ esphome: {
66
+ 'Selektor':'esphome.*._online',
67
+ 'adapter':'esphome',
68
+ 'battery':'none',
69
+ 'reach':'._online',
70
+ 'isLowBat':'none',
71
+ 'id':'.name'
72
+ },
73
+ zigbee: {
74
+ 'Selektor':'zigbee.*.link_quality',
75
+ 'adapter':'zigbee',
76
+ 'battery':'.battery',
77
+ 'reach':'.available',
78
+ 'isLowBat':'none'
79
+ },
80
+ sonoff: {
81
+ 'Selektor':'sonoff.*.Uptime',
82
+ 'adapter':'sonoff',
83
+ 'rssiState': '.Wifi_RSSI',
84
+ 'battery':'.battery',
85
+ 'reach':'.alive',
86
+ 'isLowBat':'none'
87
+ },
88
+ shelly: {
89
+ 'Selektor':'shelly.*.rssi',
90
+ 'adapter':'shelly',
91
+ 'battery':'.sensor.battery',
92
+ 'reach':'.online',
93
+ 'isLowBat':'none'
94
+ },
95
+ homematic: {
96
+ 'Selektor':'hm-rpc.*.UNREACH',
97
+ 'adapter':'homematic',
98
+ 'rssiState':'.RSSI_DEVICE',
99
+ 'battery':'.OPERATING_VOLTAGE',
100
+ 'reach':'.UNREACH',
101
+ 'isLowBat':'.LOW_BAT',
102
+ 'isLowBat2':'.LOWBAT'
103
+ },
104
+ deconz: {
105
+ 'Selektor':'deconz.*.reachable',
106
+ 'adapter':'deconz',
107
+ 'battery':'.battery',
108
+ 'reach':'.reachable',
109
+ 'isLowBat':'none'
110
+ },
111
+ zwave: {
112
+ 'Selektor':'zwave2.*.ready',
113
+ 'adapter':'zwave',
114
+ 'battery':'.Battery.level',
115
+ 'reach':'.ready',
116
+ 'isLowBat':'.Battery.isLow'
117
+ },
118
+ dect: {
119
+ 'Selektor':'fritzdect.*.present',
120
+ 'adapter':'fritzDect',
121
+ 'battery':'.battery',
122
+ 'reach':'.present',
123
+ 'isLowBat':'.batterylow'
124
+ },
125
+ hue: {
126
+ 'Selektor':'hue.*.reachable',
127
+ 'adapter':'hue',
128
+ 'battery':'.battery',
129
+ 'reach':'.reachable',
130
+ 'isLowBat':'none'
131
+ },
132
+ hueExt: {
133
+ 'Selektor':'hue-extended.*.reachable',
134
+ 'adapter':'hue extended',
135
+ 'battery':'.config.battery',
136
+ 'reach':'.reachable',
137
+ 'isLowBat':'none'
138
+ },
139
+ ping: {
140
+ 'Selektor':'ping.*.alive',
141
+ 'adapter':'ping',
142
+ 'battery':'none',
143
+ 'reach':'.alive',
144
+ 'isLowBat':'none'
145
+ },
146
+ switchbotBle: {
147
+ 'Selektor':'switchbot-ble.*.rssi',
148
+ 'adapter':'switchbot ble',
149
+ 'battery':'.battery',
150
+ 'reach':'none',
151
+ 'isLowBat':'none',
152
+ 'id':'.id'
153
+ },
154
+ sonos: {
155
+ 'Selektor':'sonos.*.alive',
156
+ 'adapter':'sonos',
157
+ 'battery':'none',
158
+ 'reach':'.alive',
159
+ 'isLowBat':'none'
160
+ },
161
+ mihome: {
162
+ 'Selektor':'mihome.*.percent',
163
+ 'adapter':'miHome',
164
+ 'battery':'.percent',
165
+ 'reach':'none',
166
+ 'isLowBat':'none'
167
+ },
168
+ mihomeGW: {
169
+ 'Selektor':'mihome.*.connected',
170
+ 'adapter':'miHome',
171
+ 'battery':'none',
172
+ 'reach':'.connected',
173
+ 'isLowBat':'none'
174
+ },
175
+ nukiExt: {
176
+ 'Selektor':'nuki-extended.*.batteryCritical',
177
+ 'adapter':'nuki_extended',
178
+ 'battery':'none',
179
+ 'reach':'none',
180
+ 'isLowBat':'.batteryCritical'
181
+ }
182
+ };
26
183
  }
27
184
 
28
185
  async onReady() {
29
- this.log.debug('Adapter Device-Watcher was started');
186
+ this.log.debug(`Adapter ${adapterName} was started`);
30
187
 
31
188
  try {
32
189
  await this.main();
190
+ await this.sendNotifications();
191
+ await this.writeDatapoints();
33
192
  this.log.debug('all done, exiting');
34
193
  this.terminate ? this.terminate('Everything done. Going to terminate till next schedule', 11) : process.exit(0);
35
194
  } catch (e) {
36
- this.log.error('Error while running Device-Watcher. Error Message:' + e);
195
+ this.log.error(`Error while running Device-Watcher. Error Message: ${e}`);
37
196
  this.terminate ? this.terminate(15) : process.exit(15);
38
197
  }
39
-
40
-
41
-
42
198
  }
43
199
 
44
- async main() {
45
-
46
- //Helperfunctions
47
- //capitalize the first letter
48
- /*
49
- async function capitalize(sentence)
50
- {
51
- return sentence && sentence[0].toUpperCase() + sentence.slice(1);
52
- }*/
53
-
54
- const pushover = {
55
- instance: this.config.instancePushover,
56
- title: this.config.titlePushover,
57
- device: this.config.devicePushover
58
-
59
- };
60
- const telegram = {
61
- instance: this.config.instanceTelegram,
62
- user: this.config.deviceTelegram
63
- };
64
- const email = {
65
- instance: this.config.instanceEmail,
66
- subject: this.config.subjectEmail,
67
- sendTo: this.config.sendToEmail
68
-
69
- };
70
- const jarvis = {
71
- instance: this.config.instanceJarvis,
72
- title: this.config.titleJarvis
73
-
74
- };
75
- const choosedDays = {
76
- monday: this.config.checkMonday,
77
- tuesday: this.config.checkTuesday,
78
- wednesday: this.config.checkWednesday,
79
- thursday: this.config.checkThursday,
80
- friday: this.config.checkFriday,
81
- saturday: this.config.checkSaturday,
82
- sunday: this.config.checkSunday,
83
- };
200
+ //Helpfunctions
201
+ async capitalize(sentence)
202
+ {
203
+ //make the first letter uppercase
204
+ return sentence && sentence[0].toUpperCase() + sentence.slice(1);
205
+ }
84
206
 
85
- const sendPushover = async (text) => {
86
- await this.sendToAsync(pushover.instance, 'send', {
87
- message: text,
88
- title: pushover.title,
89
- device: pushover.device
90
- });
91
- };
207
+ async getInitValue(obj) {
208
+ //state can be null or undefinded
209
+ const foreignState = await this.getForeignStateAsync(obj);
210
+ if (foreignState) return foreignState.val;
211
+ }
92
212
 
93
- const sendTelegram = async (text) => {
94
- await this.sendToAsync(telegram.instance, 'send', {
95
- text: text,
96
- user: telegram.user
97
- });
98
- };
213
+ async getOwnInitValue(obj) {
214
+ //state can be null or undefinded for own states
215
+ const stateVal = await this.getStateAsync(obj);
216
+ if (stateVal) return stateVal.val;
217
+ }
99
218
 
100
- const sendEmail = async (text) => {
101
- await this.sendToAsync(email.instance, 'send', {
102
- sendTo: email.sendTo,
103
- text: text,
104
- subject: email.subject
105
- });
106
- };
219
+ //create datapoints for each adapter
220
+ async createDPsForEachAdapter(adptName) {
221
+ await this.setObjectNotExistsAsync(`${adptName}.offlineCount`, {
222
+ 'type': 'state',
223
+ 'common': {
224
+ 'name': 'Quantity devices offline',
225
+ 'type': 'number',
226
+ 'role': 'value',
227
+ 'read': true,
228
+ 'write': false,
229
+ 'def': 0
230
+ },
231
+ 'native': {}
232
+ });
233
+ await this.setObjectNotExistsAsync(`${adptName}.offlineList`, {
234
+ 'type': 'state',
235
+ 'common': {
236
+ 'name': 'List devices offline',
237
+ 'type': 'array',
238
+ 'role': 'json',
239
+ 'read': true,
240
+ 'write': false,
241
+ 'def': [{Device: '--keine--', Adapter: '', Last_contact: ''}]
242
+ },
243
+ 'native': {}
244
+ });
245
+ await this.setObjectNotExistsAsync(`${adptName}.listAll`, {
246
+ 'type': 'state',
247
+ 'common': {
248
+ 'name': 'List all devices',
249
+ 'type': 'array',
250
+ 'role': 'json',
251
+ 'read': true,
252
+ 'write': false,
253
+ 'def': [{Device: '--keine--', Adapter: '', Battery: '', Last_contact: '', Link_quality: ''}]
254
+ },
255
+ 'native': {}
256
+ });
257
+ await this.setObjectNotExistsAsync(`${adptName}.linkQualityList`, {
258
+ 'type': 'state',
259
+ 'common': {
260
+ 'name': 'List devices with qualitiy strength',
261
+ 'type': 'array',
262
+ 'role': 'json',
263
+ 'read': true,
264
+ 'write': false,
265
+ 'def': [{Device: '--keine--', Adapter: '', Link_quality: ''}]
266
+ },
267
+ 'native': {}
268
+ });
269
+ await this.setObjectNotExistsAsync(`${adptName}.countAll`, {
270
+ 'type': 'state',
271
+ 'common': {
272
+ 'name': 'Quantity devices all',
273
+ 'type': 'number',
274
+ 'role': 'value',
275
+ 'read': true,
276
+ 'write': false,
277
+ 'def': 0
278
+ },
279
+ 'native': {}
280
+ });
281
+ await this.setObjectNotExistsAsync(`${adptName}.batteryList`, {
282
+ 'type': 'state',
283
+ 'common': {
284
+ 'name': 'List devices with battery state',
285
+ 'type': 'array',
286
+ 'role': 'json',
287
+ 'read': true,
288
+ 'write': false,
289
+ 'def': [{Device: '--keine--', Adapter: '', Battery: ''}]
290
+ },
291
+ 'native': {}
292
+ });
293
+ await this.setObjectNotExistsAsync(`${adptName}.lowBatteryList`, {
294
+ 'type': 'state',
295
+ 'common': {
296
+ 'name': 'List devices with low battery state',
297
+ 'type': 'array',
298
+ 'role': 'json',
299
+ 'read': true,
300
+ 'write': false,
301
+ 'def': [{Device: '--keine--', Adapter: '', Battery: ''}]
302
+ },
303
+ 'native': {}
304
+ });
305
+ await this.setObjectNotExistsAsync(`${adptName}.lowBatteryCount`, {
306
+ 'type': 'state',
307
+ 'common': {
308
+ 'name': 'Quantity devices with low battery',
309
+ 'type': 'number',
310
+ 'role': 'value',
311
+ 'read': true,
312
+ 'write': false,
313
+ 'def': 0
314
+ },
315
+ 'native': {}
316
+ });
317
+ await this.setObjectNotExistsAsync(`${adptName}.batteryCount`, {
318
+ 'type': 'state',
319
+ 'common': {
320
+ 'name': 'Quantity devices with battery',
321
+ 'type': 'number',
322
+ 'role': 'value',
323
+ 'read': true,
324
+ 'write': false,
325
+ 'def': 0
326
+ },
327
+ 'native': {}
328
+ });
329
+ }
107
330
 
108
- const sendJarvis = async (text) => {
109
- await this.setForeignStateAsync('jarvis.0.addNotification', text);
331
+ async main() {
332
+ this.log.debug(`Function started: ${this.main.name}`);
333
+
334
+ this.supAdapter = {
335
+ alexa2: this.config.alexa2Devices,
336
+ esphome: this.config.esphomeDevices,
337
+ zigbee: this.config.zigbeeDevices,
338
+ ble: this.config.bleDevices,
339
+ sonoff: this.config.sonoffDevices,
340
+ shelly: this.config.shellyDevices,
341
+ homematic: this.config.homematicDevices,
342
+ deconz: this.config.deconzDevices,
343
+ zwave: this.config.zwaveDevices,
344
+ dect: this.config.dectDevices,
345
+ hue: this.config.hueDevices,
346
+ hueExt: this.config.hueExtDevices,
347
+ nukiExt: this.config.nukiExtDevices,
348
+ ping: this.config.pingDevices,
349
+ switchbotBle: this.config.switchbotBleDevices,
350
+ sonos: this.config.sonosDevices,
351
+ mihome: this.config.mihomeDevices,
352
+ mihomeGW: this.config.mihomeDevices,
353
+ test: false, // Only for Developer
354
+ test2: false, // Only for Developer
355
+ test3: false // Only for Developer
110
356
  };
111
357
 
112
- this.log.debug('Function started: ' + this.main.name);
113
-
114
- let arrOfflineDevices = []; //JSON-Info of all offline-devices
115
- let jsonLinkQualityDevices = []; //JSON-Info of all devices with linkquality
116
- let arrBatteryPowered = []; //JSON-Info of all devices with battery
117
- let arrBatteryLowPowered = [];
118
- let arrListAllDevices = []; //JSON-Info total list with info of all devices
119
- let offlineDevicesCount = 0;
120
- let deviceCounter = 0;
121
- let batteryPoweredCount = 0;
122
- let lowBatteryPoweredCount = 0;
123
- let lastContactString;
124
- const testMe = true;
125
-
126
- if (!this.config.zigbeeDevices && !this.config.bleDevices && !this.config.sonoffDevices && !this.config.shellyDevices && !this.config.homematicDevices && !this.config.deconzDevices && !this.config.zwaveDevices) {
127
- this.log.warn('No devices selected. Pleased check the instance configuration');
358
+ for(const [id] of Object.entries(this.arrApart)) {
359
+ const idAdapter = this.supAdapter[id];
360
+ if (idAdapter) {
361
+ this.arrDev.push(this.arrApart[id]);
362
+ this.adapterSelected.push(await this.capitalize(id));
363
+ /*try {
364
+ await this.createDPsForEachAdapter(id);
365
+ this.log.debug(`Created datapoints for ${await this.capitalize(id)}`);
366
+ } catch (e) {
367
+ this.log.warn(`Error at creating datapoints for each adapter: ${e}`);
368
+ }*/
369
+ }
128
370
  }
129
371
 
130
- const myArrDev = []; //JSON mit Gesamtliste aller Geräte
131
-
132
- if (testMe) { //Only for Developer to test the functions!!
133
- myArrDev.push({'Selektor':'0_userdata.*.UNREACH', 'adapter':'Homematic', 'battery':'.OPERATING_VOLTAGE', 'reach':'.UNREACH'});
134
- myArrDev.push({'Selektor':'0_userdata.*.link_quality', 'adapter':'Zigbee', 'battery':'.battery', 'reach':'.available'});
135
- myArrDev.push({'Selektor':'0_userdata.*.reachable', 'adapter':'Test', 'battery':'.battery'});
136
- myArrDev.push({'Selektor':'0_userdata.*.rssi', 'adapter':'Test', 'battery':'.sensor.battery'});
137
- this.log.warn('Teststates wurden ausgewählt. Lade Daten...');
372
+ //Check if one Adapter is selected.
373
+ if (this.adapterSelected.length >= 1) {
374
+ this.log.info(`Number of selected adapters: ${this.adapterSelected.length}. Loading data from: ${(this.adapterSelected).join(', ')} ...`);
375
+ } else {
376
+ this.log.warn(`No adapter selected. Please check the instance configuration!`);
138
377
  }
139
378
 
140
- if (this.config.bleDevices) {
141
- myArrDev.push({'Selektor':'ble.*.rssi', 'adapter':'Ble', 'battery':'.battery', 'reach':'none', 'isLowBat':'none'});
142
- this.log.info('Ble Devices wurden ausgewählt (Xiaomi Plant Sensor). Lade Daten...');
143
- }
144
- if (this.config.zigbeeDevices) {
145
- myArrDev.push({'Selektor':'zigbee.*.link_quality', 'adapter':'Zigbee', 'battery':'.battery', 'reach':'.available', 'isLowBat':'none'});
146
- this.log.info('Zigbee Devices wurden ausgewählt. Lade Daten...');
147
- }
148
- if (this.config.sonoffDevices) {
149
- myArrDev.push({'Selektor':'sonoff.*.Wifi_RSSI', 'adapter':'Sonoff', 'battery':'.battery', 'reach':'none', 'isLowBat':'none'});
150
- myArrDev.push({'Selektor':'sonoff.*.Wifi_Signal', 'adapter':'Sonoff', 'battery':'.battery', 'reach':'none', 'isLowBat':'none'});
151
- myArrDev.push({'Selektor':'sonoff.*.RSSI', 'adapter':'Sonoff', 'battery':'.battery', 'reach':'none', 'isLowBat':'none'});
152
- this.log.info('Sonoff Devices wurden ausgewählt. Lade Daten...');
153
- }
154
- if (this.config.shellyDevices) {
155
- myArrDev.push({'Selektor':'shelly.*.rssi', 'adapter':'Shelly', 'battery':'.sensor.battery', 'reach':'none', 'isLowBat':'none'});
156
- this.log.info('Shelly Devices wurden ausgewählt. Lade Daten...');
157
- }
158
- if (this.config.homematicDevices) {
159
- myArrDev.push({'Selektor':'hm-rpc.*.RSSI_DEVICE', 'adapter':'Homematic', 'battery':'.OPERATING_VOLTAGE', 'reach':'.UNREACH', 'isLowBat':'none'});
160
- this.log.info('Homematic Devices wurden ausgewählt. Lade Daten...');
161
- }
162
- if (this.config.deconzDevices) {
163
- myArrDev.push({'Selektor':'deconz.*.reachable', 'adapter':'Deconz', 'battery':'.battery', 'reach':'.reachable', 'isLowBat':'none'});
164
- this.log.info('Deconz Devices wurden ausgewählt. Lade Daten...');
165
- }
166
- if (this.config.zwaveDevices) {
167
- myArrDev.push({'Selektor':'zwave.*.ready', 'adapter':'Zwave', 'battery':'.battery.level', 'reach':'.ready', 'isLowBat':'.battery.isLow'});
168
- this.log.info('Zwave Devices wurden ausgewählt. Lade Daten...');
169
- }
170
-
171
- this.log.debug(JSON.stringify(myArrDev));
379
+ this.log.debug(JSON.stringify(this.arrDev));
172
380
 
173
381
  /*=============================================
174
382
  = Start of main loop =
175
383
  =============================================*/
176
- for (let i = 0; i < myArrDev.length; i++) {
177
- const devices = await this.getForeignStatesAsync(myArrDev[i].Selektor);
178
- const deviceAdapterName = myArrDev[i].adapter;
179
-
180
- this.log.debug(JSON.stringify(devices));
181
-
182
- const myBlacklist = this.config.tableBlacklist;
183
- const myBlacklistArr = [];
384
+ for (let i = 0; i < this.arrDev.length; i++) {
385
+ const devices = await this.getForeignStatesAsync(this.arrDev[i].Selektor);
386
+ const deviceAdapterName = await this.capitalize(this.arrDev[i].adapter);
387
+ const myBlacklist = this.config.tableBlacklist;
184
388
 
185
389
  /*---------- Loop for blacklist ----------*/
186
390
  for(const i in myBlacklist){
187
- myBlacklistArr.push(myBlacklist[i].device);
188
- this.log.debug('Found items on the blacklist: ' + myBlacklistArr);
391
+ this.blacklistArr.push(myBlacklist[i].device);
392
+ this.log.debug(`Found items on the blacklist: ${this.blacklistArr}`);
189
393
  }
190
394
 
191
395
  /*---------- Start of second main loop ----------*/
192
396
  for(const [id] of Object.entries(devices)) {
193
- if (!myBlacklistArr.includes(id)) {
397
+ if (!this.blacklistArr.includes(id)) {
194
398
 
195
- const currDeviceString = id.slice(0, (id.lastIndexOf('.') + 1) - 1);
399
+ const currDeviceString = id.slice(0, (id.lastIndexOf('.') + 1) - 1);
400
+ const shortCurrDeviceString = currDeviceString.slice(0, (currDeviceString.lastIndexOf('.') + 1) - 1);
196
401
 
197
402
  //Get device name
198
403
  const deviceObject = await this.getForeignObjectAsync(currDeviceString);
404
+ const shortDeviceObject = await this.getForeignObjectAsync(shortCurrDeviceString);
199
405
  let deviceName;
200
406
 
201
407
  if (deviceObject && typeof deviceObject === 'object') {
202
408
  deviceName = deviceObject.common.name;
203
409
  }
204
410
 
411
+ if (shortDeviceObject && typeof shortDeviceObject === 'object') {
412
+ if (this.arrDev[i].adapter === 'hue extended') {
413
+ deviceName = shortDeviceObject.common.name;
414
+ }
415
+ }
205
416
 
206
- //Get room name (not implement yet)
207
- //const getRoomName = await this.getEnumAsync('rooms');
208
- //let currRoom;
209
- //this.log.warn(JSON.stringify(getRoomName));
210
-
211
- /*for(const [id] of Object.entries(getRoomName.result)) {
212
- currRoom = await capitalize(id.substring(id.lastIndexOf('.') + 1)) ;
213
- this.log.warn(currRoom);
214
- }*/
417
+ //Get ID for Switchbot and ESPHome Devices
418
+ switch (this.arrDev[i].adapter) {
419
+ case 'switchbot ble':
420
+ case 'esphome':
421
+ deviceName = await this.getInitValue(currDeviceString + this.arrDev[i].id);
422
+ break;
423
+ }
215
424
 
216
425
  // 1. Get link quality
217
- const deviceQualityState = await this.getForeignStateAsync(id);
426
+ let deviceQualityState;
218
427
  let linkQuality;
219
428
 
220
- if (deviceQualityState){
429
+ switch (this.arrDev[i].adapter) {
430
+ case 'homematic':
431
+ case 'sonoff':
432
+ deviceQualityState = await this.getForeignStateAsync(currDeviceString + this.arrDev[i].rssiState);
433
+ break;
434
+ default:
435
+ deviceQualityState = await this.getForeignStateAsync(id);
436
+ }
437
+
438
+ if ((deviceQualityState) && (typeof deviceQualityState.val === 'number')){
221
439
  if (this.config.trueState) {
222
440
  linkQuality = deviceQualityState.val;
223
- } else if ((deviceQualityState.val != null) && (typeof deviceQualityState.val === 'number')) {
441
+ } else {
224
442
  if (deviceQualityState.val < 0) {
225
443
  linkQuality = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100) + '%';
226
444
  } else if ((deviceQualityState.val) >= 0) {
227
445
  linkQuality = parseFloat((100/255 * deviceQualityState.val).toFixed(0)) + '%';
228
446
  }
229
447
  }
448
+ this.linkQualityDevices.push(
449
+ {
450
+ Device: deviceName,
451
+ Adapter: deviceAdapterName,
452
+ Link_quality: linkQuality
453
+ }
454
+ );
455
+ } else {
456
+ // no linkQuality available for powered devices
457
+ linkQuality = ' - ';
230
458
  }
231
- jsonLinkQualityDevices.push(
232
- {
233
- Device: deviceName,
234
- Adapter: deviceAdapterName,
235
- Link_quality: linkQuality
236
- }
237
- );
238
459
 
239
- // 1b. Count how many devices are exists
240
- deviceCounter = jsonLinkQualityDevices.length;
460
+ // 1b. Count how many devices with link Quality
461
+ this.linkQualityCount = this.linkQualityDevices.length;
241
462
 
242
463
  // 2. When was the last contact to the device?
243
- if (deviceQualityState) {
464
+ let lastContactString;
465
+
466
+ const deviceMainSelector = await this.getForeignStateAsync(id);
467
+ let deviceState = 'Online';
468
+ if (deviceMainSelector) {
244
469
  try {
245
470
  const time = new Date();
246
- const lastContact = Math.round((time.getTime() - deviceQualityState.ts) / 1000 / 60);
247
- const currDeviceUnreachString = currDeviceString + myArrDev[i].reach;
248
- const deviceUnreachState = await this.getForeignStateAsync(currDeviceUnreachString);
471
+ const lastContact = Math.round((time.getTime() - deviceMainSelector.ts) / 1000 / 60);
472
+ const lastStateChange = Math.round((time.getTime() - deviceMainSelector.lc) / 1000 / 60);
473
+ const deviceUnreachState = await this.getInitValue(currDeviceString + this.arrDev[i].reach);
474
+
475
+
476
+ const getLastContact = async () => {
477
+ lastContactString = this.formatDate(new Date((deviceMainSelector.ts)), 'hh:mm') + ' Uhr';
478
+ if (Math.round(lastContact) > 100) {
479
+ lastContactString = Math.round(lastContact/60) + ' Stunden';
480
+ }
481
+ if (Math.round(lastContact/60) > 48) {
482
+ lastContactString = Math.round(lastContact/60/24) + ' Tagen';
483
+ }
484
+ return lastContactString;
485
+ };
486
+
487
+ const getLastStateChange = async () => {
488
+ lastContactString = this.formatDate(new Date((deviceMainSelector.lc)), 'hh:mm') + ' Uhr';
489
+ if (Math.round(lastStateChange) > 100) {
490
+ lastContactString = Math.round(lastStateChange/60) + ' Stunden';
491
+ }
492
+ if (Math.round(lastStateChange/60) > 48) {
493
+ lastContactString = Math.round(lastStateChange/60/24) + ' Tagen';
494
+ }
495
+ return lastContactString;
496
+ };
249
497
 
250
498
  // 2b. wenn seit X Minuten kein Kontakt mehr besteht, nimm Gerät in Liste auf
251
499
  //Rechne auf Tage um, wenn mehr als 48 Stunden seit letztem Kontakt vergangen sind
252
500
  //lastContactString = Math.round(lastContact) + ' Minuten';
253
- lastContactString = this.formatDate(new Date((deviceQualityState.ts)), 'hh:mm') + ' Uhr';
254
- if (Math.round(lastContact) > 100) {
255
- lastContactString = Math.round(lastContact/60) + ' Stunden';
256
- }
257
- if (Math.round(lastContact/60) > 48) {
258
- lastContactString = Math.round(lastContact/60/24) + ' Tagen';
501
+ switch (this.arrDev[i].adapter) {
502
+ case 'ping':
503
+ //State changed
504
+ if (!deviceUnreachState) {
505
+ await getLastStateChange();
506
+ } else {
507
+ await getLastContact();
508
+ }
509
+ break;
510
+
511
+ default:
512
+ await getLastContact();
513
+ break;
259
514
  }
260
- if (myArrDev[i].reach === 'none') {
261
- if (lastContact > this.config.maxMinutes) {
262
- arrOfflineDevices.push(
263
- {
264
- Device: deviceName,
265
- Adapter: deviceAdapterName,
266
- Last_contact: lastContactString
515
+
516
+ switch (this.arrDev[i].adapter) {
517
+ case 'alexa2':
518
+ if (this.config.alexa2MaxMinutes === -1) {
519
+ if (!deviceUnreachState) {
520
+ deviceState = 'Offline'; //set online state to offline
521
+ this.offlineDevices.push(
522
+ {
523
+ Device: deviceName,
524
+ Adapter: deviceAdapterName,
525
+ Last_contact: lastContactString
526
+ }
527
+ );
267
528
  }
268
- );
269
- }
270
- } else {
271
- if (deviceUnreachState) {
272
- if ((deviceUnreachState.val === true) && (myArrDev[i].adapter === 'Homematic')) {
273
- arrOfflineDevices.push(
529
+ } else if (lastContact > this.config.alexa2MaxMinutes) {
530
+ deviceState = 'Offline'; //set online state to offline
531
+ this.offlineDevices.push(
274
532
  {
275
533
  Device: deviceName,
276
534
  Adapter: deviceAdapterName,
277
535
  Last_contact: lastContactString
278
536
  }
279
537
  );
280
- } else if ((deviceUnreachState.val === false) && (myArrDev[i].adapter != 'Homematic')) {
281
- arrOfflineDevices.push(
538
+ }
539
+ break;
540
+ case 'ble':
541
+ if (this.config.bleMaxMinutes === -1) {
542
+ if (!deviceUnreachState) {
543
+ deviceState = 'Offline'; //set online state to offline
544
+ this.offlineDevices.push(
545
+ {
546
+ Device: deviceName,
547
+ Adapter: deviceAdapterName,
548
+ Last_contact: lastContactString
549
+ }
550
+ );
551
+ }
552
+ } else if (lastContact > this.config.bleMaxMinutes) {
553
+ deviceState = 'Offline'; //set online state to offline
554
+ this.offlineDevices.push(
282
555
  {
283
556
  Device: deviceName,
284
557
  Adapter: deviceAdapterName,
@@ -286,53 +559,434 @@ class DeviceWatcher extends utils.Adapter {
286
559
  }
287
560
  );
288
561
  }
289
- }
562
+ break;
563
+ case 'deconz':
564
+ if (this.config.deconzMaxMinutes === -1) {
565
+ if (!deviceUnreachState) {
566
+ deviceState = 'Offline'; //set online state to offline
567
+ this.offlineDevices.push(
568
+ {
569
+ Device: deviceName,
570
+ Adapter: deviceAdapterName,
571
+ Last_contact: lastContactString
572
+ }
573
+ );
574
+ }
575
+ } else if (lastContact > this.config.deconzMaxMinutes) {
576
+ deviceState = 'Offline'; //set online state to offline
577
+ this.offlineDevices.push(
578
+ {
579
+ Device: deviceName,
580
+ Adapter: deviceAdapterName,
581
+ Last_contact: lastContactString
582
+ }
583
+ );
584
+ }
585
+ break;
586
+ case 'esphome':
587
+ if (this.config.esphomeMaxMinutes === -1) {
588
+ if (!deviceUnreachState) {
589
+ deviceState = 'Offline'; //set online state to offline
590
+ this.offlineDevices.push(
591
+ {
592
+ Device: deviceName,
593
+ Adapter: deviceAdapterName,
594
+ Last_contact: lastContactString
595
+ }
596
+ );
597
+ }
598
+ } else if (lastContact > this.config.esphomeMaxMinutes) {
599
+ deviceState = 'Offline'; //set online state to offline
600
+ this.offlineDevices.push(
601
+ {
602
+ Device: deviceName,
603
+ Adapter: deviceAdapterName,
604
+ Last_contact: lastContactString
605
+ }
606
+ );
607
+ }
608
+ break;
609
+ case 'fritzDect':
610
+ if (this.config.fritzdectMaxMinutes === -1) {
611
+ if (!deviceUnreachState) {
612
+ deviceState = 'Offline'; //set online state to offline
613
+ this.offlineDevices.push(
614
+ {
615
+ Device: deviceName,
616
+ Adapter: deviceAdapterName,
617
+ Last_contact: lastContactString
618
+ }
619
+ );
620
+ }
621
+ } else if (lastContact > this.config.fritzdectMaxMinutes) {
622
+ deviceState = 'Offline'; //set online state to offline
623
+ this.offlineDevices.push(
624
+ {
625
+ Device: deviceName,
626
+ Adapter: deviceAdapterName,
627
+ Last_contact: lastContactString
628
+ }
629
+ );
630
+ }
631
+ break;
632
+ case 'homematic':
633
+ if (this.config.homematicMaxMinutes === -1) {
634
+ if (deviceUnreachState) {
635
+ deviceState = 'Offline'; //set online state to offline
636
+ this.offlineDevices.push(
637
+ {
638
+ Device: deviceName,
639
+ Adapter: deviceAdapterName,
640
+ Last_contact: lastContactString
641
+ }
642
+ );
643
+ }
644
+ } else if (lastContact > this.config.homematicMaxMinutes) {
645
+ deviceState = 'Offline'; //set online state to offline
646
+ this.offlineDevices.push(
647
+ {
648
+ Device: deviceName,
649
+ Adapter: deviceAdapterName,
650
+ Last_contact: lastContactString
651
+ }
652
+ );
653
+ }
654
+ break;
655
+ case 'hue':
656
+ if (this.config.hueMaxMinutes === -1) {
657
+ if (!deviceUnreachState) {
658
+ deviceState = 'Offline'; //set online state to offline
659
+ this.offlineDevices.push(
660
+ {
661
+ Device: deviceName,
662
+ Adapter: deviceAdapterName,
663
+ Last_contact: lastContactString
664
+ }
665
+ );
666
+ }
667
+ } else if (lastContact > this.config.hueMaxMinutes) {
668
+ deviceState = 'Offline'; //set online state to offline
669
+ this.offlineDevices.push(
670
+ {
671
+ Device: deviceName,
672
+ Adapter: deviceAdapterName,
673
+ Last_contact: lastContactString
674
+ }
675
+ );
676
+ }
677
+ break;
678
+ case 'hue extended':
679
+ if (this.config.hueextMaxMinutes === -1) {
680
+ if (!deviceUnreachState) {
681
+ deviceState = 'Offline'; //set online state to offline
682
+ this.offlineDevices.push(
683
+ {
684
+ Device: deviceName,
685
+ Adapter: deviceAdapterName,
686
+ Last_contact: lastContactString
687
+ }
688
+ );
689
+ }
690
+ } else if (lastContact > this.config.hueextMaxMinutes) {
691
+ deviceState = 'Offline'; //set online state to offline
692
+ this.offlineDevices.push(
693
+ {
694
+ Device: deviceName,
695
+ Adapter: deviceAdapterName,
696
+ Last_contact: lastContactString
697
+ }
698
+ );
699
+ }
700
+ break;
701
+ case 'miHome':
702
+ if (this.config.mihomeMaxMinutes === -1) {
703
+ if (!deviceUnreachState) {
704
+ deviceState = 'Offline'; //set online state to offline
705
+ this.offlineDevices.push(
706
+ {
707
+ Device: deviceName,
708
+ Adapter: deviceAdapterName,
709
+ Last_contact: lastContactString
710
+ }
711
+ );
712
+ }
713
+ } else if (lastContact > this.config.mihomeMaxMinutes) {
714
+ deviceState = 'Offline'; //set online state to offline
715
+ this.offlineDevices.push(
716
+ {
717
+ Device: deviceName,
718
+ Adapter: deviceAdapterName,
719
+ Last_contact: lastContactString
720
+ }
721
+ );
722
+ }
723
+ break;
724
+ case 'nuki_extended':
725
+ if (this.config.nukiextendMaxMinutes === -1) {
726
+ if (!deviceUnreachState) {
727
+ deviceState = 'Offline'; //set online state to offline
728
+ this.offlineDevices.push(
729
+ {
730
+ Device: deviceName,
731
+ Adapter: deviceAdapterName,
732
+ Last_contact: lastContactString
733
+ }
734
+ );
735
+ }
736
+ } else if (lastContact > this.config.nukiextendMaxMinutes) {
737
+ deviceState = 'Offline'; //set online state to offline
738
+ this.offlineDevices.push(
739
+ {
740
+ Device: deviceName,
741
+ Adapter: deviceAdapterName,
742
+ Last_contact: lastContactString
743
+ }
744
+ );
745
+ }
746
+ break;
747
+ case 'ping':
748
+ if (this.config.pingMaxMinutes === -1) {
749
+ if (!deviceUnreachState) {
750
+ deviceState = 'Offline'; //set online state to offline
751
+ this.offlineDevices.push(
752
+ {
753
+ Device: deviceName,
754
+ Adapter: deviceAdapterName,
755
+ Last_contact: lastContactString
756
+ }
757
+ );
758
+ }
759
+ } else if ((lastStateChange > this.config.pingMaxMinutes) && (!deviceUnreachState)) {
760
+ deviceState = 'Offline'; //set online state to offline
761
+ this.offlineDevices.push(
762
+ {
763
+ Device: deviceName,
764
+ Adapter: deviceAdapterName,
765
+ Last_contact: lastContactString
766
+ }
767
+ );
768
+ }
769
+ break;
770
+ case 'shelly':
771
+ if (this.config.shellyMaxMinutes === -1) {
772
+ if (!deviceUnreachState) {
773
+ deviceState = 'Offline'; //set online state to offline
774
+ this.offlineDevices.push(
775
+ {
776
+ Device: deviceName,
777
+ Adapter: deviceAdapterName,
778
+ Last_contact: lastContactString
779
+ }
780
+ );
781
+ }
782
+ } else if (lastContact > this.config.shellyMaxMinutes) {
783
+ deviceState = 'Offline'; //set online state to offline
784
+ this.offlineDevices.push(
785
+ {
786
+ Device: deviceName,
787
+ Adapter: deviceAdapterName,
788
+ Last_contact: lastContactString
789
+ }
790
+ );
791
+ }
792
+ break;
793
+ case 'sonoff':
794
+ if (this.config.sonoffMaxMinutes === -1) {
795
+ if (!deviceUnreachState) {
796
+ deviceState = 'Offline'; //set online state to offline
797
+ this.offlineDevices.push(
798
+ {
799
+ Device: deviceName,
800
+ Adapter: deviceAdapterName,
801
+ Last_contact: lastContactString
802
+ }
803
+ );
804
+ }
805
+ } else if (lastContact > this.config.sonoffMaxMinutes) {
806
+ deviceState = 'Offline'; //set online state to offline
807
+ this.offlineDevices.push(
808
+ {
809
+ Device: deviceName,
810
+ Adapter: deviceAdapterName,
811
+ Last_contact: lastContactString
812
+ }
813
+ );
814
+ }
815
+ break;
816
+ case 'sonos':
817
+ if (this.config.sonosMaxMinutes === -1) {
818
+ if (!deviceUnreachState) {
819
+ deviceState = 'Offline'; //set online state to offline
820
+ this.offlineDevices.push(
821
+ {
822
+ Device: deviceName,
823
+ Adapter: deviceAdapterName,
824
+ Last_contact: lastContactString
825
+ }
826
+ );
827
+ }
828
+ } else if (lastContact > this.config.sonosMaxMinutes) {
829
+ deviceState = 'Offline'; //set online state to offline
830
+ this.offlineDevices.push(
831
+ {
832
+ Device: deviceName,
833
+ Adapter: deviceAdapterName,
834
+ Last_contact: lastContactString
835
+ }
836
+ );
837
+ }
838
+ break;
839
+ case 'switchbot ble':
840
+ if (this.config.switchbotMaxMinutes === -1) {
841
+ if (!deviceUnreachState) {
842
+ deviceState = 'Offline'; //set online state to offline
843
+ this.offlineDevices.push(
844
+ {
845
+ Device: deviceName,
846
+ Adapter: deviceAdapterName,
847
+ Last_contact: lastContactString
848
+ }
849
+ );
850
+ }
851
+ } else if (lastContact > this.config.switchbotMaxMinutes) {
852
+ deviceState = 'Offline'; //set online state to offline
853
+ this.offlineDevices.push(
854
+ {
855
+ Device: deviceName,
856
+ Adapter: deviceAdapterName,
857
+ Last_contact: lastContactString
858
+ }
859
+ );
860
+ }
861
+ break;
862
+ case 'zigbee':
863
+ if (this.config.zigbeeMaxMinutes === -1) {
864
+ if (!deviceUnreachState) {
865
+ deviceState = 'Offline'; //set online state to offline
866
+ this.offlineDevices.push(
867
+ {
868
+ Device: deviceName,
869
+ Adapter: deviceAdapterName,
870
+ Last_contact: lastContactString
871
+ }
872
+ );
873
+ }
874
+ } else if (lastContact > this.config.zigbeeMaxMinutes) {
875
+ deviceState = 'Offline'; //set online state to offline
876
+ this.offlineDevices.push(
877
+ {
878
+ Device: deviceName,
879
+ Adapter: deviceAdapterName,
880
+ Last_contact: lastContactString
881
+ }
882
+ );
883
+ }
884
+ break;
885
+ case 'zwave':
886
+ if (this.config.zwaveMaxMinutes === -1) {
887
+ if (!deviceUnreachState) {
888
+ deviceState = 'Offline'; //set online state to offline
889
+ this.offlineDevices.push(
890
+ {
891
+ Device: deviceName,
892
+ Adapter: deviceAdapterName,
893
+ Last_contact: lastContactString
894
+ }
895
+ );
896
+ }
897
+ } else if (lastContact > this.config.zwaveMaxMinutes) {
898
+ deviceState = 'Offline'; //set online state to offline
899
+ this.offlineDevices.push(
900
+ {
901
+ Device: deviceName,
902
+ Adapter: deviceAdapterName,
903
+ Last_contact: lastContactString
904
+ }
905
+ );
906
+ }
907
+ break;
290
908
  }
291
909
  } catch (e) {
292
- this.log.error('(03) Error while getting timestate ' + e);
910
+ this.log.error(`(03) Error while getting timestate ${e}`);
293
911
  }
294
912
  }
295
913
 
296
914
 
915
+
297
916
  // 2c. Count how many devcies are offline
298
- offlineDevicesCount = arrOfflineDevices.length;
917
+ this.offlineDevicesCount = this.offlineDevices.length;
299
918
 
300
919
  // 3. Get battery states
301
- const currDeviceBatteryString = currDeviceString + myArrDev[i].battery;
302
- const deviceBatteryState = await this.getForeignStateAsync(currDeviceBatteryString);
920
+ const deviceBatteryState = await this.getInitValue(currDeviceString + this.arrDev[i].battery);
921
+ const shortDeviceBatteryState = await this.getInitValue(shortCurrDeviceString + this.arrDev[i].battery);
303
922
  let batteryHealth;
304
923
 
305
- if (!deviceBatteryState) {
306
- batteryHealth = ' - ';
307
- } else if ((myArrDev[i].adapter === 'Homematic') && (deviceBatteryState).val === 0) {
924
+ if ((!deviceBatteryState) && (!shortDeviceBatteryState)) {
308
925
  batteryHealth = ' - ';
309
- } else if ((deviceBatteryState) && (myArrDev[i].adapter != 'Homematic')) {
310
- batteryHealth = (deviceBatteryState).val + '%';
311
- arrBatteryPowered.push(
312
- {
313
- Device: deviceName,
314
- Adapter: deviceAdapterName,
315
- Battery: batteryHealth
316
- }
317
- );
318
- } else if ((deviceBatteryState) && (deviceBatteryState).val != 0 && myArrDev[i].adapter === 'Homematic') {
319
- batteryHealth = (deviceBatteryState).val + 'V';
320
- arrBatteryPowered.push(
321
- {
322
- Device: deviceName,
323
- Adapter: deviceAdapterName,
324
- Battery: batteryHealth
325
- }
326
- );
926
+ } else {
927
+
928
+ switch (this.arrDev[i].adapter) {
929
+ case 'homematic':
930
+ if (deviceBatteryState === 0) {
931
+ batteryHealth = ' - ';
932
+ } else {
933
+ batteryHealth = deviceBatteryState + 'V';
934
+ }
935
+
936
+ this.batteryPowered.push(
937
+ {
938
+ Device: deviceName,
939
+ Adapter: deviceAdapterName,
940
+ Battery: batteryHealth
941
+ }
942
+ );
943
+ break;
944
+ case 'hue extended':
945
+ if (shortDeviceBatteryState) {
946
+ batteryHealth = shortDeviceBatteryState + '%';
947
+ this.batteryPowered.push(
948
+ {
949
+ Device: deviceName,
950
+ Adapter: deviceAdapterName,
951
+ Battery: batteryHealth
952
+ }
953
+ );
954
+ }
955
+ break;
956
+ default:
957
+ batteryHealth = (deviceBatteryState) + '%';
958
+ this.batteryPowered.push(
959
+ {
960
+ Device: deviceName,
961
+ Adapter: deviceAdapterName,
962
+ Battery: batteryHealth
963
+ }
964
+ );
965
+ }
327
966
  }
967
+
328
968
  // 3b. Count how many devices are with battery
329
- batteryPoweredCount = arrBatteryPowered.length;
969
+ this.batteryPoweredCount = this.batteryPowered.length;
330
970
 
331
971
  // 3c. Count how many devices are with low battery
332
- if (deviceBatteryState && deviceBatteryState.val) {
333
- const batteryWarningMin = this.config.minWarnBatterie;
334
- if ((deviceBatteryState.val < batteryWarningMin) && (myArrDev[i].adapter != 'Homematic')) {
335
- arrBatteryLowPowered.push(
972
+ const batteryWarningMin = this.config.minWarnBatterie;
973
+ const deviceLowBatState = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat);
974
+ const deviceLowBatStateHM = await this.getInitValue(currDeviceString + this.arrDev[i].isLowBat2);
975
+
976
+
977
+ if (this.arrDev[i].isLowBat === 'none') {
978
+ if (deviceBatteryState && (deviceBatteryState < batteryWarningMin)) {
979
+ this.batteryLowPowered.push(
980
+ {
981
+ Device: deviceName,
982
+ Adapter: deviceAdapterName,
983
+ Battery: batteryHealth
984
+ }
985
+ );
986
+ }
987
+ } else {
988
+ if (deviceLowBatState || deviceLowBatStateHM) {
989
+ this.batteryLowPowered.push(
336
990
  {
337
991
  Device: deviceName,
338
992
  Adapter: deviceAdapterName,
@@ -340,85 +994,202 @@ class DeviceWatcher extends utils.Adapter {
340
994
  }
341
995
  );
342
996
  }
343
-
344
997
  }
998
+
345
999
  // 3d. Count how many devices are with low battery
346
- lowBatteryPoweredCount = arrBatteryLowPowered.length;
1000
+ this.lowBatteryPoweredCount = this.batteryLowPowered.length;
347
1001
 
348
1002
  // 4. Add all devices in the list
349
- arrListAllDevices.push(
350
- {
351
- Device: deviceName,
352
- Adapter: deviceAdapterName,
353
- Battery: batteryHealth,
354
- Last_contact: lastContactString,
355
- Link_quality: linkQuality
1003
+ if (this.config.listOnlyBattery) {
1004
+ if (deviceBatteryState !== null || shortDeviceBatteryState !== null) {
1005
+ this.listAllDevices.push(
1006
+ {
1007
+ Device: deviceName,
1008
+ Adapter: deviceAdapterName,
1009
+ Battery: batteryHealth,
1010
+ Link_quality: linkQuality,
1011
+ Last_contact: lastContactString,
1012
+ Status: deviceState
1013
+ }
1014
+ );
356
1015
  }
357
- );
1016
+ } else if (!this.config.listOnlyBattery) {
1017
+ this.listAllDevices.push(
1018
+ {
1019
+ Device: deviceName,
1020
+ Adapter: deviceAdapterName,
1021
+ Battery: batteryHealth,
1022
+ Link_quality: linkQuality,
1023
+ Last_contact: lastContactString,
1024
+ Status: deviceState
1025
+ }
1026
+ );
1027
+ }
1028
+
1029
+
1030
+ // 4a. Count how many devices are exists
1031
+ this.deviceCounter = this.listAllDevices.length;
358
1032
  }
359
1033
  } //<--End of second loop
360
1034
  } //<---End of main loop
361
1035
 
1036
+ this.log.debug(`Function finished: ${this.main.name}`);
1037
+ } //<--End of main function
1038
+
1039
+ async sendNotifications() {
362
1040
  /*=============================================
363
1041
  = Notifications =
364
1042
  =============================================*/
1043
+ this.log.debug(`Start the function: ${this.sendNotifications.name}`);
1044
+
1045
+ const pushover = {
1046
+ instance: this.config.instancePushover,
1047
+ title: this.config.titlePushover,
1048
+ device: this.config.devicePushover,
1049
+ prio: this.config.prioPushover
1050
+
1051
+ };
1052
+ const telegram = {
1053
+ instance: this.config.instanceTelegram,
1054
+ user: this.config.deviceTelegram,
1055
+ chatId: this.config.chatIdTelegram
1056
+ };
1057
+ const whatsapp = {
1058
+ instance: this.config.instanceWhatsapp,
1059
+ phone: this.config.phoneWhatsapp
1060
+ };
1061
+ const email = {
1062
+ instance: this.config.instanceEmail,
1063
+ subject: this.config.subjectEmail,
1064
+ sendTo: this.config.sendToEmail
1065
+
1066
+ };
1067
+ const jarvis = {
1068
+ instance: this.config.instanceJarvis,
1069
+ title: this.config.titleJarvis
1070
+
1071
+ };
1072
+ const lovelace = {
1073
+ instance: this.config.instanceLovelace,
1074
+ title: this.config.titleLovelace
1075
+
1076
+ };
1077
+
1078
+ const choosedDays = {
1079
+ monday: this.config.checkMonday,
1080
+ tuesday: this.config.checkTuesday,
1081
+ wednesday: this.config.checkWednesday,
1082
+ thursday: this.config.checkThursday,
1083
+ friday: this.config.checkFriday,
1084
+ saturday: this.config.checkSaturday,
1085
+ sunday: this.config.checkSunday,
1086
+ };
1087
+
1088
+ const sendPushover = async (text) => {
1089
+ await this.sendToAsync(pushover.instance, 'send', {
1090
+ message: text,
1091
+ title: pushover.title,
1092
+ device: pushover.device,
1093
+ priority: pushover.prio
1094
+ });
1095
+ };
1096
+
1097
+ const sendTelegram = async (text) => {
1098
+ await this.sendToAsync(telegram.instance, 'send', {
1099
+ text: text,
1100
+ user: telegram.user,
1101
+ chatId: telegram.chatId
1102
+ });
1103
+ };
1104
+
1105
+ const sendWhatsapp = async (text) => {
1106
+ await this.sendToAsync(whatsapp.instance, 'send', {
1107
+ text: text,
1108
+ phone: whatsapp.phone
1109
+ });
1110
+ };
1111
+
1112
+ const sendEmail = async (text) => {
1113
+ await this.sendToAsync(email.instance, 'send', {
1114
+ sendTo: email.sendTo,
1115
+ text: text,
1116
+ subject: email.subject
1117
+ });
1118
+ };
1119
+
1120
+ const sendJarvis = async (text) => {
1121
+ await this.setForeignStateAsync(`${jarvis.instance}.addNotification`, text);
1122
+ };
1123
+
1124
+ const sendLovelace = async (text) => {
1125
+ await this.setForeignStateAsync(`${lovelace.instance}.notifications.add`, text);
1126
+ };
365
1127
 
366
1128
  /*---------- oflline notification ----------*/
367
1129
  if(this.config.checkSendOfflineMsg) {
368
1130
  try {
369
1131
  let msg = '';
370
- const offlineDevicesCountOld = await this.getStateAsync('offlineCount');
371
-
372
- if ((offlineDevicesCountOld != undefined) && (offlineDevicesCountOld != null)) {
373
- if ((offlineDevicesCount != offlineDevicesCountOld.val) && (offlineDevicesCount != 0)) {
374
- if (offlineDevicesCount == 1) {
375
- msg = 'Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n';
376
- } else if (offlineDevicesCount >= 2) {
377
- msg = 'Folgende ' + offlineDevicesCount + ' Geräte sind seit einiger Zeit nicht erreichbar: \n';
1132
+ const offlineDevicesCountOld = await this.getOwnInitValue('offlineCount');
1133
+
1134
+ if ((this.offlineDevicesCount != offlineDevicesCountOld)) {
1135
+ if (this.offlineDevicesCount == 1) { // make singular if it is only one device
1136
+ msg = 'Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n';
1137
+ } else if (this.offlineDevicesCount >= 2) { //make plural if it is more than one device
1138
+ msg = `Folgende ${this.offlineDevicesCount} Geräte sind seit einiger Zeit nicht erreichbar: \n`;
1139
+ }
1140
+
1141
+ for (const id of this.offlineDevices) {
1142
+ msg = `${msg} \n ${id['Device']} (${id['Last_contact']})`;
1143
+ }
1144
+ this.log.info(msg);
1145
+ await this.setStateAsync('lastNotification', msg, true);
1146
+ if (pushover.instance) {
1147
+ try {
1148
+ await sendPushover(msg);
1149
+ } catch (e) {
1150
+ this.log.warn (`Getting error at sending notification ${e}`);
378
1151
  }
379
- for (const id of arrOfflineDevices) {
380
- msg = msg + '\n' + id['Device'] + ' ' + /*id['room'] +*/ ' (' + id['Last_contact'] + ')';
1152
+ }
1153
+ if (telegram.instance) {
1154
+ try {
1155
+ await sendTelegram(msg);
1156
+ } catch (e) {
1157
+ this.log.warn (`Getting error at sending notification ${e}`);
381
1158
  }
382
- this.log.info(msg);
383
- await this.setStateAsync('lastNotification', msg, true);
384
- if (pushover.instance) {
385
- try {
386
- await sendPushover(msg);
387
- } catch (e) {
388
- this.log.warn ('Getting error at sending notification' + (e));
389
- }
1159
+ }
1160
+ if (whatsapp.instance) {
1161
+ try {
1162
+ await sendWhatsapp(msg);
1163
+ } catch (e) {
1164
+ this.log.warn (`Getting error at sending notification ${e}`);
390
1165
  }
391
- if (telegram.instance) {
392
- try {
393
- await sendTelegram(msg);
394
- } catch (e) {
395
- this.log.warn ('Getting error at sending notification' + (e));
396
- }
1166
+ }
1167
+ if (email.instance) {
1168
+ try {
1169
+ await sendEmail(msg);
1170
+ } catch (e) {
1171
+ this.log.warn (`Getting error at sending notification ${e}`);
397
1172
  }
398
- if (email.instance) {
399
- try {
400
- await sendEmail(msg);
401
- } catch (e) {
402
- this.log.warn ('Getting error at sending notification' + (e));
403
- }
1173
+ }
1174
+ if (jarvis.instance) {
1175
+ try {
1176
+ await sendJarvis('{"title":"'+ jarvis.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')","message":" ' + this.offlineDevicesCount + ' Geräte sind nicht erreichbar","display": "drawer"}');
1177
+ } catch (e) {
1178
+ this.log.warn (`Getting error at sending notification ${e}`);
404
1179
  }
405
- if (jarvis.instance) {
406
- try {
407
- await sendJarvis('{"title":"'+ jarvis.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')","message":" ' + offlineDevicesCount + ' Geräte sind nicht erreichbar","display": "drawer"}');
408
- } catch (e) {
409
- this.log.warn ('Getting error at sending notification' + (e));
410
- }
1180
+ }
1181
+ if (lovelace.instance) {
1182
+ try {
1183
+ await sendLovelace('{"message":" ' + this.offlineDevicesCount + ' Geräte sind nicht erreichbar", "title":"'+ lovelace.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')"}');
1184
+ } catch (e) {
1185
+ this.log.warn (`Getting error at sending notification ${e}`);
411
1186
  }
412
-
413
-
414
1187
  }
415
1188
  }
416
-
417
1189
  } catch (e) {
418
- this.log.debug('Getting error at sending offline notification ' + e);
1190
+ this.log.debug(`Getting error at sending offline notification ${e}`);
419
1191
  }
420
-
421
- }
1192
+ }//<--End of offline notification
422
1193
 
423
1194
  /*---------- Low battery Notification ----------*/
424
1195
  const now = new Date();
@@ -444,121 +1215,145 @@ class DeviceWatcher extends utils.Adapter {
444
1215
 
445
1216
  if (this.config.checkSendBatteryMsg) {
446
1217
  try {
447
- //Nur einmal abfragen
448
- const lastBatteryNotifyIndicator = await this.getStateAsync('info.lastBatteryNotification');
449
-
450
- if ((lastBatteryNotifyIndicator != undefined) && (lastBatteryNotifyIndicator != null)) {
451
- if (now.getHours() < 11) {await this.setStateAsync('info.lastBatteryNotification', false, true);}
452
- if ((now.getHours() > 11) && (lastBatteryNotifyIndicator.val == false) && (checkToday != undefined)){
453
- let batteryMinCount = 0;
454
- const batteryWarningMin = this.config.minWarnBatterie;
455
-
456
- let infotext = '';
457
- for (const id of arrBatteryPowered) {
458
- if (id['Battery']) {
459
- const batteryValue = parseFloat(id['Battery'].replace('%', ''));
460
- if ((batteryValue < batteryWarningMin) && (id['Adapter'] != 'Homematic')) {
461
- infotext = infotext + '\n' + id['Device'] + ' ' + /*id['room'] +*/ ' (' + id['Battery'] + ')'.split(', ');
462
- ++batteryMinCount;
463
- }
1218
+ const lastBatteryNotifyIndicator = await this.getOwnInitValue('info.lastBatteryNotification');
1219
+ const batteryWarningMin = this.config.minWarnBatterie;
1220
+
1221
+ if (now.getHours() < 11) {await this.setStateAsync('info.lastBatteryNotification', false, true);} //Nur einmal abfragen
1222
+ if ((now.getHours() > 11) && (!lastBatteryNotifyIndicator) && (checkToday != undefined)){
1223
+ let batteryMinCount = 0;
1224
+ let infotext = '';
1225
+
1226
+ for (const id of this.batteryPowered) {
1227
+ if (id['Battery']) {
1228
+ const batteryValue = parseFloat(id['Battery'].replace('%', ''));
1229
+ if ((batteryValue < batteryWarningMin) && (id['Adapter'] != 'Homematic')) {
1230
+ infotext = infotext + '\n' + id['Device'] + ' ' + ' (' + id['Battery'] + ')'.split(', ');
1231
+ ++batteryMinCount;
464
1232
  }
465
1233
  }
466
- if (batteryMinCount > 0) {
467
- this.log.info('Batteriezustände: ' + infotext);
468
- await this.setStateAsync('lastNotification', infotext, true);
469
- if (jarvis.instance) {
470
- try {
471
- await sendJarvis('{"title":"'+ jarvis.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')","message":" ' + batteryMinCount + ' Geräte mit schwacher Batterie","display": "drawer"}');
472
- } catch (e) {
473
- this.log.warn ('Getting error at sending notification' + (e));
474
- }
1234
+ }
1235
+ if (batteryMinCount > 0) {
1236
+ this.log.info(`Batteriezustände: ${infotext}`);
1237
+ await this.setStateAsync('lastNotification', infotext, true);
1238
+
1239
+ if (pushover.instance) {
1240
+ try {
1241
+ await sendPushover(`Batteriezustände: ${infotext}`);
1242
+ } catch (e) {
1243
+ this.log.warn (`Getting error at sending notification ${e}`);
475
1244
  }
476
- if (pushover.instance) {
477
- try {
478
- await sendPushover('Batteriezustände: ' + infotext);
479
- } catch (e) {
480
- this.log.warn ('Getting error at sending notification' + (e));
481
- }
1245
+ }
1246
+ if (telegram.instance) {
1247
+ try {
1248
+ await sendTelegram(`Batteriezustände: ${infotext}`);
1249
+ } catch (e) {
1250
+ this.log.warn (`Getting error at sending notification ${e}`);
482
1251
  }
483
- if (telegram.instance) {
484
- try {
485
- await sendTelegram('Batteriezuständ: ' + infotext);
486
- } catch (e) {
487
- this.log.warn ('Getting error at sending notification' + (e));
488
- }
1252
+ }
1253
+ if (whatsapp.instance) {
1254
+ try {
1255
+ await sendWhatsapp(`Batteriezustände: ${infotext}`);
1256
+ } catch (e) {
1257
+ this.log.warn (`Getting error at sending notification ${e}`);
1258
+ }
1259
+ }
1260
+ if (email.instance) {
1261
+ try {
1262
+ await sendEmail(`Batteriezustände: ${infotext}`);
1263
+ } catch (e) {
1264
+ this.log.warn (`Getting error at sending notification ${e}`);
1265
+ }
1266
+ }
1267
+ if (jarvis.instance) {
1268
+ try {
1269
+ await sendJarvis('{"title":"'+ jarvis.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')","message":" ' + batteryMinCount + ' Geräte mit schwacher Batterie","display": "drawer"}');
1270
+ } catch (e) {
1271
+ this.log.warn (`Getting error at sending notification ${e}`);
489
1272
  }
490
- await this.setStateAsync('info.lastBatteryNotification', true, true);
491
1273
  }
1274
+ if (lovelace.instance) {
1275
+ try {
1276
+ await sendLovelace('{"message":" ' + batteryMinCount + ' Geräte mit schwacher Batterie", "title":"'+ lovelace.title +' (' + this.formatDate(new Date(), 'DD.MM.YYYY - hh:mm:ss') + ')"}');
1277
+ } catch (e) {
1278
+ this.log.warn (`Getting error at sending notification ${e}`);
1279
+ }
1280
+ }
1281
+
1282
+ await this.setStateAsync('info.lastBatteryNotification', true, true);
492
1283
  }
493
1284
  }
494
1285
  } catch (e) {
495
- this.log.debug('Getting error at batterynotification ' + e);
1286
+ this.log.debug(`Getting error at sending battery notification ${e}`);
496
1287
  }
497
- }
498
-
499
-
500
- /*===== End of Section notifications ======*/
501
-
1288
+ }//<--End of battery notification
1289
+ this.log.debug(`Function finished: ${this.sendNotifications.name}`);
1290
+ }
1291
+ /*===== End of Section notifications ======*/
502
1292
 
1293
+ async writeDatapoints() {
503
1294
  /*=============================================
504
1295
  = Write Datapoints =
505
1296
  =============================================*/
506
- this.log.debug('write the datapoints ' + this.main.name);
1297
+ this.log.debug(`Start the function: ${this.writeDatapoints.name}`);
507
1298
 
508
1299
  try {
509
- await this.setStateAsync('offlineCount', {val: offlineDevicesCount, ack: true});
510
- await this.setStateAsync('countAll', {val: deviceCounter, ack: true});
511
- await this.setStateAsync('batteryCount', {val: batteryPoweredCount, ack: true});
512
- await this.setStateAsync('lowBatteryCount', {val: lowBatteryPoweredCount, ack: true});
1300
+ await this.setStateAsync('offlineCount', {val: this.offlineDevicesCount, ack: true});
1301
+ await this.setStateAsync('countAll', {val: this.deviceCounter, ack: true});
1302
+ await this.setStateAsync('batteryCount', {val: this.batteryPoweredCount, ack: true});
1303
+ await this.setStateAsync('lowBatteryCount', {val: this.lowBatteryPoweredCount, ack: true});
513
1304
 
514
- if (deviceCounter == 0) {
515
- jsonLinkQualityDevices = [{Device: '--keine--', Adapter: '', Link_quality: ''}]; //JSON-Info alle mit LinkQuality
516
- arrListAllDevices = [{Device: '--keine--', Adapter: '', Battery: '', Last_contact: '', Link_quality: ''}]; //JSON-Info Gesamtliste mit Info je Gerät
1305
+ if (this.deviceCounter == 0) {
1306
+ this.listAllDevices = [{Device: '--keine--', Adapter: '', Battery: '', Last_contact: '', Link_quality: ''}]; //JSON-Info Gesamtliste mit Info je Gerät
517
1307
 
518
- await this.setStateAsync('linkQualityList', {val: JSON.stringify(jsonLinkQualityDevices), ack: true});
519
- await this.setStateAsync('listAll', {val: JSON.stringify(arrListAllDevices), ack: true});
1308
+ await this.setStateAsync('listAll', {val: JSON.stringify(this.listAllDevices), ack: true});
520
1309
  } else {
521
- await this.setStateAsync('linkQualityList', {val: JSON.stringify(jsonLinkQualityDevices), ack: true});
522
- await this.setStateAsync('listAll', {val: JSON.stringify(arrListAllDevices), ack: true});
1310
+ await this.setStateAsync('listAll', {val: JSON.stringify(this.listAllDevices), ack: true});
523
1311
  }
524
1312
 
525
- if (offlineDevicesCount == 0) {
526
- arrOfflineDevices = [{Device: '--keine--', Adapter: '', Last_contact: ''}]; //JSON-Info alle offline-Geräte = 0
1313
+ if (this.linkQualityCount == 0) {
1314
+ this.linkQualityDevices = [{Device: '--keine--', Adapter: '', Link_quality: ''}]; //JSON-Info alle mit LinkQuality
527
1315
 
528
- await this.setStateAsync('offlineList', {val: JSON.stringify(arrOfflineDevices), ack: true});
1316
+ await this.setStateAsync('linkQualityList', {val: JSON.stringify(this.linkQualityDevices), ack: true});
529
1317
  } else {
530
- await this.setStateAsync('offlineList', {val: JSON.stringify(arrOfflineDevices), ack: true});
1318
+ await this.setStateAsync('linkQualityList', {val: JSON.stringify(this.linkQualityDevices), ack: true});
531
1319
  }
532
1320
 
533
- if (batteryPoweredCount == 0) {
534
- arrBatteryPowered = [{Device: '--keine--', Adapter: '', Battery: ''}]; //JSON-Info alle batteriebetriebenen Geräte
535
1321
 
536
- await this.setStateAsync('batteryList', {val: JSON.stringify(arrBatteryPowered), ack: true});
1322
+ if (this.offlineDevicesCount == 0) {
1323
+ this.offlineDevices = [{Device: '--keine--', Adapter: '', Last_contact: ''}]; //JSON-Info alle offline-Geräte = 0
1324
+
1325
+ await this.setStateAsync('offlineList', {val: JSON.stringify(this.offlineDevices), ack: true});
537
1326
  } else {
538
- await this.setStateAsync('batteryList', {val: JSON.stringify(arrBatteryPowered), ack: true});
1327
+ await this.setStateAsync('offlineList', {val: JSON.stringify(this.offlineDevices), ack: true});
539
1328
  }
540
1329
 
541
- if (lowBatteryPoweredCount == 0) {
542
- arrBatteryLowPowered = [{Device: '--keine--', Adapter: '', Battery: ''}]; //JSON-Info alle batteriebetriebenen Geräte
1330
+ if (this.batteryPoweredCount == 0) {
1331
+ this.batteryPowered = [{Device: '--keine--', Adapter: '', Battery: ''}]; //JSON-Info alle batteriebetriebenen Geräte
543
1332
 
544
- await this.setStateAsync('lowBatteryList', {val: JSON.stringify(arrBatteryLowPowered), ack: true});
1333
+ await this.setStateAsync('batteryList', {val: JSON.stringify(this.batteryPowered), ack: true});
545
1334
  } else {
546
- await this.setStateAsync('lowBatteryList', {val: JSON.stringify(arrBatteryLowPowered), ack: true});
1335
+ await this.setStateAsync('batteryList', {val: JSON.stringify(this.batteryPowered), ack: true});
1336
+ }
1337
+
1338
+ if (this.lowBatteryPoweredCount == 0) {
1339
+ this.batteryLowPowered = [{Device: '--keine--', Adapter: '', Battery: ''}]; //JSON-Info alle batteriebetriebenen Geräte
1340
+
1341
+ await this.setStateAsync('lowBatteryList', {val: JSON.stringify(this.batteryLowPowered), ack: true});
1342
+ } else {
1343
+ await this.setStateAsync('lowBatteryList', {val: JSON.stringify(this.batteryLowPowered), ack: true});
547
1344
  }
548
1345
 
549
1346
  //Zeitstempel wann die Datenpunkte zuletzt gecheckt wurden
550
1347
  const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
551
1348
  await this.setStateAsync('lastCheck', lastCheck, true);
552
-
553
- this.log.debug('write the datapoints finished ' + this.main.name);
554
1349
  }
555
1350
  catch (e) {
556
- this.log.error('(05) Error while writing the states ' + e);
1351
+ this.log.error(`(05) Error while writing the states ${e}`);
557
1352
  }
558
- /*===== End of writing Datapoints ======*/
559
-
560
- this.log.debug('Function finished: ' + this.main.name);
1353
+ this.log.debug(`Function finished: ${this.writeDatapoints.name}`);
561
1354
  }
1355
+ /*===== End of writing Datapoints ======*/
1356
+
562
1357
 
563
1358
  onUnload(callback) {
564
1359
  try {
@@ -579,4 +1374,4 @@ if (require.main !== module) {
579
1374
  } else {
580
1375
  // otherwise start the instance directly
581
1376
  new DeviceWatcher();
582
- }
1377
+ }