iobroker.device-watcher 2.5.0 → 2.6.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
@@ -26,13 +26,11 @@ class DeviceWatcher extends utils.Adapter {
26
26
 
27
27
  // instances and adapters
28
28
  // raw arrays
29
+ this.listInstanceRaw = new Map();
29
30
  this.adapterUpdatesJsonRaw = [];
30
- this.listInstanceRaw = [];
31
31
  this.listErrorInstanceRaw = [];
32
32
 
33
33
  // user arrays
34
- this.blacklistInstancesLists = [];
35
- this.blacklistInstancesNotify = [];
36
34
  this.listAllInstances = [];
37
35
  this.listDeactivatedInstances = [];
38
36
  this.listAdapterUpdates = [];
@@ -45,25 +43,22 @@ class DeviceWatcher extends utils.Adapter {
45
43
  this.countErrorInstance = 0;
46
44
 
47
45
  // devices
46
+ // raw arrays
47
+ this.listAllDevicesRaw = new Map();
48
+ this.batteryLowPoweredRaw = [];
49
+ this.offlineDevicesRaw = [];
50
+ this.upgradableDevicesRaw = [];
51
+
48
52
  // arrays
49
53
  this.offlineDevices = [];
50
54
  this.linkQualityDevices = [];
51
55
  this.batteryPowered = [];
52
56
  this.batteryLowPowered = [];
53
57
  this.listAllDevices = [];
54
- this.blacklistLists = [];
55
- this.blacklistAdapterLists = [];
56
- this.blacklistNotify = [];
57
58
  this.selAdapter = [];
58
59
  this.adapterSelected = [];
59
60
  this.upgradableList = [];
60
61
 
61
- // raw arrays
62
- this.listAllDevicesRaw = [];
63
- this.batteryLowPoweredRaw = [];
64
- this.offlineDevicesRaw = [];
65
- this.upgradableDevicesRaw = [];
66
-
67
62
  // counts
68
63
  this.offlineDevicesCount = 0;
69
64
  this.deviceCounter = 0;
@@ -72,12 +67,22 @@ class DeviceWatcher extends utils.Adapter {
72
67
  this.lowBatteryPoweredCount = 0;
73
68
  this.upgradableDevicesCount = 0;
74
69
 
70
+ // Blacklist
71
+ // Instances
72
+ this.blacklistInstancesLists = [];
73
+ this.blacklistInstancesNotify = [];
74
+
75
+ // Devices
76
+ this.blacklistLists = [];
77
+ this.blacklistAdapterLists = [];
78
+ this.blacklistNotify = [];
79
+
75
80
  // Interval timer
76
81
  this.refreshDataTimeout = null;
77
82
 
78
83
  this.on('ready', this.onReady.bind(this));
79
84
  this.on('stateChange', this.onStateChange.bind(this));
80
- // this.on('objectChange', this.onObjectChange.bind(this));
85
+ this.on('objectChange', this.onObjectChange.bind(this));
81
86
  this.on('message', this.onMessage.bind(this));
82
87
  this.on('unload', this.onUnload.bind(this));
83
88
  }
@@ -126,6 +131,7 @@ class DeviceWatcher extends utils.Adapter {
126
131
  nukiExt: this.config.nukiExtDevices,
127
132
  nut: this.config.nutDevices,
128
133
  ping: this.config.pingDevices,
134
+ proxmox: this.config.proxmoxDevices,
129
135
  roomba: this.config.roombaDevices,
130
136
  shelly: this.config.shellyDevices,
131
137
  smartgarden: this.config.smartgardenDevices,
@@ -177,6 +183,7 @@ class DeviceWatcher extends utils.Adapter {
177
183
  nukiExt: this.config.nukiextendMaxMinutes,
178
184
  nut: this.config.nutMaxMinutes,
179
185
  ping: this.config.pingMaxMinutes,
186
+ proxmox: this.config.proxmoxMaxMinutes,
180
187
  roomba: this.config.roombaMaxMinutes,
181
188
  shelly: this.config.shellyMaxMinutes,
182
189
  smartgarden: this.config.smartgardenMaxMinutes,
@@ -214,19 +221,23 @@ class DeviceWatcher extends utils.Adapter {
214
221
  }
215
222
 
216
223
  //create Blacklist
217
- try {
218
- await this.createBlacklist();
219
- } catch (error) {
220
- this.errorReporting('[onReady - create blacklist]', error);
221
- }
224
+ await this.createBlacklist();
222
225
 
223
- //create and fill datapoints for each adapter if selected
224
- if (this.createOwnFolder) {
226
+ //create datapoints for each adapter if selected
227
+ for (const [id] of Object.entries(arrApart)) {
225
228
  try {
226
- for (const [id] of Object.entries(arrApart)) {
227
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
229
+ if (!this.createOwnFolder) {
230
+ await this.deleteDPsForEachAdapter(id);
231
+ await this.deleteHtmlListDatapoints(id);
232
+ } else {
233
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
228
234
  await this.createDPsForEachAdapter(id);
229
- if (this.createHtmlList) await this.createHtmlListDatapoints(id);
235
+ // create HTML list datapoints
236
+ if (!this.createHtmlList) {
237
+ await this.deleteHtmlListDatapoints(id);
238
+ } else {
239
+ await this.createHtmlListDatapoints(id);
240
+ }
230
241
  this.log.debug(`Created datapoints for ${this.capitalize(id)}`);
231
242
  }
232
243
  }
@@ -236,13 +247,24 @@ class DeviceWatcher extends utils.Adapter {
236
247
  }
237
248
 
238
249
  // create HTML list datapoints
239
- if (this.createHtmlList) await this.createHtmlListDatapoints();
250
+ if (!this.createHtmlList) {
251
+ await this.deleteHtmlListDatapoints();
252
+ } else {
253
+ await this.createHtmlListDatapoints();
254
+ }
240
255
 
241
- //read data first at start
256
+ // read data first at start
257
+ // devices
242
258
  await this.main();
243
259
 
244
- if (this.config.checkAdapterInstances) {
245
- await this.getInstanceData();
260
+ // instances and adapters
261
+ if (!this.config.checkAdapterInstances) {
262
+ await this.deleteDPsForInstances();
263
+ } else {
264
+ // instances
265
+ await this.createDPsForInstances();
266
+ await this.getAllInstanceData();
267
+ // adapter updates
246
268
  await this.createAdapterUpdateData();
247
269
  }
248
270
 
@@ -250,22 +272,59 @@ class DeviceWatcher extends utils.Adapter {
250
272
  await this.refreshData();
251
273
 
252
274
  // send overview for low battery devices
253
- if (this.config.checkSendBatteryMsgDaily) await this.sendBatteryNotifyShedule();
275
+ if (this.config.checkSendBatteryMsgDaily) this.sendScheduleNotifications('lowBatteryDevices');
254
276
 
255
277
  // send overview of offline devices
256
- if (this.config.checkSendOfflineMsgDaily) await this.sendOfflineNotificationsShedule();
278
+ if (this.config.checkSendOfflineMsgDaily) this.sendScheduleNotifications('offlineDevices');
257
279
 
258
280
  // send overview of upgradeable devices
259
- if (this.config.checkSendUpgradeMsgDaily) await this.sendDeviceUpdateNotificationsShedule();
281
+ if (this.config.checkSendUpgradeMsgDaily) this.sendScheduleNotifications('updateDevices');
282
+
283
+ // send overview of updatable adapters
284
+ if (this.config.checkSendAdapterUpdateMsgDaily) this.sendScheduleNotifications('updateAdapter');
260
285
 
261
286
  // send overview of instances with error
262
- if (this.config.checkSendInstanceFailedDaily) await this.sendInstanceErrorNotificationShedule();
287
+ if (this.config.checkSendInstanceFailedDaily) this.sendScheduleNotifications('errorInstance');
263
288
  } catch (error) {
264
289
  this.errorReporting('[onReady]', error);
265
290
  this.terminate ? this.terminate(15) : process.exit(15);
266
291
  }
267
292
  } // <-- onReady end
268
293
 
294
+ // If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.
295
+ // You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.
296
+ //
297
+ /**
298
+ * Is called if a subscribed object changes
299
+ * @param {string} id
300
+ * @param {ioBroker.Object | null | undefined} obj
301
+ */
302
+ async onObjectChange(id, obj) {
303
+ if (obj) {
304
+ // The object was changed
305
+ //this.log.warn(`object ${id} changed: ${JSON.stringify(obj)}`);
306
+
307
+ //read new instance data and add it to the lists
308
+ await this.getInstanceData(id);
309
+
310
+ //read devices data and renew the lists
311
+ await this.main();
312
+ } else {
313
+ // The object was deleted
314
+ //this.log.warn(`object ${id} deleted`);
315
+
316
+ // delete instance data in map
317
+ this.listInstanceRaw.delete(id);
318
+
319
+ // delete device data in map
320
+ this.listAllDevicesRaw.delete(id);
321
+
322
+ //unsubscribe of Objects and states
323
+ this.unsubscribeForeignObjects(id);
324
+ this.unsubscribeForeignStates(id);
325
+ }
326
+ }
327
+
269
328
  /**
270
329
  * Is called if a subscribed state changes
271
330
  * @param {string} id
@@ -274,193 +333,196 @@ class DeviceWatcher extends utils.Adapter {
274
333
  async onStateChange(id, state) {
275
334
  // Admin JSON for Adapter updates
276
335
  if (id && state) {
277
- this.log.debug(`State changed: ${id} changed ${state.val}`);
336
+ // this.log.debug(`State changed: ${id} changed ${state.val}`);
278
337
  let batteryData;
279
338
  let oldLowBatState;
280
339
  let contactData;
281
340
  let oldStatus;
282
341
  let isLowBatValue;
283
342
  let instanceStatusRaw;
284
- let instanceDeviceConnectionDpTS;
285
- const instanceDeviceConnectionDpTSminTime = 10;
343
+ let oldInstanceHostState;
344
+ let oldInstanceDeviceState;
286
345
 
287
- /*
288
- if (this.config.checkAdapterInstances) {
289
- for (const adapter of this.adapterUpdatesJsonRaw) {
290
- switch (id) {
291
- case adapter.Path:
292
-
293
- this.sendAdapterUpdatesNotification(id, state);
294
- }
346
+ for (const adapter of this.adapterUpdatesJsonRaw) {
347
+ switch (id) {
348
+ case adapter.Path:
349
+ await this.getAdapterUpdateData(id);
350
+ await this.createAdapterUpdateList();
351
+ if (this.config.checkSendAdapterUpdateMsg) {
352
+ await this.sendStateNotifications('updateAdapter', null);
353
+ }
295
354
  }
296
- }*/
355
+ }
297
356
 
298
- for (const instance of this.listInstanceRaw) {
357
+ for (const [instance, instanceData] of this.listInstanceRaw) {
299
358
  switch (id) {
300
- case instance.instanceAlivePath:
301
- if (state.val !== instance.isAlive) {
359
+ case instanceData.instanceAlivePath:
360
+ if (state.val !== instanceData.isAlive) {
302
361
  instanceStatusRaw = await this.setInstanceStatus(
303
- instance.instanceMode,
304
- instance.schedule,
305
- instance.instanceAlivePath,
306
- state.val,
307
- instance.isConnectedHost,
308
- instance.isConnectedDevice,
362
+ instanceData.instanceMode,
363
+ instanceData.schedule,
364
+ instanceData.instanceAlivePath,
365
+ instanceData.connectedHostPath,
366
+ instanceData.connectedDevicePath,
309
367
  );
310
- instance.isAlive = instanceStatusRaw[1];
311
- instance.status = instanceStatusRaw[0];
312
- instance.isHealthy = instanceStatusRaw[2];
368
+ instanceData.isAlive = instanceStatusRaw[1];
369
+ instanceData.status = instanceStatusRaw[0];
370
+ instanceData.isHealthy = instanceStatusRaw[2];
313
371
  }
314
372
  break;
315
- case instance.connectedHostPath:
316
- if (instance.isAlive && state.val !== instance.isConnectedHost) {
317
- instance.isConnectedHost = state.val;
373
+ case instanceData.connectedHostPath:
374
+ oldInstanceHostState = instanceData.isConnectedHost;
375
+ instanceData.isConnectedHost = state.val;
376
+ if (oldInstanceHostState !== instanceData.isConnectedHost) {
318
377
  instanceStatusRaw = await this.setInstanceStatus(
319
- instance.instanceMode,
320
- instance.schedule,
321
- instance.instanceAlivePath,
322
- instance.isAlive,
323
- state.val,
324
- instance.isConnectedDevice,
378
+ instanceData.instanceMode,
379
+ instanceData.schedule,
380
+ instanceData.instanceAlivePath,
381
+ instanceData.connectedHostPath,
382
+ instanceData.connectedDevicePath,
325
383
  );
326
- instance.isAlive = instanceStatusRaw[1];
327
- instance.status = instanceStatusRaw[0];
328
- instance.isHealthy = instanceStatusRaw[2];
329
-
330
- if (this.config.checkSendInstanceFailedMsg && !instance.isHealthy && !this.blacklistNotify.includes(instance.instanceAlivePath)) {
331
- await this.sendInstanceErrorNotification(instance.InstanceName, instance.status);
384
+ instanceData.isAlive = instanceStatusRaw[1];
385
+ instanceData.status = instanceStatusRaw[0];
386
+ instanceData.isHealthy = instanceStatusRaw[2];
387
+
388
+ if (!instanceData.isAlive) continue;
389
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
390
+ if (!instanceData.isHealthy) {
391
+ await this.sendStateNotifications('errorInstance', instance);
392
+ }
332
393
  }
333
394
  }
334
395
  break;
335
- case instance.connectedDevicePath:
336
- if (instance.isAlive && state.val !== instance.isConnectedDevice) {
337
- instance.isConnectedDevice = state.val;
396
+ case instanceData.connectedDevicePath:
397
+ oldInstanceDeviceState = instanceData.isConnectedDevice;
398
+ instanceData.isConnectedDevice = state.val;
399
+ if (oldInstanceDeviceState !== instanceData.isConnectedDevice) {
338
400
  instanceStatusRaw = await this.setInstanceStatus(
339
- instance.instanceMode,
340
- instance.schedule,
341
- instance.instanceAlivePath,
342
- instance.isAlive,
343
- instance.isConnectedHost,
344
- state.val,
401
+ instanceData.instanceMode,
402
+ instanceData.schedule,
403
+ instanceData.instanceAlivePath,
404
+ instanceData.connectedHostPath,
405
+ instanceData.connectedDevicePath,
345
406
  );
346
- instance.isAlive = instanceStatusRaw[1];
347
- instance.status = instanceStatusRaw[0];
348
- instance.isHealthy = instanceStatusRaw[2];
349
-
350
- if (this.config.checkSendInstanceFailedMsg && !instance.isHealthy && !this.blacklistNotify.includes(instance.instanceAlivePath)) {
351
- await this.sendInstanceErrorNotification(instance.InstanceName, instance.status);
407
+ instanceData.isAlive = instanceStatusRaw[1];
408
+ instanceData.status = instanceStatusRaw[0];
409
+ instanceData.isHealthy = instanceStatusRaw[2];
410
+
411
+ if (!instanceData.isAlive) continue;
412
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
413
+ if (!instanceData.isHealthy) {
414
+ await this.sendStateNotifications('errorInstance', instance);
415
+ }
352
416
  }
353
417
  }
354
418
  break;
355
419
  }
356
420
  }
357
421
 
358
- for (const device of this.listAllDevicesRaw) {
422
+ for (const [device, deviceData] of this.listAllDevicesRaw) {
359
423
  // On statechange update available datapoint
360
424
  switch (id) {
361
- case device.instanceDeviceConnectionDP:
362
- if (state.val !== device.instancedeviceConnected) {
363
- device.instancedeviceConnected = state.val;
425
+ case deviceData.instanceDeviceConnectionDP:
426
+ if (state.val !== deviceData.instancedeviceConnected) {
427
+ deviceData.instancedeviceConnected = state.val;
364
428
  }
365
429
  break;
366
430
 
367
- case device.UpdateDP:
368
- if (state.val !== device.Upgradable) {
369
- device.Upgradable = state.val;
431
+ case deviceData.UpdateDP:
432
+ if (state.val !== deviceData.Upgradable) {
433
+ deviceData.Upgradable = state.val;
370
434
  if (state.val) {
371
- if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(device.Path)) {
372
- await this.sendDeviceUpdatesNotification(device.Device, device.Adapter);
435
+ if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(deviceData.Path)) {
436
+ await this.sendStateNotifications('updateDevice', device);
373
437
  }
374
438
  }
375
439
  }
376
440
  break;
377
441
 
378
- case device.SignalStrengthDP:
379
- device.SignalStrength = await this.calculateSignalStrength(state, device.adapterID);
442
+ case deviceData.SignalStrengthDP:
443
+ deviceData.SignalStrength = await this.calculateSignalStrength(state, deviceData.adapterID);
380
444
  break;
381
445
 
382
- case device.batteryDP:
383
- if (device.isBatteryDevice) {
384
- oldLowBatState = device.LowBat;
385
- batteryData = await this.getBatteryData(state.val, oldLowBatState, device.adapterID);
446
+ case deviceData.batteryDP:
447
+ if (deviceData.isBatteryDevice) {
448
+ oldLowBatState = deviceData.LowBat;
449
+ batteryData = await this.getBatteryData(state.val, oldLowBatState, deviceData.adapterID);
386
450
 
387
- device.Battery = batteryData[0];
388
- device.BatteryRaw = batteryData[2];
389
- if (device.LowBatDP !== 'none') {
390
- isLowBatValue = await this.getInitValue(device.LowBatDP);
451
+ deviceData.Battery = batteryData[0];
452
+ deviceData.BatteryRaw = batteryData[2];
453
+ if (deviceData.LowBatDP !== 'none') {
454
+ isLowBatValue = await this.getInitValue(deviceData.LowBatDP);
391
455
  } else {
392
456
  isLowBatValue = undefined;
393
457
  }
394
- device.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, device.faultReport, device.adapterID);
458
+ deviceData.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, deviceData.faultReport, deviceData.adapterID);
395
459
 
396
- if (device.LowBat && oldLowBatState !== device.LowBat) {
397
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(device.Path)) {
398
- await this.sendLowBatNoticiation(device.Device, device.Adapter, device.Battery);
460
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
461
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
462
+ await this.sendStateNotifications('lowBatDevice', device);
399
463
  }
400
464
  }
401
465
  }
402
466
  break;
403
467
 
404
- case device.LowBatDP:
405
- if (device.isBatteryDevice) {
406
- oldLowBatState = device.LowBat;
407
- batteryData = await this.getBatteryData(device.BatteryRaw, state.val, device.adapterID);
408
- device.Battery = batteryData[0];
409
- device.BatteryRaw = batteryData[2];
410
- device.LowBat = await this.setLowbatIndicator(device.BatteryRaw, state.val, device.faultReport, device.adapterID);
411
-
412
- if (device.LowBat && oldLowBatState !== device.LowBat) {
413
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(device.Path)) {
414
- await this.sendLowBatNoticiation(device.Device, device.Adapter, device.Battery);
468
+ case deviceData.LowBatDP:
469
+ if (deviceData.isBatteryDevice) {
470
+ oldLowBatState = deviceData.LowBat;
471
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, state.val, deviceData.adapterID);
472
+ deviceData.Battery = batteryData[0];
473
+ deviceData.BatteryRaw = batteryData[2];
474
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
475
+
476
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
477
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
478
+ await this.sendStateNotifications('lowBatDevice', device);
415
479
  }
416
480
  }
417
481
  }
418
482
  break;
419
483
 
420
- case device.faultReportDP:
421
- if (device.isBatteryDevice) {
422
- oldLowBatState = device.LowBat;
423
- batteryData = await this.getBatteryData(device.BatteryRaw, oldLowBatState, device.adapterID);
484
+ case deviceData.faultReportDP:
485
+ if (deviceData.isBatteryDevice) {
486
+ oldLowBatState = deviceData.LowBat;
487
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, oldLowBatState, deviceData.adapterID);
424
488
 
425
- device.Battery = batteryData[0];
426
- device.BatteryRaw = batteryData[2];
427
- device.LowBat = await this.setLowbatIndicator(device.BatteryRaw, undefined, state.val, device.adapterID);
489
+ deviceData.Battery = batteryData[0];
490
+ deviceData.BatteryRaw = batteryData[2];
491
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, undefined, state.val, deviceData.adapterID);
428
492
 
429
- if (device.LowBat && oldLowBatState !== device.LowBat) {
430
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(device.Path)) {
431
- await this.sendLowBatNoticiation(device.Device, device.Adapter, device.Battery);
493
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
494
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
495
+ await this.sendStateNotifications('lowBatDevice', device);
432
496
  }
433
497
  }
434
498
  }
435
499
  break;
436
500
 
437
- case device.UnreachDP:
438
- oldStatus = device.Status;
439
- device.UnreachState = await this.getInitValue(device.UnreachDP);
501
+ case deviceData.UnreachDP:
502
+ oldStatus = deviceData.Status;
503
+ deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
440
504
  contactData = await this.getOnlineState(
441
- device.timeSelector,
442
- device.adapterID,
443
- device.UnreachDP,
444
- device.SignalStrength,
445
- device.UnreachState,
446
- device.DeviceStateSelectorDP,
447
- device.rssiPeerSelectorDP,
505
+ deviceData.timeSelector,
506
+ deviceData.adapterID,
507
+ deviceData.UnreachDP,
508
+ deviceData.SignalStrength,
509
+ deviceData.UnreachState,
510
+ deviceData.DeviceStateSelectorDP,
511
+ deviceData.rssiPeerSelectorDP,
448
512
  );
449
513
  if (contactData !== undefined) {
450
- device.LastContact = contactData[0];
451
- device.Status = contactData[1];
452
- device.SignalStrength = contactData[2];
514
+ deviceData.LastContact = contactData[0];
515
+ deviceData.Status = contactData[1];
516
+ deviceData.SignalStrength = contactData[2];
453
517
  }
454
- if (device.instanceDeviceConnectionDP !== undefined) {
455
- instanceDeviceConnectionDpTS = await this.getTimestampConnectionDP(device.instanceDeviceConnectionDP);
456
- if (device.instancedeviceConnected !== false && instanceDeviceConnectionDpTS && instanceDeviceConnectionDpTS >= instanceDeviceConnectionDpTSminTime) {
457
- if (this.config.checkSendOfflineMsg && oldStatus !== device.Status && !this.blacklistNotify.includes(device.Path)) {
458
- await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
518
+ if (this.config.checkSendOfflineMsg && oldStatus !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
519
+ if (deviceData.instanceDeviceConnectionDP !== undefined) {
520
+ // check if the generally deviceData connected state is for a while true
521
+ if (await this.getTimestampConnectionDP(deviceData.instanceDeviceConnectionDP, 20000)) {
522
+ await this.sendStateNotifications('onlineStateDevice', device);
459
523
  }
460
- }
461
- } else {
462
- if (this.config.checkSendOfflineMsg && oldStatus !== device.Status && !this.blacklistNotify.includes(device.Path)) {
463
- await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
524
+ } else {
525
+ await this.sendStateNotifications('onlineStateDevice', device);
464
526
  }
465
527
  }
466
528
  break;
@@ -474,26 +536,23 @@ class DeviceWatcher extends utils.Adapter {
474
536
  */
475
537
  onMessage(obj) {
476
538
  const devices = [];
477
- let myCount = 0;
478
- let result;
479
539
  const instances = [];
480
- let myCountInstances = 0;
481
- let resultInstances;
540
+ let countDevices = 0;
541
+ let countInstances = 0;
482
542
 
483
543
  switch (obj.command) {
484
544
  case 'devicesList':
485
545
  if (obj.message) {
486
546
  try {
487
- result = this.listAllDevicesRaw;
488
- for (const element in result) {
489
- const label = `${result[element].Adapter}: ${result[element].Device}`;
490
- const myValueObject = {
491
- deviceName: result[element].Device,
492
- adapter: result[element].Adapter,
493
- path: result[element].Path,
547
+ for (const deviceData of this.listAllDevicesRaw.values()) {
548
+ const label = `${deviceData.Adapter}: ${deviceData.Device}`;
549
+ const valueObjectDevices = {
550
+ deviceName: deviceData.Device,
551
+ adapter: deviceData.Adapter,
552
+ path: deviceData.Path,
494
553
  };
495
- devices[myCount] = { label: label, value: JSON.stringify(myValueObject) };
496
- myCount++;
554
+ devices[countDevices] = { label: label, value: JSON.stringify(valueObjectDevices) };
555
+ countDevices++;
497
556
  }
498
557
  const sortDevices = devices.slice(0);
499
558
  sortDevices.sort(function (a, b) {
@@ -513,16 +572,15 @@ class DeviceWatcher extends utils.Adapter {
513
572
  case 'instancesList':
514
573
  if (obj.message) {
515
574
  try {
516
- resultInstances = this.listInstanceRaw;
517
- for (const element in resultInstances) {
518
- const label = `${resultInstances[element].Adapter}: ${resultInstances[element].InstanceName}`;
519
- const myValueObject = {
520
- adapter: resultInstances[element].Adapter,
521
- instanceName: resultInstances[element].InstanceName,
522
- path: resultInstances[element].instanceAlivePath,
575
+ for (const instanceData of this.listInstanceRaw.values()) {
576
+ const label = `${instanceData.Adapter}: ${instanceData.InstanceName}`;
577
+ const valueObjectInstances = {
578
+ adapter: instanceData.Adapter,
579
+ instanceName: instanceData.InstanceName,
580
+ path: instanceData.instanceAlivePath,
523
581
  };
524
- instances[myCountInstances] = { label: label, value: JSON.stringify(myValueObject) };
525
- myCountInstances++;
582
+ instances[countInstances] = { label: label, value: JSON.stringify(valueObjectInstances) };
583
+ countInstances++;
526
584
  }
527
585
  const sortInstances = instances.slice(0);
528
586
  sortInstances.sort(function (a, b) {
@@ -549,7 +607,11 @@ class DeviceWatcher extends utils.Adapter {
549
607
 
550
608
  // fill counts and lists of all selected adapter
551
609
  try {
552
- await this.createDataOfAllAdapter();
610
+ for (let i = 0; i < this.selAdapter.length; i++) {
611
+ await this.createData(i);
612
+ await this.createLists();
613
+ }
614
+ await this.writeDatapoints(); // fill the datapoints
553
615
  this.log.debug(`Created and filled data for all adapters`);
554
616
  } catch (error) {
555
617
  this.errorReporting('[main - create data of all adapter]', error);
@@ -559,8 +621,13 @@ class DeviceWatcher extends utils.Adapter {
559
621
  if (this.createOwnFolder) {
560
622
  try {
561
623
  for (const [id] of Object.entries(arrApart)) {
562
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
563
- await this.createDataForEachAdapter(id);
624
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
625
+ for (const deviceData of this.listAllDevicesRaw.values()) {
626
+ // list device only if selected adapter matched with device
627
+ if (!deviceData.adapterID.includes(id)) continue;
628
+ await this.createLists(id);
629
+ }
630
+ await this.writeDatapoints(id); // fill the datapoints
564
631
  this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
565
632
  }
566
633
  }
@@ -585,7 +652,7 @@ class DeviceWatcher extends utils.Adapter {
585
652
 
586
653
  if (this.createOwnFolder) {
587
654
  for (const [id] of Object.entries(arrApart)) {
588
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
655
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
589
656
  await this.createLists(id);
590
657
  await this.writeDatapoints(id);
591
658
  this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
@@ -626,7 +693,7 @@ class DeviceWatcher extends utils.Adapter {
626
693
 
627
694
  for (const i in myBlacklist) {
628
695
  try {
629
- const blacklistParse = await this.parseData(myBlacklist[i].devices);
696
+ const blacklistParse = this.parseData(myBlacklist[i].devices);
630
697
  // push devices in list to ignor device in lists
631
698
  if (myBlacklist[i].checkIgnorLists) {
632
699
  this.blacklistLists.push(blacklistParse.path);
@@ -645,14 +712,14 @@ class DeviceWatcher extends utils.Adapter {
645
712
 
646
713
  if (this.blacklistLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistLists}`);
647
714
  if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistAdapterLists}`);
648
- if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notificatioons: ${this.blacklistNotify}`);
715
+ if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistNotify}`);
649
716
 
650
717
  // INSTANCES
651
718
  const myBlacklistInstances = this.config.tableBlacklistInstances;
652
719
 
653
720
  for (const i in myBlacklistInstances) {
654
721
  try {
655
- const blacklistParse = await this.parseData(myBlacklistInstances[i].instances);
722
+ const blacklistParse = this.parseData(myBlacklistInstances[i].instances);
656
723
  // push devices in list to ignor device in lists
657
724
  if (myBlacklistInstances[i].checkIgnorLists) {
658
725
  this.blacklistInstancesLists.push(blacklistParse.path);
@@ -667,7 +734,7 @@ class DeviceWatcher extends utils.Adapter {
667
734
  }
668
735
 
669
736
  if (this.blacklistInstancesLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistInstancesLists}`);
670
- if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found items on blacklist for notificatioons: ${this.blacklistInstancesNotify}`);
737
+ if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistInstancesNotify}`);
671
738
 
672
739
  this.log.debug(`Function finished: ${this.createBlacklist.name}`);
673
740
  }
@@ -688,6 +755,7 @@ class DeviceWatcher extends utils.Adapter {
688
755
  const instanceDeviceConnectionDP = `${instance}.info.connection`;
689
756
  const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
690
757
  this.subscribeForeignStates(instanceDeviceConnectionDP);
758
+ this.subscribeForeignObjectsAsync(`${this.selAdapter[i].Selektor}`);
691
759
 
692
760
  /*=============================================
693
761
  = Get device name =
@@ -705,6 +773,9 @@ class DeviceWatcher extends utils.Adapter {
705
773
  const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
706
774
  const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
707
775
 
776
+ // subscribe to object device path
777
+ this.subscribeForeignObjectsAsync(currDeviceString);
778
+
708
779
  /*=============================================
709
780
  = Get signal strength =
710
781
  =============================================*/
@@ -831,8 +902,8 @@ class DeviceWatcher extends utils.Adapter {
831
902
  }
832
903
 
833
904
  /*=============================================
834
- = Get update data =
835
- =============================================*/
905
+ = Get update data =
906
+ =============================================*/
836
907
  const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
837
908
  let isUpgradable;
838
909
 
@@ -851,41 +922,8 @@ class DeviceWatcher extends utils.Adapter {
851
922
  /*=============================================
852
923
  = Fill Raw Lists =
853
924
  =============================================*/
854
-
855
- /* Add only devices with battery in the rawlist */
856
- if (this.listOnlyBattery) {
857
- if (isBatteryDevice) {
858
- this.listAllDevicesRaw.push({
859
- Path: id,
860
- instanceDeviceConnectionDP: instanceDeviceConnectionDP,
861
- instancedeviceConnected: instancedeviceConnected,
862
- Device: deviceName,
863
- adapterID: adapterID,
864
- Adapter: adapter,
865
- timeSelector: timeSelector,
866
- isBatteryDevice: isBatteryDevice,
867
- Battery: batteryHealth,
868
- BatteryRaw: batteryHealthRaw,
869
- batteryDP: deviceBatteryStateDP,
870
- LowBat: lowBatIndicator,
871
- LowBatDP: isLowBatDP,
872
- faultReport: faultReportingState,
873
- faultReportDP: faultReportingDP,
874
- SignalStrengthDP: deviceQualityDP,
875
- SignalStrength: linkQuality,
876
- UnreachState: deviceUnreachState,
877
- UnreachDP: unreachDP,
878
- DeviceStateSelectorDP: deviceStateSelectorDP,
879
- rssiPeerSelectorDP: rssiPeerSelectorDP,
880
- LastContact: lastContactString,
881
- Status: deviceState,
882
- UpdateDP: deviceUpdateDP,
883
- Upgradable: isUpgradable,
884
- });
885
- }
886
- } else {
887
- /* Add all devices */
888
- this.listAllDevicesRaw.push({
925
+ const setupList = () => {
926
+ this.listAllDevicesRaw.set(currDeviceString, {
889
927
  Path: id,
890
928
  instanceDeviceConnectionDP: instanceDeviceConnectionDP,
891
929
  instancedeviceConnected: instancedeviceConnected,
@@ -912,6 +950,15 @@ class DeviceWatcher extends utils.Adapter {
912
950
  UpdateDP: deviceUpdateDP,
913
951
  Upgradable: isUpgradable,
914
952
  });
953
+ };
954
+
955
+ if (!this.listOnlyBattery) {
956
+ // Add all devices
957
+ setupList();
958
+ } else {
959
+ // Add only devices with battery in the rawlist
960
+ if (!isBatteryDevice) continue;
961
+ setupList();
915
962
  }
916
963
  } // <-- end of loop
917
964
  } // <-- end of createData
@@ -1187,7 +1234,7 @@ class DeviceWatcher extends utils.Adapter {
1187
1234
  * @param {object} selector - Selector
1188
1235
  */
1189
1236
  async getLastContact(selector) {
1190
- const lastContact = await this.getTimestamp(selector);
1237
+ const lastContact = this.getTimestamp(selector);
1191
1238
  let lastContactString;
1192
1239
 
1193
1240
  lastContactString = this.formatDate(new Date(selector), 'hh:mm') + ' Uhr';
@@ -1220,8 +1267,8 @@ class DeviceWatcher extends utils.Adapter {
1220
1267
  const deviceUnreachSelector = await this.getForeignStateAsync(unreachDP);
1221
1268
  const deviceStateSelector = await this.getForeignStateAsync(deviceStateSelectorDP); // for hmrpc devices
1222
1269
  const rssiPeerSelector = await this.getForeignStateAsync(rssiPeerSelectorDP);
1223
- const lastContact = await this.getTimestamp(deviceTimeSelector.ts);
1224
- const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? await this.getTimestamp(deviceUnreachSelector.lc) : await this.getTimestamp(timeSelector.ts);
1270
+ const lastContact = this.getTimestamp(deviceTimeSelector.ts);
1271
+ const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? this.getTimestamp(deviceUnreachSelector.lc) : this.getTimestamp(timeSelector.ts);
1225
1272
  // If there is no contact since user sets minutes add device in offline list
1226
1273
  // calculate to days after 48 hours
1227
1274
  switch (unreachDP) {
@@ -1273,6 +1320,16 @@ class DeviceWatcher extends utils.Adapter {
1273
1320
  linkQuality = '0%'; // set linkQuality to nothing
1274
1321
  }
1275
1322
  break;
1323
+ case 'proxmox':
1324
+ if (this.configMaxMinutes[adapterID] <= 0) {
1325
+ if (deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1326
+ deviceState = 'Offline'; //set online state to offline
1327
+ }
1328
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1329
+ deviceState = 'Offline'; //set online state to offline
1330
+ linkQuality = '0%'; // set linkQuality to nothing
1331
+ }
1332
+ break;
1276
1333
  case 'hmiP':
1277
1334
  case 'maxcube':
1278
1335
  if (this.configMaxMinutes[adapterID] <= 0) {
@@ -1374,26 +1431,26 @@ class DeviceWatcher extends utils.Adapter {
1374
1431
  * when was last contact of device
1375
1432
  */
1376
1433
  async checkLastContact() {
1377
- for (const device of this.listAllDevicesRaw) {
1378
- if (device.instancedeviceConnected !== false) {
1379
- const oldContactState = device.Status;
1380
- device.UnreachState = await this.getInitValue(device.UnreachDP);
1434
+ for (const [device, deviceData] of this.listAllDevicesRaw) {
1435
+ if (deviceData.instancedeviceConnected !== false) {
1436
+ const oldContactState = deviceData.Status;
1437
+ deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
1381
1438
  const contactData = await this.getOnlineState(
1382
- device.timeSelector,
1383
- device.adapterID,
1384
- device.UnreachDP,
1385
- device.SignalStrength,
1386
- device.UnreachState,
1387
- device.DeviceStateSelectorDP,
1388
- device.rssiPeerSelectorDP,
1439
+ deviceData.timeSelector,
1440
+ deviceData.adapterID,
1441
+ deviceData.UnreachDP,
1442
+ deviceData.SignalStrength,
1443
+ deviceData.UnreachState,
1444
+ deviceData.DeviceStateSelectorDP,
1445
+ deviceData.rssiPeerSelectorDP,
1389
1446
  );
1390
1447
  if (contactData !== undefined) {
1391
- device.LastContact = contactData[0];
1392
- device.Status = contactData[1];
1393
- device.linkQuality = contactData[2];
1448
+ deviceData.LastContact = contactData[0];
1449
+ deviceData.Status = contactData[1];
1450
+ deviceData.linkQuality = contactData[2];
1394
1451
  }
1395
- if (this.config.checkSendOfflineMsg && oldContactState !== device.Status && !this.blacklistNotify.includes(device.Path)) {
1396
- await this.sendOfflineNotifications(device.Device, device.Adapter, device.Status, device.LastContact);
1452
+ if (this.config.checkSendOfflineMsg && oldContactState !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
1453
+ await this.sendStateNotifications('onlineStateDevice', device);
1397
1454
  }
1398
1455
  }
1399
1456
  }
@@ -1417,47 +1474,45 @@ class DeviceWatcher extends utils.Adapter {
1417
1474
  adptName = '';
1418
1475
  }
1419
1476
 
1420
- for (const device of this.listAllDevicesRaw) {
1477
+ for (const deviceData of this.listAllDevicesRaw.values()) {
1421
1478
  /*---------- fill raw lists ----------*/
1422
1479
  // low bat list
1423
- if (device.LowBat && device.Status !== 'Offline') {
1480
+ if (deviceData.LowBat && deviceData.Status !== 'Offline') {
1424
1481
  this.batteryLowPoweredRaw.push({
1425
- Path: device.Path,
1426
- Device: device.Device,
1427
- Adapter: device.Adapter,
1428
- Battery: device.Battery,
1482
+ Path: deviceData.Path,
1483
+ Device: deviceData.Device,
1484
+ Adapter: deviceData.Adapter,
1485
+ Battery: deviceData.Battery,
1429
1486
  });
1430
1487
  }
1431
1488
  // offline raw list
1432
- if (device.Status === 'Offline') {
1489
+ if (deviceData.Status === 'Offline') {
1433
1490
  this.offlineDevicesRaw.push({
1434
- Path: device.Path,
1435
- Device: device.Device,
1436
- Adapter: device.Adapter,
1437
- LastContact: device.LastContact,
1491
+ Path: deviceData.Path,
1492
+ Device: deviceData.Device,
1493
+ Adapter: deviceData.Adapter,
1494
+ LastContact: deviceData.LastContact,
1438
1495
  });
1439
1496
  }
1440
1497
 
1441
1498
  // upgradable raw list
1442
- if (device.Upgradable) {
1499
+ if (deviceData.Upgradable) {
1443
1500
  this.upgradableDevicesRaw.push({
1444
- Path: device.Path,
1445
- Device: device.Device,
1446
- Adapter: device.Adapter,
1501
+ Path: deviceData.Path,
1502
+ Device: deviceData.Device,
1503
+ Adapter: deviceData.Adapter,
1447
1504
  });
1448
1505
  }
1449
1506
 
1450
- if (adptName === '' && !this.blacklistLists.includes(device.Path)) {
1451
- await this.theLists(device);
1507
+ if (adptName === '' && !this.blacklistLists.includes(deviceData.Path)) {
1508
+ await this.theLists(deviceData);
1452
1509
  }
1453
1510
 
1454
1511
  if (this.config.createOwnFolder && adptName !== '') {
1455
- if (device.adapterID.includes(adptName)) {
1456
- /*---------- fill user lists for each adapter ----------*/
1457
- if (!this.blacklistAdapterLists.includes(device.Path)) {
1458
- await this.theLists(device);
1459
- }
1460
- }
1512
+ if (!deviceData.adapterID.includes(adptName)) continue;
1513
+ /*---------- fill user lists for each adapter ----------*/
1514
+ if (this.blacklistAdapterLists.includes(deviceData.Path)) continue;
1515
+ await this.theLists(deviceData);
1461
1516
  }
1462
1517
  }
1463
1518
  await this.countDevices();
@@ -1547,47 +1602,6 @@ class DeviceWatcher extends utils.Adapter {
1547
1602
  this.upgradableDevicesCount = this.upgradableList.length;
1548
1603
  }
1549
1604
 
1550
- /**
1551
- * @param {string} adptName - Adapter name
1552
- */
1553
- async createDataForEachAdapter(adptName) {
1554
- // create Data for each Adapter in own lists
1555
- this.log.debug(`Function started: ${this.createDataForEachAdapter.name}`);
1556
-
1557
- try {
1558
- for (const device of this.listAllDevicesRaw) {
1559
- if (device.adapterID.includes(adptName)) {
1560
- // list device only if selected adapter matched with device
1561
- await this.createLists(adptName);
1562
- }
1563
- }
1564
- await this.writeDatapoints(adptName); // fill the datapoints
1565
- } catch (error) {
1566
- this.errorReporting('[createDataForEachAdapter]', error);
1567
- }
1568
-
1569
- this.log.debug(`Function finished: ${this.createDataForEachAdapter.name}`);
1570
- } // <-- end of createDataForEachAdapter
1571
-
1572
- /**
1573
- * create Data of all selected adapter in one list
1574
- */
1575
- async createDataOfAllAdapter() {
1576
- this.log.debug(`Function started: ${this.createDataOfAllAdapter.name}`);
1577
-
1578
- try {
1579
- for (let i = 0; i < this.selAdapter.length; i++) {
1580
- await this.createData(i);
1581
- await this.createLists();
1582
- }
1583
- await this.writeDatapoints(); // fill the datapoints
1584
- } catch (error) {
1585
- this.errorReporting('[createDataOfAllAdapter]', error);
1586
- }
1587
-
1588
- this.log.debug(`Function finished: ${this.createDataOfAllAdapter.name}`);
1589
- } // <-- end of createDataOfAllAdapter
1590
-
1591
1605
  /**
1592
1606
  * @param {string} [adptName] - Adaptername
1593
1607
  */
@@ -1714,19 +1728,19 @@ class DeviceWatcher extends utils.Adapter {
1714
1728
  //write HTML list
1715
1729
  if (this.createHtmlList) {
1716
1730
  await this.setStateAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1717
- val: await this.creatLinkQualityListHTML(this.linkQualityDevices, this.linkQualityCount),
1731
+ val: await this.createListHTML('linkQualityList', this.linkQualityDevices, this.linkQualityCount, null),
1718
1732
  ack: true,
1719
1733
  });
1720
1734
  await this.setStateAsync(`devices.${dpSubFolder}offlineListHTML`, {
1721
- val: await this.createOfflineListHTML(this.offlineDevices, this.offlineDevicesCount),
1735
+ val: await this.createListHTML('offlineList', this.offlineDevices, this.offlineDevicesCount, null),
1722
1736
  ack: true,
1723
1737
  });
1724
1738
  await this.setStateAsync(`devices.${dpSubFolder}batteryListHTML`, {
1725
- val: await this.createBatteryListHTML(this.batteryPowered, this.batteryPoweredCount, false),
1739
+ val: await this.createListHTML('batteryList', this.batteryPowered, this.batteryPoweredCount, false),
1726
1740
  ack: true,
1727
1741
  });
1728
1742
  await this.setStateAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1729
- val: await this.createBatteryListHTML(this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1743
+ val: await this.createListHTML('batteryList', this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1730
1744
  ack: true,
1731
1745
  });
1732
1746
  }
@@ -1741,85 +1755,93 @@ class DeviceWatcher extends utils.Adapter {
1741
1755
  } //<--End of writing Datapoints
1742
1756
 
1743
1757
  /**
1744
- * get Instances
1758
+ * get all Instances at start
1745
1759
  */
1746
- async getInstanceData() {
1760
+ async getAllInstanceData() {
1747
1761
  try {
1748
- await this.createDPsForInstances();
1762
+ const allInstances = `system.adapter.*`;
1763
+ await this.getInstanceData(allInstances);
1764
+ } catch (error) {
1765
+ this.errorReporting('[getInstance]', error);
1766
+ }
1767
+ }
1749
1768
 
1750
- const instanceAliveDP = await this.getForeignStatesAsync(`system.adapter.*.alive`);
1751
- for (const [id] of Object.entries(instanceAliveDP)) {
1752
- if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
1769
+ /**
1770
+ * get instance data
1771
+ *@param {string} instanceObject
1772
+ */
1773
+ async getInstanceData(instanceObject) {
1774
+ const instanceAliveDP = await this.getForeignStatesAsync(`${instanceObject}.alive`);
1753
1775
 
1754
- // get instance name
1755
- const instanceName = await this.getInstanceName(id);
1776
+ for (const [id] of Object.entries(instanceAliveDP)) {
1777
+ if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
1756
1778
 
1757
- // get instance connected to host data
1758
- const instanceConnectedHostDP = `system.adapter.${instanceName}.connected`;
1759
- const instanceConnectedHostVal = await this.getInitValue(instanceConnectedHostDP);
1779
+ // get instance name
1780
+ const instanceName = await this.getInstanceName(id);
1760
1781
 
1761
- // get instance connected to device data
1762
- const instanceConnectedDeviceDP = `${instanceName}.info.connection`;
1763
- let instanceConnectedDeviceVal;
1764
- if (instanceConnectedDeviceDP !== undefined && typeof instanceConnectedDeviceDP === 'boolean') {
1765
- instanceConnectedDeviceVal = await this.getInitValue(instanceConnectedDeviceDP);
1766
- } else {
1767
- instanceConnectedDeviceVal = 'N/A';
1768
- }
1782
+ // get instance connected to host data
1783
+ const instanceConnectedHostDP = `system.adapter.${instanceName}.connected`;
1784
+ const instanceConnectedHostVal = await this.getInitValue(instanceConnectedHostDP);
1769
1785
 
1770
- // get adapter version
1771
- const instanceObjectPath = `system.adapter.${instanceName}`;
1772
- let adapterName;
1773
- let adapterVersion;
1774
- let instanceMode;
1775
- let scheduleTime = 'N/A';
1776
- const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
1777
- if (instanceObjectData) {
1778
- // @ts-ignore
1779
- adapterName = this.capitalize(instanceObjectData.common.name);
1780
- adapterVersion = instanceObjectData.common.version;
1781
- instanceMode = instanceObjectData.common.mode;
1782
-
1783
- if (instanceMode === 'schedule') {
1784
- scheduleTime = instanceObjectData.common.schedule;
1785
- }
1786
- }
1786
+ // get instance connected to device data
1787
+ const instanceConnectedDeviceDP = `${instanceName}.info.connection`;
1788
+ let instanceConnectedDeviceVal;
1789
+ if (instanceConnectedDeviceDP !== undefined && typeof instanceConnectedDeviceDP === 'boolean') {
1790
+ instanceConnectedDeviceVal = await this.getInitValue(instanceConnectedDeviceDP);
1791
+ } else {
1792
+ instanceConnectedDeviceVal = 'N/A';
1793
+ }
1787
1794
 
1788
- //const adapterVersionVal = await this.getInitValue(adapterVersionDP);
1789
- const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceAliveDP[id].val, instanceConnectedHostVal, instanceConnectedDeviceVal);
1790
- const isAlive = instanceStatusRaw[1];
1791
- const instanceStatus = instanceStatusRaw[0];
1792
- const isHealthy = instanceStatusRaw[2];
1793
-
1794
- //subscribe to statechanges
1795
- this.subscribeForeignStatesAsync(id);
1796
- this.subscribeForeignStatesAsync(instanceConnectedHostDP);
1797
- this.subscribeForeignStatesAsync(instanceConnectedDeviceDP);
1798
- //this.subscribeForeignObjectsAsync(instanceObjectPath);
1799
-
1800
- // create raw list
1801
- this.listInstanceRaw.push({
1802
- Adapter: adapterName,
1803
- InstanceName: instanceName,
1804
- instanceObjectPath: instanceObjectPath,
1805
- instanceAlivePath: id,
1806
- instanceMode: instanceMode,
1807
- schedule: scheduleTime,
1808
- adapterVersion: adapterVersion,
1809
- isAlive: isAlive,
1810
- isHealthy: isHealthy,
1811
- connectedHostPath: instanceConnectedHostDP,
1812
- isConnectedHost: instanceConnectedHostVal,
1813
- connectedDevicePath: instanceConnectedDeviceDP,
1814
- isConnectedDevice: instanceConnectedDeviceVal,
1815
- status: instanceStatus,
1816
- });
1795
+ // get adapter version
1796
+ const instanceObjectPath = `system.adapter.${instanceName}`;
1797
+ let adapterName;
1798
+ let adapterVersion;
1799
+ let instanceMode;
1800
+ let scheduleTime = 'N/A';
1801
+ const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
1802
+ if (instanceObjectData) {
1803
+ // @ts-ignore
1804
+ adapterName = this.capitalize(instanceObjectData.common.name);
1805
+ adapterVersion = instanceObjectData.common.version;
1806
+ instanceMode = instanceObjectData.common.mode;
1807
+
1808
+ if (instanceMode === 'schedule') {
1809
+ scheduleTime = instanceObjectData.common.schedule;
1810
+ }
1817
1811
  }
1818
- await this.createInstanceList();
1819
- await this.writeInstanceDPs();
1820
- } catch (error) {
1821
- this.errorReporting('[getInstance]', error);
1812
+
1813
+ //const adapterVersionVal = await this.getInitValue(adapterVersionDP);
1814
+ const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceConnectedHostDP, instanceConnectedDeviceDP);
1815
+ const isAlive = instanceStatusRaw[1];
1816
+ const instanceStatus = instanceStatusRaw[0];
1817
+ const isHealthy = instanceStatusRaw[2];
1818
+
1819
+ //subscribe to statechanges
1820
+ this.subscribeForeignStatesAsync(id);
1821
+ this.subscribeForeignStatesAsync(instanceConnectedHostDP);
1822
+ this.subscribeForeignStatesAsync(instanceConnectedDeviceDP);
1823
+ this.subscribeForeignObjectsAsync(instanceObjectPath);
1824
+
1825
+ // create raw list
1826
+ this.listInstanceRaw.set(instanceObjectPath, {
1827
+ Adapter: adapterName,
1828
+ InstanceName: instanceName,
1829
+ instanceObjectPath: instanceObjectPath,
1830
+ instanceAlivePath: id,
1831
+ instanceMode: instanceMode,
1832
+ schedule: scheduleTime,
1833
+ adapterVersion: adapterVersion,
1834
+ isAlive: isAlive,
1835
+ isHealthy: isHealthy,
1836
+ connectedHostPath: instanceConnectedHostDP,
1837
+ isConnectedHost: instanceConnectedHostVal,
1838
+ connectedDevicePath: instanceConnectedDeviceDP,
1839
+ isConnectedDevice: instanceConnectedDeviceVal,
1840
+ status: instanceStatus,
1841
+ });
1822
1842
  }
1843
+ await this.createInstanceList();
1844
+ await this.writeInstanceDPs();
1823
1845
  }
1824
1846
 
1825
1847
  /**
@@ -1835,28 +1857,29 @@ class DeviceWatcher extends utils.Adapter {
1835
1857
 
1836
1858
  /**
1837
1859
  * set status for instance
1838
- * @param {object} instanceMode
1839
- * @param {object} scheduleTime
1860
+ * @param {string} instanceMode
1861
+ * @param {string} scheduleTime
1840
1862
  * @param {object} instanceAlivePath
1841
- * @param {object} isAliveVal
1842
- * @param {object} connectedHostVal
1843
- * @param {object} connectedDeviceVal
1863
+ * @param {string} hostConnectedPath
1864
+ * @param {string} isDeviceConnctedPath
1844
1865
  */
1845
- async setInstanceStatus(instanceMode, scheduleTime, instanceAlivePath, isAliveVal, connectedHostVal, connectedDeviceVal) {
1846
- let instanceStatusString = 'not enabled';
1866
+ async setInstanceStatus(instanceMode, scheduleTime, instanceAlivePath, hostConnectedPath, isDeviceConnctedPath) {
1867
+ const isAliveSchedule = await this.getForeignStateAsync(instanceAlivePath);
1868
+ let isHostConnected = await this.getInitValue(hostConnectedPath);
1869
+ let isAlive = await this.getInitValue(instanceAlivePath);
1870
+ let isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
1871
+ let instanceStatusString = 'Instance deactivated';
1847
1872
  let lastUpdate;
1848
1873
  let lastCronRun;
1849
1874
  let diff;
1850
1875
  let previousCronRun = null;
1851
- let isAlive = false;
1852
1876
  let isHealthy = false;
1853
- let dpValue;
1877
+
1854
1878
  switch (instanceMode) {
1855
1879
  case 'schedule':
1856
- dpValue = await this.getForeignStateAsync(instanceAlivePath);
1857
- if (dpValue) {
1858
- lastUpdate = Math.round((Date.now() - dpValue.lc) / 1000); // Last state change in seconds
1859
- previousCronRun = await this.getPreviousCronRun(scheduleTime); // When was the last cron run
1880
+ if (isAliveSchedule) {
1881
+ lastUpdate = Math.round((Date.now() - isAliveSchedule.lc) / 1000); // Last state change in seconds
1882
+ previousCronRun = this.getPreviousCronRun(scheduleTime); // When was the last cron run
1860
1883
  if (previousCronRun) {
1861
1884
  lastCronRun = Math.round(previousCronRun / 1000); // change distance to last run in seconds
1862
1885
  diff = lastCronRun - lastUpdate;
@@ -1864,42 +1887,43 @@ class DeviceWatcher extends utils.Adapter {
1864
1887
  // if 5 minutes difference exceeded, instance is not alive
1865
1888
  isAlive = true;
1866
1889
  isHealthy = true;
1867
- instanceStatusString = 'Instance okay';
1890
+ instanceStatusString = 'Instanz okay';
1868
1891
  }
1869
1892
  }
1870
1893
  }
1871
1894
  break;
1872
1895
  case 'daemon':
1873
- if (!isAliveVal) return ['Instance deactivated', false, null]; // if instance is turned off
1874
-
1896
+ if (!isAlive) return ['Instanz deaktiviert', false, null]; // if instance is turned off
1897
+ if (isDeviceConnected === undefined) isDeviceConnected = true;
1875
1898
  // In case of (re)start, connection may take some time. We take 3 attempts.
1876
1899
  // Attempt 1/3 - immediately
1877
- if (connectedHostVal && connectedDeviceVal) {
1878
- isAlive = true;
1900
+ if (isHostConnected && isDeviceConnected) {
1879
1901
  isHealthy = true;
1880
- instanceStatusString = 'Instance okay';
1902
+ instanceStatusString = 'Instanz okay';
1881
1903
  } else {
1882
1904
  // Attempt 2/3 - after 10 seconds
1883
1905
  await this.wait(10000);
1884
- if (connectedHostVal && connectedDeviceVal) {
1885
- isAlive = true;
1906
+ isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
1907
+ isHostConnected = await this.getInitValue(hostConnectedPath);
1908
+
1909
+ if (isHostConnected && isDeviceConnected) {
1886
1910
  isHealthy = true;
1887
- instanceStatusString = 'Instance okay';
1911
+ instanceStatusString = 'Instanz okay';
1888
1912
  } else {
1889
1913
  // Attempt 3/3 - after 20 seconds in total
1890
1914
  await this.wait(10000);
1891
- if (connectedHostVal && connectedDeviceVal) {
1892
- isAlive = true;
1915
+ isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
1916
+ isHostConnected = await this.getInitValue(hostConnectedPath);
1917
+
1918
+ if (isHostConnected && isDeviceConnected) {
1893
1919
  isHealthy = true;
1894
- instanceStatusString = 'Instance okay';
1920
+ instanceStatusString = 'Instanz okay';
1895
1921
  } else {
1896
- if (!connectedDeviceVal) {
1897
- instanceStatusString = 'not connected to Device';
1898
- isAlive = true;
1922
+ if (!isDeviceConnected) {
1923
+ instanceStatusString = 'Nicht verbunden mit Gerät oder Dienst';
1899
1924
  isHealthy = false;
1900
- } else if (!connectedHostVal) {
1901
- instanceStatusString = 'not connected to host';
1902
- isAlive = true;
1925
+ } else if (!isHostConnected) {
1926
+ instanceStatusString = 'Nicht verbunden mit Host';
1903
1927
  isHealthy = false;
1904
1928
  }
1905
1929
  }
@@ -1911,27 +1935,45 @@ class DeviceWatcher extends utils.Adapter {
1911
1935
  return [instanceStatusString, isAlive, isHealthy];
1912
1936
  }
1913
1937
 
1938
+ /**
1939
+ * create adapter update data
1940
+ */
1914
1941
  async createAdapterUpdateData() {
1915
1942
  const adapterUpdateListDP = `admin.*.info.updatesJson`;
1916
- const adapterUpdatesListVal = await this.getForeignStatesAsync(adapterUpdateListDP);
1917
1943
 
1918
1944
  // subscribe to datapoint
1919
1945
  this.subscribeForeignStates(adapterUpdateListDP);
1946
+
1947
+ await this.getAdapterUpdateData(adapterUpdateListDP);
1948
+
1949
+ await this.createAdapterUpdateList();
1950
+ }
1951
+
1952
+ /**
1953
+ * create adapter update raw lists
1954
+ * @param {string} adapterUpdateListDP
1955
+ */
1956
+ async getAdapterUpdateData(adapterUpdateListDP) {
1957
+ this.adapterUpdatesJsonRaw = [];
1958
+ const adapterUpdatesListVal = await this.getForeignStatesAsync(adapterUpdateListDP);
1959
+
1920
1960
  let adapterJsonList;
1961
+ let adapterUpdatesJsonPath;
1921
1962
 
1922
1963
  for (const [id] of Object.entries(adapterUpdatesListVal)) {
1923
- adapterJsonList = await this.parseData(adapterUpdatesListVal[id].val);
1964
+ adapterJsonList = this.parseData(adapterUpdatesListVal[id].val);
1965
+ adapterUpdatesJsonPath = id;
1924
1966
  }
1925
1967
 
1926
1968
  for (const [id] of Object.entries(adapterJsonList)) {
1927
1969
  this.adapterUpdatesJsonRaw.push({
1928
- Path: adapterUpdateListDP,
1970
+ Path: adapterUpdatesJsonPath,
1929
1971
  Adapter: this.capitalize(id),
1930
1972
  newVersion: adapterJsonList[id].availableVersion,
1931
1973
  oldVersion: adapterJsonList[id].installedVersion,
1932
1974
  });
1933
1975
  }
1934
- await this.createAdapterUpdateList();
1976
+ return this.adapterUpdatesJsonRaw;
1935
1977
  }
1936
1978
 
1937
1979
  /**
@@ -1975,7 +2017,7 @@ class DeviceWatcher extends utils.Adapter {
1975
2017
  this.listErrorInstanceRaw = [];
1976
2018
  this.listErrorInstance = [];
1977
2019
 
1978
- for (const instance of this.listInstanceRaw) {
2020
+ for (const instance of this.listInstanceRaw.values()) {
1979
2021
  // fill raw list
1980
2022
  if (instance.isAlive && !instance.isHealthy) {
1981
2023
  this.listErrorInstanceRaw.push({
@@ -2268,6 +2310,21 @@ class DeviceWatcher extends utils.Adapter {
2268
2310
  });
2269
2311
  }
2270
2312
 
2313
+ /**
2314
+ * delete Datapoints for Instances
2315
+ */
2316
+ async deleteDPsForInstances() {
2317
+ await this.delObjectAsync(`adapterAndInstances`);
2318
+ await this.delObjectAsync(`adapterAndInstances.listAllInstances`);
2319
+ await this.delObjectAsync(`adapterAndInstances.countAllInstances`);
2320
+ await this.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
2321
+ await this.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
2322
+ await this.delObjectAsync(`adapterAndInstances.listInstancesError`);
2323
+ await this.delObjectAsync(`adapterAndInstances.countInstancesError`);
2324
+ await this.delObjectAsync(`adapterAndInstances.listAdapterUpdates`);
2325
+ await this.delObjectAsync(`adapterAndInstances.countAdapterUpdates`);
2326
+ }
2327
+
2271
2328
  /*=============================================
2272
2329
  = functions to send notifications =
2273
2330
  =============================================*/
@@ -2418,539 +2475,379 @@ class DeviceWatcher extends utils.Adapter {
2418
2475
  }
2419
2476
  } // <-- End of sendNotification function
2420
2477
 
2421
- /*---------- Battery notifications ----------*/
2478
+ /*---------- Notifications ----------*/
2422
2479
  /**
2423
- * send shedule message for low battery devices
2480
+ * Notifications on state changes
2481
+ * @param {string} type
2482
+ * @param {object} id
2424
2483
  */
2425
- async sendBatteryNotifyShedule() {
2426
- const time = this.config.checkSendBatteryTime.split(':');
2427
-
2428
- const checkDays = []; // list of selected days
2429
-
2430
- // push the selected days in list
2431
- if (this.config.checkMonday) checkDays.push(1);
2432
- if (this.config.checkTuesday) checkDays.push(2);
2433
- if (this.config.checkWednesday) checkDays.push(3);
2434
- if (this.config.checkThursday) checkDays.push(4);
2435
- if (this.config.checkFriday) checkDays.push(5);
2436
- if (this.config.checkSaturday) checkDays.push(6);
2437
- if (this.config.checkSunday) checkDays.push(0);
2438
-
2439
- if (checkDays.length >= 1) {
2440
- // check if an day is selected
2441
- this.log.debug(`Number of selected days for daily battery message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2442
- } else {
2443
- this.log.warn(`No days selected for daily battery message. Please check the instance configuration!`);
2444
- return; // cancel function if no day is selected
2445
- }
2446
-
2447
- if (!isUnloaded) {
2448
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2449
- schedule.scheduleJob(cron, () => {
2450
- try {
2451
- let deviceList = '';
2452
-
2453
- for (const id of this.batteryLowPoweredRaw) {
2454
- if (!this.blacklistNotify.includes(id.Path)) {
2455
- if (!this.config.showAdapterNameinMsg) {
2456
- deviceList = `${deviceList}\n${id.Device} (${id.Battery})`;
2457
- } else {
2458
- // Add adaptername if checkbox is checked true in options by user
2459
- deviceList = `${deviceList}\n${id.Adapter}: ${id.Device} (${id.Battery})`;
2460
- }
2484
+ async sendStateNotifications(type, id) {
2485
+ if (isUnloaded) return;
2486
+ let objectData;
2487
+ let list = '';
2488
+ let message = '';
2489
+ const setMessage = async (message) => {
2490
+ this.log.info(`${message}`);
2491
+ await this.setStateAsync('lastNotification', `${message}`, true);
2492
+ await this.sendNotification(`${message}`);
2493
+ return (message = '');
2494
+ };
2495
+ switch (type) {
2496
+ case 'lowBatDevice':
2497
+ objectData = this.listAllDevicesRaw.get(id);
2498
+ if (!this.config.showAdapterNameinMsg) {
2499
+ message = `Gerät mit geringer Batterie erkannt: \n${objectData.Device} (${objectData.Battery})`;
2500
+ } else {
2501
+ message = `Gerät mit geringer Batterie erkannt: \n${objectData.Adapter}: ${objectData.Device} (${objectData.Battery})`;
2502
+ }
2503
+ setMessage(message);
2504
+ break;
2505
+ case 'onlineStateDevice':
2506
+ objectData = this.listAllDevicesRaw.get(id);
2507
+ switch (objectData.Status) {
2508
+ case 'Online':
2509
+ if (!this.config.showAdapterNameinMsg) {
2510
+ message = `Folgendes Gerät ist wieder erreichbar: \n${objectData.Device} (${objectData.LastContact})`;
2511
+ } else {
2512
+ message = `Folgendes Gerät ist wieder erreichbar: \n${objectData.Adapter}: ${objectData.Device} (${objectData.LastContact})`;
2461
2513
  }
2462
- }
2463
- if (deviceList.length > 0) {
2464
- this.log.info(`Niedrige Batteriezustände: ${deviceList}`);
2465
- this.setStateAsync('lastNotification', `Niedrige Batteriezustände: ${deviceList}`, true);
2466
-
2467
- this.sendNotification(`Niedrige Batteriezustände: ${deviceList}`);
2468
- }
2469
- } catch (error) {
2470
- this.errorReporting('[sendBatteryNotifyShedule]', error);
2514
+ break;
2515
+ case 'Offline':
2516
+ if (!this.config.showAdapterNameinMsg) {
2517
+ message = `Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n${objectData.Device} (${objectData.LastContact})`;
2518
+ } else {
2519
+ message = `Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n${objectData.Adapter}: ${objectData.Device} (${objectData.LastContact})`;
2520
+ }
2521
+ break;
2471
2522
  }
2472
- });
2473
- }
2474
- } //<--End of battery notification
2475
-
2476
- /**
2477
- * check if device updates are available and send notification
2478
- * @param {string} deviceName
2479
- * @param {string} adapter
2480
- * @param {string} battery
2481
- **/
2482
- async sendLowBatNoticiation(deviceName, adapter, battery) {
2483
- this.log.debug(`Start the function: ${this.sendLowBatNoticiation.name}`);
2484
-
2485
- try {
2486
- let msg = '';
2487
- let deviceList = '';
2488
-
2489
- if (!this.config.showAdapterNameinMsg) {
2490
- deviceList = `${deviceList}\n${deviceName} (${battery})`;
2491
- } else {
2492
- deviceList = `${deviceList}\n${adapter}: ${deviceName} (${battery})`;
2493
- }
2494
- msg = `Gerät mit geringer Batterie erkannt: \n`;
2523
+ setMessage(message);
2524
+ break;
2525
+ case 'updateDevice':
2526
+ objectData = this.listAllDevicesRaw.get(id);
2527
+ if (!this.config.showAdapterNameinMsg) {
2528
+ message = `Neue Geräte Updates vorhanden: \n${objectData.Device}`;
2529
+ } else {
2530
+ message = `Neue Geräte Updates vorhanden: \n${objectData.Adapter}: ${objectData.Device}`;
2531
+ }
2532
+ setMessage(message);
2533
+ break;
2534
+ case 'updateAdapter':
2535
+ objectData = this.listAdapterUpdates;
2536
+ list = '';
2495
2537
 
2496
- this.log.info(msg + deviceList);
2497
- await this.setStateAsync('lastNotification', msg + deviceList, true);
2498
- await this.sendNotification(msg + deviceList);
2499
- } catch (error) {
2500
- this.errorReporting('[sendLowBatNoticiation]', error);
2538
+ for (const id of objectData) {
2539
+ list = `${list}\n${id.Adapter}: v${id['Available Version']}`;
2540
+ }
2541
+ if (list.length === 0) return;
2542
+ message = `Neue Adapter Updates vorhanden: ${list}`;
2543
+ setMessage(message);
2544
+ break;
2545
+ case 'errorInstance':
2546
+ objectData = this.listInstanceRaw.get(id);
2547
+ message = `Instanz Watchdog:\n${objectData.InstanceName}: ${objectData.status}`;
2548
+ setMessage(message);
2549
+ break;
2501
2550
  }
2502
- this.log.debug(`Finished the function: ${this.sendLowBatNoticiation.name}`);
2503
2551
  }
2504
2552
 
2505
- /*---------- Offline/Online notifications ----------*/
2506
- /**
2507
- * send message if an device is offline
2508
- * @param {string} deviceName
2509
- * @param {string} adapter
2510
- * @param {string} status
2511
- * @param {string} lastContact
2512
- */
2513
- async sendOfflineNotifications(deviceName, adapter, status, lastContact) {
2514
- this.log.debug(`Start the function: ${this.sendOfflineNotifications.name}`);
2515
-
2516
- try {
2517
- let msg = '';
2518
- let deviceList = '';
2519
-
2520
- if (!this.config.showAdapterNameinMsg) {
2521
- deviceList = `${deviceList}\n${deviceName} (${lastContact})`;
2522
- } else {
2523
- deviceList = `${deviceList}\n${adapter}: ${deviceName} (${lastContact})`;
2524
- }
2525
-
2526
- if (status === 'Online') {
2527
- // make singular if it is only one device
2528
- msg = 'Folgendes Gerät ist wieder erreichbar: \n';
2529
- } else if (status === 'Offline') {
2530
- //make plural if it is more than one device
2531
- msg = `Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n`;
2532
- }
2533
-
2534
- this.log.info(msg + deviceList);
2535
- await this.setStateAsync('lastNotification', msg + deviceList, true);
2536
- await this.sendNotification(msg + deviceList);
2537
- } catch (error) {
2538
- this.errorReporting('[sendOfflineMessage]', error);
2539
- }
2540
- this.log.debug(`Finished the function: ${this.sendOfflineNotifications.name}`);
2541
- } //<--End of offline notification
2542
-
2543
2553
  /**
2544
- * send shedule message with offline devices
2554
+ * Notifications per user defined schedule
2555
+ * @param {string} type
2545
2556
  */
2546
- async sendOfflineNotificationsShedule() {
2547
- const time = this.config.checkSendOfflineTime.split(':');
2548
-
2549
- const checkDays = []; // list of selected days
2550
-
2551
- // push the selected days in list
2552
- if (this.config.checkOfflineMonday) checkDays.push(1);
2553
- if (this.config.checkOfflineTuesday) checkDays.push(2);
2554
- if (this.config.checkOfflineWednesday) checkDays.push(3);
2555
- if (this.config.checkOfflineThursday) checkDays.push(4);
2556
- if (this.config.checkOfflineFriday) checkDays.push(5);
2557
- if (this.config.checkOfflineSaturday) checkDays.push(6);
2558
- if (this.config.checkOfflineSunday) checkDays.push(0);
2559
-
2560
- if (checkDays.length >= 1) {
2561
- // check if an day is selected
2562
- this.log.debug(`Number of selected days for daily offline message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2563
- } else {
2564
- this.log.warn(`No days selected for daily offline message. Please check the instance configuration!`);
2565
- return; // cancel function if no day is selected
2566
- }
2567
-
2568
- if (!isUnloaded) {
2569
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2570
- schedule.scheduleJob(cron, () => {
2571
- try {
2572
- let deviceList = '';
2557
+ sendScheduleNotifications(type) {
2558
+ if (isUnloaded) return;
2559
+
2560
+ let time;
2561
+ let cron;
2562
+ let list = '';
2563
+ let message = '';
2564
+ const checkDays = [];
2565
+ const setMessage = async (message) => {
2566
+ this.log.info(`${message}`);
2567
+ await this.setStateAsync('lastNotification', `${message}`, true);
2568
+ await this.sendNotification(`${message}`);
2569
+ return (message = '');
2570
+ };
2571
+
2572
+ switch (type) {
2573
+ case 'lowBatteryDevices':
2574
+ // push the selected days in list
2575
+ if (this.config.checkMonday) checkDays.push(1);
2576
+ if (this.config.checkTuesday) checkDays.push(2);
2577
+ if (this.config.checkWednesday) checkDays.push(3);
2578
+ if (this.config.checkThursday) checkDays.push(4);
2579
+ if (this.config.checkFriday) checkDays.push(5);
2580
+ if (this.config.checkSaturday) checkDays.push(6);
2581
+ if (this.config.checkSunday) checkDays.push(0);
2582
+
2583
+ time = this.config.checkSendBatteryTime.split(':');
2584
+
2585
+ if (checkDays.length === 0) {
2586
+ this.log.warn(`No days selected for daily low battery devices message. Please check the instance configuration!`);
2587
+ return; // cancel function if no day is selected
2588
+ }
2589
+ this.log.debug(`Number of selected days for daily low battery devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2573
2590
 
2574
- for (const id of this.offlineDevicesRaw) {
2575
- if (!this.blacklistNotify.includes(id.Path)) {
2576
- if (!this.config.showAdapterNameinMsg) {
2577
- deviceList = `${deviceList}\n${id.Device} (${id.LastContact})`;
2578
- } else {
2579
- deviceList = `${deviceList}\n${id.Adapter}: ${id.Device} (${id.LastContact})`;
2580
- }
2591
+ cron = '1 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2592
+ schedule.scheduleJob(cron, () => {
2593
+ list = '';
2594
+ for (const id of this.batteryLowPoweredRaw) {
2595
+ if (this.blacklistNotify.includes(id.Path)) continue;
2596
+ if (!this.config.showAdapterNameinMsg) {
2597
+ list = `${list}\n${id.Device} (${id.Battery})`;
2598
+ } else {
2599
+ // Add adaptername if checkbox is checked true in options by user
2600
+ list = `${list}\n${id.Adapter}: ${id.Device} (${id.Battery})`;
2581
2601
  }
2582
2602
  }
2583
-
2584
- if (deviceList.length > 0) {
2585
- this.log.info(`Geräte Offline: ${deviceList}`);
2586
- this.setStateAsync('lastNotification', `Geräte Offline: ${deviceList}`, true);
2587
-
2588
- this.sendNotification(`Geräte Offline: ${deviceList}`);
2589
- }
2590
- } catch (error) {
2591
- this.errorReporting('[sendOfflineNotificationsShedule]', error);
2603
+ if (list.length === 0) return;
2604
+ message = `Tägliche Meldung über Geräte mit niedrigen Batteriezuständen: ${list}`;
2605
+ setMessage(message);
2606
+ });
2607
+ break;
2608
+ case 'offlineDevices':
2609
+ // push the selected days in list
2610
+ if (this.config.checkOfflineMonday) checkDays.push(1);
2611
+ if (this.config.checkOfflineTuesday) checkDays.push(2);
2612
+ if (this.config.checkOfflineWednesday) checkDays.push(3);
2613
+ if (this.config.checkOfflineThursday) checkDays.push(4);
2614
+ if (this.config.checkOfflineFriday) checkDays.push(5);
2615
+ if (this.config.checkOfflineSaturday) checkDays.push(6);
2616
+ if (this.config.checkOfflineSunday) checkDays.push(0);
2617
+
2618
+ time = this.config.checkSendOfflineTime.split(':');
2619
+
2620
+ if (checkDays.length === 0) {
2621
+ this.log.warn(`No days selected for daily offline devices message. Please check the instance configuration!`);
2622
+ return; // cancel function if no day is selected
2592
2623
  }
2593
- });
2594
- }
2595
- } //<--End of daily offline notification
2596
-
2597
- /*---------- Device Updates notifications ----------*/
2598
- /**
2599
- * check if device updates are available and send notification
2600
- * @param {string} deviceName
2601
- * @param {string} adapter
2602
- **/
2603
- async sendDeviceUpdatesNotification(deviceName, adapter) {
2604
- this.log.debug(`Start the function: ${this.sendDeviceUpdatesNotification.name}`);
2624
+ this.log.debug(`Number of selected days for daily offline devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2605
2625
 
2606
- try {
2607
- let msg = '';
2608
- let deviceList = '';
2626
+ cron = '2 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2627
+ schedule.scheduleJob(cron, () => {
2628
+ list = '';
2609
2629
 
2610
- if (!this.config.showAdapterNameinMsg) {
2611
- deviceList = `${deviceList}\n${deviceName}`;
2612
- } else {
2613
- deviceList = `${deviceList}\n${adapter}: ${deviceName}`;
2614
- }
2615
-
2616
- msg = `Neue Geräte Updates vorhanden: \n`;
2617
-
2618
- this.log.info(msg + deviceList);
2619
- await this.setStateAsync('lastNotification', msg + deviceList, true);
2620
- await this.sendNotification(msg + deviceList);
2621
- } catch (error) {
2622
- this.errorReporting('[sendDeviceUpdatesNotification]', error);
2623
- }
2624
- this.log.debug(`Finished the function: ${this.sendDeviceUpdatesNotification.name}`);
2625
- }
2626
-
2627
- /**
2628
- * send shedule message with offline devices
2629
- */
2630
- async sendDeviceUpdateNotificationsShedule() {
2631
- const time = this.config.checkSendUpgradeTime.split(':');
2632
-
2633
- const checkDays = []; // list of selected days
2634
-
2635
- // push the selected days in list
2636
- if (this.config.checkUpgradeMonday) checkDays.push(1);
2637
- if (this.config.checkUpgradeTuesday) checkDays.push(2);
2638
- if (this.config.checkUpgradeWednesday) checkDays.push(3);
2639
- if (this.config.checkUpgradeThursday) checkDays.push(4);
2640
- if (this.config.checkUpgradeFriday) checkDays.push(5);
2641
- if (this.config.checkUpgradeSaturday) checkDays.push(6);
2642
- if (this.config.checkUpgradeSunday) checkDays.push(0);
2643
-
2644
- if (checkDays.length >= 1) {
2645
- // check if an day is selected
2646
- this.log.debug(`Number of selected days for daily Upgrade message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2647
- } else {
2648
- this.log.warn(`No days selected for daily Upgrade message. Please check the instance configuration!`);
2649
- return; // cancel function if no day is selected
2650
- }
2651
-
2652
- if (!isUnloaded) {
2653
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2654
- schedule.scheduleJob(cron, () => {
2655
- try {
2656
- let deviceList = '';
2657
-
2658
- for (const id of this.upgradableDevicesRaw) {
2659
- if (!this.blacklistNotify.includes(id.Path)) {
2660
- if (!this.config.showAdapterNameinMsg) {
2661
- deviceList = `${deviceList}\n${id.Device}`;
2662
- } else {
2663
- deviceList = `${deviceList}\n${id.Adapter}: ${id.Device}`;
2664
- }
2630
+ for (const id of this.offlineDevicesRaw) {
2631
+ if (this.blacklistNotify.includes(id.Path)) continue;
2632
+ if (!this.config.showAdapterNameinMsg) {
2633
+ list = `${list}\n${id.Device} (${id.LastContact})`;
2634
+ } else {
2635
+ list = `${list}\n${id.Adapter}: ${id.Device} (${id.LastContact})`;
2665
2636
  }
2666
2637
  }
2667
- if (deviceList.length > 0) {
2668
- this.log.info(`Geräte Upgrade: ${deviceList}`);
2669
- this.setStateAsync('lastNotification', `Geräte Upgrade: ${deviceList}`, true);
2670
-
2671
- this.sendNotification(`Geräte Upgrade:\n${deviceList}`);
2672
- }
2673
- } catch (error) {
2674
- this.errorReporting('[sendUpgradeNotificationsShedule]', error);
2675
- }
2676
- });
2677
- }
2678
- } //<--End of daily device updates notification
2679
-
2680
- /*---------- Adapter Updates notifications ----------*/
2681
- /**
2682
- * check if adapter updates are available and send notification
2683
- * @param {string} id
2684
- * @param {ioBroker.State | null | undefined} state
2685
- */
2686
- async sendAdapterUpdatesNotification(id, state) {
2687
- this.log.debug(`Start the function: ${this.sendAdapterUpdatesNotification.name}`);
2688
2638
 
2689
- try {
2690
- if (state && state !== undefined) {
2691
- const list = await this.parseData(state.val);
2692
- let msg = '';
2693
- let adapterList = '';
2694
-
2695
- for (const [id] of Object.entries(list)) {
2696
- adapterList = `${adapterList}\n${this.capitalize(id)} - Version: ${list[id].availableVersion}`;
2639
+ if (list.length === 0) return;
2640
+ message = `Tägliche Meldung über offline Geräte: ${list}`;
2641
+ setMessage(message);
2642
+ });
2643
+ break;
2644
+ case 'updateDevices':
2645
+ // push the selected days in list
2646
+ if (this.config.checkUpgradeMonday) checkDays.push(1);
2647
+ if (this.config.checkUpgradeTuesday) checkDays.push(2);
2648
+ if (this.config.checkUpgradeWednesday) checkDays.push(3);
2649
+ if (this.config.checkUpgradeThursday) checkDays.push(4);
2650
+ if (this.config.checkUpgradeFriday) checkDays.push(5);
2651
+ if (this.config.checkUpgradeSaturday) checkDays.push(6);
2652
+ if (this.config.checkUpgradeSunday) checkDays.push(0);
2653
+
2654
+ time = this.config.checkSendUpgradeTime.split(':');
2655
+
2656
+ if (checkDays.length === 0) {
2657
+ this.log.warn(`No days selected for daily updatable devices message. Please check the instance configuration!`);
2658
+ return; // cancel function if no day is selected
2697
2659
  }
2698
- if (adapterList.length !== 0) {
2699
- msg = `Neue Adapter Updates vorhanden: \n`;
2660
+ this.log.debug(`Number of selected days for daily updatable devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2700
2661
 
2701
- this.log.info(msg + adapterList);
2702
- await this.setStateAsync('lastNotification', msg + adapterList, true);
2703
- await this.sendNotification(msg + adapterList);
2704
- }
2705
- }
2706
- } catch (error) {
2707
- this.errorReporting('[sendAdapterUpdatesNotification]', error);
2708
- }
2709
- this.log.debug(`Finished the function: ${this.sendAdapterUpdatesNotification.name}`);
2710
- }
2711
-
2712
- /**
2713
- * send shedule message with list of updatable adapters
2714
- */
2715
- async sendAdapterUpdatesNotificatioShedule() {
2716
- const time = this.config.checkSendAdapterUpdateTime.split(':');
2717
-
2718
- const checkDays = []; // list of selected days
2719
-
2720
- // push the selected days in list
2721
- if (this.config.checkAdapterUpdateMonday) checkDays.push(1);
2722
- if (this.config.checkAdapterUpdateTuesday) checkDays.push(2);
2723
- if (this.config.checkAdapterUpdateWednesday) checkDays.push(3);
2724
- if (this.config.checkAdapterUpdateThursday) checkDays.push(4);
2725
- if (this.config.checkAdapterUpdateFriday) checkDays.push(5);
2726
- if (this.config.checkAdapterUpdateSaturday) checkDays.push(6);
2727
- if (this.config.checkAdapterUpdateSunday) checkDays.push(0);
2728
-
2729
- if (checkDays.length >= 1) {
2730
- // check if an day is selected
2731
- this.log.debug(`Number of selected days for daily adapter update message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2732
- } else {
2733
- this.log.warn(`No days selected for daily adapter update message. Please check the instance configuration!`);
2734
- return; // cancel function if no day is selected
2735
- }
2736
-
2737
- if (!isUnloaded) {
2738
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2739
- schedule.scheduleJob(cron, () => {
2740
- try {
2741
- let deviceList = '';
2662
+ cron = '3 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2663
+ schedule.scheduleJob(cron, () => {
2664
+ list = '';
2742
2665
 
2743
2666
  for (const id of this.upgradableDevicesRaw) {
2744
- if (!this.blacklistNotify.includes(id.Path)) {
2745
- if (!this.config.showAdapterNameinMsg) {
2746
- deviceList = `${deviceList}\n${id.Device}`;
2747
- } else {
2748
- deviceList = `${deviceList}\n${id.Adapter}: ${id.Device}`;
2749
- }
2667
+ if (this.blacklistNotify.includes(id.Path)) continue;
2668
+ if (!this.config.showAdapterNameinMsg) {
2669
+ list = `${list}\n${id.Device}`;
2670
+ } else {
2671
+ list = `${list}\n${id.Adapter}: ${id.Device}`;
2750
2672
  }
2751
2673
  }
2752
- if (deviceList.length > 0) {
2753
- this.log.info(`Geräte Upgrade: ${deviceList}`);
2754
- this.setStateAsync('lastNotification', `Geräte Upgrade: ${deviceList}`, true);
2755
-
2756
- this.sendNotification(`Geräte Upgrade:\n${deviceList}`);
2757
- }
2758
- } catch (error) {
2759
- this.errorReporting('[sendUpgradeNotificationsShedule]', error);
2674
+ if (list.length === 0) return;
2675
+ message = `Tägliche Meldung über verfügbare Geräte Updates: ${list}`;
2676
+ setMessage(message);
2677
+ });
2678
+ break;
2679
+ case 'updateAdapter':
2680
+ // push the selected days in list
2681
+ if (this.config.checkAdapterUpdateMonday) checkDays.push(1);
2682
+ if (this.config.checkAdapterUpdateTuesday) checkDays.push(2);
2683
+ if (this.config.checkAdapterUpdateWednesday) checkDays.push(3);
2684
+ if (this.config.checkAdapterUpdateThursday) checkDays.push(4);
2685
+ if (this.config.checkAdapterUpdateFriday) checkDays.push(5);
2686
+ if (this.config.checkAdapterUpdateSaturday) checkDays.push(6);
2687
+ if (this.config.checkAdapterUpdateSunday) checkDays.push(0);
2688
+
2689
+ time = this.config.checkSendAdapterUpdateTime.split(':');
2690
+
2691
+ if (checkDays.length === 0) {
2692
+ this.log.warn(`No days selected for daily adapter update message. Please check the instance configuration!`);
2693
+ return; // cancel function if no day is selected
2760
2694
  }
2761
- });
2762
- }
2763
- } //<--End of daily offline notification
2764
-
2765
- /*---------- Instance error notifications ----------*/
2766
- /**
2767
- * check if device updates are available and send notification
2768
- * @param {string} instanceName
2769
- * @param {string} error
2770
- **/
2771
- async sendInstanceErrorNotification(instanceName, error) {
2772
- this.log.debug(`Start the function: ${this.sendInstanceErrorNotification.name}`);
2773
-
2774
- try {
2775
- let msg = '';
2776
- let instanceList = '';
2777
-
2778
- instanceList = `${instanceList}\n${instanceName}: ${error}`;
2779
-
2780
- msg = `Fehler einer Instanz entdeckt: \n`;
2781
-
2782
- this.log.info(msg + instanceList);
2783
- await this.setStateAsync('lastNotification', msg + instanceList, true);
2784
- await this.sendNotification(msg + instanceList);
2785
- } catch (error) {
2786
- this.errorReporting('[sendInstanceErrorNotification]', error);
2787
- }
2788
- this.log.debug(`Finished the function: ${this.sendInstanceErrorNotification.name}`);
2789
- }
2790
-
2791
- /**
2792
- * send shedule message with offline devices
2793
- */
2794
- async sendInstanceErrorNotificationShedule() {
2795
- const time = this.config.checkSendInstanceFailedTime.split(':');
2796
-
2797
- const checkDays = []; // list of selected days
2798
-
2799
- // push the selected days in list
2800
- if (this.config.checkFailedInstancesMonday) checkDays.push(1);
2801
- if (this.config.checkFailedInstancesTuesday) checkDays.push(2);
2802
- if (this.config.checkFailedInstancesWednesday) checkDays.push(3);
2803
- if (this.config.checkFailedInstancesThursday) checkDays.push(4);
2804
- if (this.config.checkFailedInstancesFriday) checkDays.push(5);
2805
- if (this.config.checkFailedInstancesSaturday) checkDays.push(6);
2806
- if (this.config.checkFailedInstancesSunday) checkDays.push(0);
2807
-
2808
- if (checkDays.length >= 1) {
2809
- // check if an day is selected
2810
- this.log.debug(`Number of selected days for daily instance error message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2811
- } else {
2812
- this.log.warn(`No days selected for daily instance error message. Please check the instance configuration!`);
2813
- return; // cancel function if no day is selected
2814
- }
2695
+ this.log.debug(`Number of selected days for daily adapter update message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2815
2696
 
2816
- if (!isUnloaded) {
2817
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2818
- schedule.scheduleJob(cron, () => {
2819
- try {
2820
- let instanceList = '';
2697
+ cron = '4 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2698
+ schedule.scheduleJob(cron, () => {
2699
+ list = '';
2821
2700
 
2822
- for (const id of this.listErrorInstanceRaw) {
2823
- if (!this.blacklistInstancesNotify.includes(id.instanceAlivePath)) {
2824
- instanceList = `${instanceList}\n${id.Instance}: ${id.Status}`;
2825
- }
2701
+ for (const id of this.listAdapterUpdates) {
2702
+ list = `${list}\n${id.Adapter}: v${id['Available Version']}`;
2826
2703
  }
2827
- if (instanceList.length > 0) {
2828
- this.log.info(`Instanz Fehler: ${instanceList}`);
2829
- this.setStateAsync('lastNotification', `Instanz Fehler: ${instanceList}`, true);
2704
+ if (list.length === 0) return;
2705
+ message = `Tägliche Meldung über verfügbare Adapter Updates: ${list}`;
2706
+ setMessage(message);
2707
+ });
2708
+ break;
2709
+ case 'errorInstance':
2710
+ // push the selected days in list
2711
+ if (this.config.checkFailedInstancesMonday) checkDays.push(1);
2712
+ if (this.config.checkFailedInstancesTuesday) checkDays.push(2);
2713
+ if (this.config.checkFailedInstancesWednesday) checkDays.push(3);
2714
+ if (this.config.checkFailedInstancesThursday) checkDays.push(4);
2715
+ if (this.config.checkFailedInstancesFriday) checkDays.push(5);
2716
+ if (this.config.checkFailedInstancesSaturday) checkDays.push(6);
2717
+ if (this.config.checkFailedInstancesSunday) checkDays.push(0);
2718
+
2719
+ time = this.config.checkSendInstanceFailedTime.split(':');
2720
+
2721
+ if (checkDays.length === 0) {
2722
+ this.log.warn(`No days selected for daily instance error message. Please check the instance configuration!`);
2723
+ return; // cancel function if no day is selected
2724
+ }
2725
+ this.log.debug(`Number of selected days for daily instance error message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2726
+ cron = '5 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2727
+ schedule.scheduleJob(cron, () => {
2728
+ list = '';
2830
2729
 
2831
- this.sendNotification(`Instanz Fehler:\n${instanceList}`);
2730
+ for (const id of this.listErrorInstanceRaw) {
2731
+ if (this.blacklistInstancesNotify.includes(id.instanceAlivePath)) continue;
2732
+ list = `${list}\n${id.Instance}: ${id.Status}`;
2832
2733
  }
2833
- } catch (error) {
2834
- this.errorReporting('[sendInstanceErrorNotificationShedule]', error);
2835
- }
2836
- });
2734
+ if (list.length === 0) return;
2735
+ message = `Tägliche Meldung über fehlerhafte Instanzen: ${list}`;
2736
+ setMessage(message);
2737
+ });
2738
+ break;
2837
2739
  }
2838
- } //<--End of daily device updates notification
2740
+ }
2839
2741
 
2840
2742
  /*=============================================
2841
2743
  = functions to create html lists =
2842
2744
  =============================================*/
2843
-
2844
2745
  /**
2746
+ * @param {string} type - type of list
2845
2747
  * @param {object} devices - Device
2846
2748
  * @param {number} deviceCount - Counted devices
2749
+ * @param {object} isLowBatteryList - list Low Battery Devices
2847
2750
  */
2848
- async creatLinkQualityListHTML(devices, deviceCount) {
2849
- devices = devices.sort((a, b) => {
2850
- a = a.Device || '';
2851
- b = b.Device || '';
2852
- return a.localeCompare(b);
2853
- });
2854
- let html = `<center>
2855
- <b>Link Quality Devices:<font> ${deviceCount}</b><small></small></font>
2856
- <p></p>
2857
- </center>
2858
- <table width=100%>
2859
- <tr>
2860
- <th align=left>Device</th>
2861
- <th align=center width=120>Adapter</th>
2862
- <th align=right>Link Quality</th>
2863
- </tr>
2864
- <tr>
2865
- <td colspan="5"><hr></td>
2866
- </tr>`;
2867
-
2868
- for (const device of devices) {
2869
- html += `<tr>
2870
- <td><font>${device.Device}</font></td>
2871
- <td align=center><font>${device.Adapter}</font></td>
2872
- <td align=right><font>${device['Signal strength']}</font></td>
2751
+ async createListHTML(type, devices, deviceCount, isLowBatteryList) {
2752
+ let html;
2753
+ switch (type) {
2754
+ case 'linkQualityList':
2755
+ devices = devices.sort((a, b) => {
2756
+ a = a.Device || '';
2757
+ b = b.Device || '';
2758
+ return a.localeCompare(b);
2759
+ });
2760
+ html = `<center>
2761
+ <b>Link Quality Devices:<font> ${deviceCount}</b><small></small></font>
2762
+ <p></p>
2763
+ </center>
2764
+ <table width=100%>
2765
+ <tr>
2766
+ <th align=left>Device</th>
2767
+ <th align=center width=120>Adapter</th>
2768
+ <th align=right>Link Quality</th>
2769
+ </tr>
2770
+ <tr>
2771
+ <td colspan="5"><hr></td>
2873
2772
  </tr>`;
2874
- }
2875
2773
 
2876
- html += '</table>';
2877
- return html;
2878
- }
2774
+ for (const device of devices) {
2775
+ html += `<tr>
2776
+ <td><font>${device.Device}</font></td>
2777
+ <td align=center><font>${device.Adapter}</font></td>
2778
+ <td align=right><font>${device['Signal strength']}</font></td>
2779
+ </tr>`;
2780
+ }
2879
2781
 
2880
- /**
2881
- * @param {object} devices - Device
2882
- * @param {number} deviceCount - Counted devices
2883
- */
2884
- async createOfflineListHTML(devices, deviceCount) {
2885
- devices = devices.sort((a, b) => {
2886
- a = a.Device || '';
2887
- b = b.Device || '';
2888
- return a.localeCompare(b);
2889
- });
2890
- let html = `<center>
2891
- <b>Offline Devices: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
2892
- <p></p>
2893
- </center>
2894
- <table width=100%>
2895
- <tr>
2896
- <th align=left>Device</th>
2897
- <th align=center width=120>Adapter</th>
2898
- <th align=center>Letzter Kontakt</th>
2899
- </tr>
2900
- <tr>
2901
- <td colspan="5"><hr></td>
2902
- </tr>`;
2903
-
2904
- for (const device of devices) {
2905
- html += `<tr>
2906
- <td><font>${device.Device}</font></td>
2907
- <td align=center><font>${device.Adapter}</font></td>
2908
- <td align=center><font color=orange>${device['Last contact']}</font></td>
2782
+ html += '</table>';
2783
+ break;
2784
+
2785
+ case 'offlineList':
2786
+ devices = devices.sort((a, b) => {
2787
+ a = a.Device || '';
2788
+ b = b.Device || '';
2789
+ return a.localeCompare(b);
2790
+ });
2791
+ html = `<center>
2792
+ <b>Offline Devices: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
2793
+ <p></p>
2794
+ </center>
2795
+ <table width=100%>
2796
+ <tr>
2797
+ <th align=left>Device</th>
2798
+ <th align=center width=120>Adapter</th>
2799
+ <th align=center>Letzter Kontakt</th>
2800
+ </tr>
2801
+ <tr>
2802
+ <td colspan="5"><hr></td>
2909
2803
  </tr>`;
2910
- }
2911
2804
 
2912
- html += '</table>';
2913
- return html;
2914
- }
2805
+ for (const device of devices) {
2806
+ html += `<tr>
2807
+ <td><font>${device.Device}</font></td>
2808
+ <td align=center><font>${device.Adapter}</font></td>
2809
+ <td align=center><font color=orange>${device['Last contact']}</font></td>
2810
+ </tr>`;
2811
+ }
2915
2812
 
2916
- /**
2917
- * @param {object} [devices] - Device
2918
- * @param {object} [deviceCount] - Counted devices
2919
- * @param {object} [isLowBatteryList] - list Low Battery Devices
2920
- */
2921
- async createBatteryListHTML(devices, deviceCount, isLowBatteryList) {
2922
- devices = devices.sort((a, b) => {
2923
- a = a.Device || '';
2924
- b = b.Device || '';
2925
- return a.localeCompare(b);
2926
- });
2927
- let html = `<center>
2928
- <b>${isLowBatteryList === true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
2929
- <p></p>
2930
- </center>
2931
- <table width=100%>
2932
- <tr>
2933
- <th align=left>Device</th>
2934
- <th align=center width=120>Adapter</th>
2935
- <th align=${isLowBatteryList ? 'center' : 'right'}>Batterie</th>
2936
- </tr>
2937
- <tr>
2938
- <td colspan="5"><hr></td>
2939
- </tr>`;
2940
- for (const device of devices) {
2941
- html += `<tr>
2942
- <td><font>${device.Device}</font></td>
2943
- <td align=center><font>${device.Adapter}</font></td>`;
2944
-
2945
- if (isLowBatteryList) {
2946
- html += `<td align=center><font color=orange>${device.Battery}</font></td>`;
2947
- } else {
2948
- html += `<td align=right><font color=#3bcf0e>${device.Battery}</font></td>`;
2949
- }
2950
- html += `</tr>`;
2951
- }
2813
+ html += '</table>';
2814
+ break;
2815
+
2816
+ case 'batteryList':
2817
+ devices = devices.sort((a, b) => {
2818
+ a = a.Device || '';
2819
+ b = b.Device || '';
2820
+ return a.localeCompare(b);
2821
+ });
2822
+ html = `<center>
2823
+ <b>${isLowBatteryList === true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
2824
+ <p></p>
2825
+ </center>
2826
+ <table width=100%>
2827
+ <tr>
2828
+ <th align=left>Device</th>
2829
+ <th align=center width=120>Adapter</th>
2830
+ <th align=${isLowBatteryList ? 'center' : 'right'}>Batterie</th>
2831
+ </tr>
2832
+ <tr>
2833
+ <td colspan="5"><hr></td>
2834
+ </tr>`;
2835
+ for (const device of devices) {
2836
+ html += `<tr>
2837
+ <td><font>${device.Device}</font></td>
2838
+ <td align=center><font>${device.Adapter}</font></td>`;
2839
+
2840
+ if (isLowBatteryList) {
2841
+ html += `<td align=center><font color=orange>${device.Battery}</font></td>`;
2842
+ } else {
2843
+ html += `<td align=right><font color=#3bcf0e>${device.Battery}</font></td>`;
2844
+ }
2845
+ html += `</tr>`;
2846
+ }
2952
2847
 
2953
- html += '</table>';
2848
+ html += '</table>';
2849
+ break;
2850
+ }
2954
2851
  return html;
2955
2852
  }
2956
2853
 
@@ -3302,6 +3199,29 @@ class DeviceWatcher extends utils.Adapter {
3302
3199
  }
3303
3200
 
3304
3201
  /**
3202
+ * delete datapoints for each adapter
3203
+ * @param {object} adptName - Adaptername of devices
3204
+ */
3205
+ async deleteDPsForEachAdapter(adptName) {
3206
+ await this.delObjectAsync(`devices.${adptName}`);
3207
+ await this.delObjectAsync(`devices.${adptName}.offlineCount`);
3208
+ await this.delObjectAsync(`devices.${adptName}.offlineList`);
3209
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
3210
+ await this.delObjectAsync(`devices.${adptName}.listAll`);
3211
+ await this.delObjectAsync(`devices.${adptName}.linkQualityList`);
3212
+ await this.delObjectAsync(`devices.${adptName}.countAll`);
3213
+ await this.delObjectAsync(`devices.${adptName}.batteryList`);
3214
+ await this.delObjectAsync(`devices.${adptName}.lowBatteryList`);
3215
+ await this.delObjectAsync(`devices.${adptName}.lowBatteryCount`);
3216
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceLowBat`);
3217
+ await this.delObjectAsync(`devices.${adptName}.batteryCount`);
3218
+ await this.delObjectAsync(`devices.${adptName}.upgradableCount`);
3219
+ await this.delObjectAsync(`devices.${adptName}.upgradableList`);
3220
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceUpdatable`);
3221
+ }
3222
+
3223
+ /**
3224
+ * create HTML list datapoints
3305
3225
  * @param {object} [adptName] - Adaptername of devices
3306
3226
  **/
3307
3227
  async createHtmlListDatapoints(adptName) {
@@ -3406,6 +3326,25 @@ class DeviceWatcher extends utils.Adapter {
3406
3326
  });
3407
3327
  }
3408
3328
 
3329
+ /**
3330
+ * delete html datapoints
3331
+ * @param {object} [adptName] - Adaptername of devices
3332
+ **/
3333
+ async deleteHtmlListDatapoints(adptName) {
3334
+ // delete the datapoints in subfolders with the adaptername otherwise delete the dP's in the root folder
3335
+ let dpSubFolder;
3336
+ if (adptName) {
3337
+ dpSubFolder = `${adptName}.`;
3338
+ } else {
3339
+ dpSubFolder = '';
3340
+ }
3341
+
3342
+ await this.delObjectAsync(`devices.${dpSubFolder}offlineListHTML`);
3343
+ await this.delObjectAsync(`devices.${dpSubFolder}linkQualityListHTML`);
3344
+ await this.delObjectAsync(`devices.${dpSubFolder}batteryListHTML`);
3345
+ await this.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
3346
+ }
3347
+
3409
3348
  /*=============================================
3410
3349
  = help functions =
3411
3350
  =============================================*/
@@ -3421,20 +3360,27 @@ class DeviceWatcher extends utils.Adapter {
3421
3360
  /**
3422
3361
  * @param {number} dpValue - get Time of this datapoint
3423
3362
  */
3424
- async getTimestamp(dpValue) {
3363
+ getTimestamp(dpValue) {
3425
3364
  const time = new Date();
3426
3365
  return (dpValue = Math.round((time.getTime() - dpValue) / 1000 / 60));
3427
3366
  }
3428
3367
 
3429
3368
  /**
3430
3369
  * @param {string} dp - get Time of this datapoint
3370
+ * @param {number} ms - milliseconds
3431
3371
  */
3432
- async getTimestampConnectionDP(dp) {
3372
+ async getTimestampConnectionDP(dp, ms) {
3433
3373
  const time = new Date();
3434
3374
  const dpValue = await this.getForeignStateAsync(dp);
3435
- if (dpValue !== null && dpValue !== undefined) {
3436
- const dpLastStateChange = Math.round((time.getTime() - dpValue.lc) / 1000);
3437
- return dpLastStateChange;
3375
+ if (dpValue) {
3376
+ if (!dpValue.val) return false;
3377
+
3378
+ const dpLastStateChange = Math.round(time.getTime() - dpValue.lc); // calculate in ms
3379
+ if (dpLastStateChange >= ms) {
3380
+ return true;
3381
+ } else {
3382
+ return false;
3383
+ }
3438
3384
  }
3439
3385
  }
3440
3386
 
@@ -3459,7 +3405,7 @@ class DeviceWatcher extends utils.Adapter {
3459
3405
  /**
3460
3406
  * @param {object} data - object
3461
3407
  */
3462
- async parseData(data) {
3408
+ parseData(data) {
3463
3409
  if (!data) return {};
3464
3410
  if (typeof data === 'object') return data;
3465
3411
  if (typeof data === 'string') return JSON.parse(data);
@@ -3469,8 +3415,8 @@ class DeviceWatcher extends utils.Adapter {
3469
3415
  /**
3470
3416
  * @param {number} time
3471
3417
  */
3472
- async wait(time) {
3473
- return new Promise((resolve) => {
3418
+ wait(time) {
3419
+ return new Promise(function (resolve) {
3474
3420
  setTimeout(resolve, time);
3475
3421
  });
3476
3422
  }
@@ -3481,7 +3427,7 @@ class DeviceWatcher extends utils.Adapter {
3481
3427
  * Inspired by https://stackoverflow.com/questions/68134104/
3482
3428
  * @param {string} lastCronRun
3483
3429
  */
3484
- async getPreviousCronRun(lastCronRun) {
3430
+ getPreviousCronRun(lastCronRun) {
3485
3431
  try {
3486
3432
  const interval = cronParser.parseExpression(lastCronRun);
3487
3433
  const previous = interval.prev();