iobroker.device-watcher 2.5.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/main.js CHANGED
@@ -26,13 +26,11 @@ class DeviceWatcher extends utils.Adapter {
26
26
 
27
27
  // instances and adapters
28
28
  // raw arrays
29
- this.adapterUpdatesJsonRaw = [];
30
- this.listInstanceRaw = [];
29
+ this.listInstanceRaw = new Map();
30
+ this.adapterUpdatesJsonRaw = new Map();
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,23 @@ 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
53
+ this.listAllDevicesUserRaw = [];
54
+ this.listAllDevices = [];
49
55
  this.offlineDevices = [];
50
56
  this.linkQualityDevices = [];
51
57
  this.batteryPowered = [];
52
58
  this.batteryLowPowered = [];
53
- this.listAllDevices = [];
54
- this.blacklistLists = [];
55
- this.blacklistAdapterLists = [];
56
- this.blacklistNotify = [];
57
59
  this.selAdapter = [];
58
60
  this.adapterSelected = [];
59
61
  this.upgradableList = [];
60
62
 
61
- // raw arrays
62
- this.listAllDevicesRaw = [];
63
- this.batteryLowPoweredRaw = [];
64
- this.offlineDevicesRaw = [];
65
- this.upgradableDevicesRaw = [];
66
-
67
63
  // counts
68
64
  this.offlineDevicesCount = 0;
69
65
  this.deviceCounter = 0;
@@ -72,12 +68,22 @@ class DeviceWatcher extends utils.Adapter {
72
68
  this.lowBatteryPoweredCount = 0;
73
69
  this.upgradableDevicesCount = 0;
74
70
 
71
+ // Blacklist
72
+ // Instances
73
+ this.blacklistInstancesLists = [];
74
+ this.blacklistInstancesNotify = [];
75
+
76
+ // Devices
77
+ this.blacklistLists = [];
78
+ this.blacklistAdapterLists = [];
79
+ this.blacklistNotify = [];
80
+
75
81
  // Interval timer
76
82
  this.refreshDataTimeout = null;
77
83
 
78
84
  this.on('ready', this.onReady.bind(this));
79
85
  this.on('stateChange', this.onStateChange.bind(this));
80
- // this.on('objectChange', this.onObjectChange.bind(this));
86
+ this.on('objectChange', this.onObjectChange.bind(this));
81
87
  this.on('message', this.onMessage.bind(this));
82
88
  this.on('unload', this.onUnload.bind(this));
83
89
  }
@@ -88,117 +94,122 @@ class DeviceWatcher extends utils.Adapter {
88
94
  async onReady() {
89
95
  this.log.debug(`Adapter ${adapterName} was started`);
90
96
 
91
- try {
92
- this.listOnlyBattery = this.config.listOnlyBattery;
93
- this.createOwnFolder = this.config.createOwnFolder;
94
- this.createHtmlList = this.config.createHtmlList;
95
-
96
- this.configSetAdapter = {
97
- alexa2: this.config.alexa2Devices,
98
- apcups: this.config.apcupsDevices,
99
- ble: this.config.bleDevices,
100
- deconz: this.config.deconzDevices,
101
- enocean: this.config.enoceanDevices,
102
- esphome: this.config.esphomeDevices,
103
- eusec: this.config.eusecDevices,
104
- fritzdect: this.config.fritzdectDevices,
105
- fullybrowser: this.config.fullybrowserDevices,
106
- ham: this.config.hamDevices,
107
- harmony: this.config.harmonyDevices,
108
- hmiP: this.config.hmiPDevices,
109
- hmrpc: this.config.hmrpcDevices,
110
- homeconnect: this.config.homeconnectDevices,
111
- hs100: this.config.hs100Devices,
112
- hue: this.config.hueDevices,
113
- hueExt: this.config.hueExtDevices,
114
- innogy: this.config.innogyDevices,
115
- jeelink: this.config.jeelinkDevices,
116
- lupusec: this.config.lupusecDevices,
117
- maxcube: this.config.maxcubeDevices,
118
- meross: this.config.merossDevices,
119
- mihome: this.config.mihomeDevices,
120
- mihomeGW: this.config.mihomeDevices,
121
- mihomeVacuum: this.config.mihomeVacuumDevices,
122
- mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttDevices,
123
- mqttNuki: this.config.mqttNukiDevices,
124
- musiccast: this.config.musiccastDevices,
125
- netatmo: this.config.netatmoDevices,
126
- nukiExt: this.config.nukiExtDevices,
127
- nut: this.config.nutDevices,
128
- ping: this.config.pingDevices,
129
- roomba: this.config.roombaDevices,
130
- shelly: this.config.shellyDevices,
131
- smartgarden: this.config.smartgardenDevices,
132
- sonoff: this.config.sonoffDevices,
133
- sonos: this.config.sonosDevices,
134
- sureflap: this.config.sureflapDevices,
135
- switchbotBle: this.config.switchbotBleDevices,
136
- tado: this.config.tadoDevices,
137
- tapo: this.config.tapoDevices,
138
- tradfri: this.config.tradfriDevices,
139
- unifi: this.config.unifiDevices,
140
- wled: this.config.wledDevices,
141
- yeelight: this.config.yeelightDevices,
142
- zigbee: this.config.zigbeeDevices,
143
- zigbee2MQTT: this.config.zigbee2mqttDevices,
144
- zwave: this.config.zwaveDevices,
145
- };
146
-
147
- this.configMaxMinutes = {
148
- alexa2: this.config.alexa2MaxMinutes,
149
- apcups: this.config.apcupsMaxMinutes,
150
- ble: this.config.bleMaxMinutes,
151
- deconz: this.config.deconzMaxMinutes,
152
- enocean: this.config.enoceanMaxMinutes,
153
- esphome: this.config.esphomeMaxMinutes,
154
- eusec: this.config.eusecMaxMinutes,
155
- fritzdect: this.config.fritzdectMaxMinutes,
156
- fullybrowser: this.config.fullybrowserMaxMinutes,
157
- ham: this.config.hamMaxMinutes,
158
- harmony: this.config.harmonyMaxMinutes,
159
- hmiP: this.config.hmiPMaxMinutes,
160
- hmrpc: this.config.hmrpcMaxMinutes,
161
- homeconnect: this.config.homeconnectMaxMinutes,
162
- hs100: this.config.hs100MaxMinutes,
163
- hue: this.config.hueMaxMinutes,
164
- hueExt: this.config.hueextMaxMinutes,
165
- innogy: this.config.innogyMaxMinutes,
166
- jeelink: this.config.jeelinkMaxMinutes,
167
- lupusec: this.config.lupusecMaxMinutes,
168
- maxcube: this.config.maxcubeMaxMinutes,
169
- meross: this.config.merossMaxMinutes,
170
- mihome: this.config.mihomeMaxMinutes,
171
- mihomeGW: this.config.mihomeMaxMinutes,
172
- mihomeVacuum: this.config.mihomeVacuumMaxMinutes,
173
- mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttMaxMinutes,
174
- mqttNuki: this.config.mqttNukiMaxMinutes,
175
- musiccast: this.config.musiccastMaxMinutes,
176
- netatmo: this.config.netatmoMaxMinutes,
177
- nukiExt: this.config.nukiextendMaxMinutes,
178
- nut: this.config.nutMaxMinutes,
179
- ping: this.config.pingMaxMinutes,
180
- roomba: this.config.roombaMaxMinutes,
181
- shelly: this.config.shellyMaxMinutes,
182
- smartgarden: this.config.smartgardenMaxMinutes,
183
- sonoff: this.config.sonoffMaxMinutes,
184
- sonos: this.config.sonosMaxMinutes,
185
- sureflap: this.config.sureflapMaxMinutes,
186
- switchbotBle: this.config.switchbotMaxMinutes,
187
- tado: this.config.tadoMaxMinutes,
188
- tapo: this.config.tapoMaxMinutes,
189
- tradfri: this.config.tradfriMaxMinutes,
190
- unifi: this.config.unifiMaxMinutes,
191
- wled: this.config.wledMaxMinutes,
192
- yeelight: this.config.yeelightMaxMinutes,
193
- zigbee: this.config.zigbeeMaxMinutes,
194
- zigbee2MQTT: this.config.zigbee2mqttMaxMinutes,
195
- zwave: this.config.zwaveMaxMinutes,
196
- };
97
+ this.configCreateInstanceList = this.config.checkAdapterInstances;
98
+ this.configListOnlyBattery = this.config.listOnlyBattery;
99
+ this.configCreateOwnFolder = this.config.createOwnFolder;
100
+ this.configCreateHtmlList = this.config.createHtmlList;
101
+
102
+ this.configSetAdapter = {
103
+ alexa2: this.config.alexa2Devices,
104
+ apcups: this.config.apcupsDevices,
105
+ ble: this.config.bleDevices,
106
+ deconz: this.config.deconzDevices,
107
+ enocean: this.config.enoceanDevices,
108
+ esphome: this.config.esphomeDevices,
109
+ eusec: this.config.eusecDevices,
110
+ fhemTFAsensors: this.config.fhemTFAsensorsDevices,
111
+ fritzdect: this.config.fritzdectDevices,
112
+ fullybrowser: this.config.fullybrowserDevices,
113
+ ham: this.config.hamDevices,
114
+ harmony: this.config.harmonyDevices,
115
+ hmiP: this.config.hmiPDevices,
116
+ hmrpc: this.config.hmrpcDevices,
117
+ homeconnect: this.config.homeconnectDevices,
118
+ hs100: this.config.hs100Devices,
119
+ hue: this.config.hueDevices,
120
+ hueExt: this.config.hueExtDevices,
121
+ innogy: this.config.innogyDevices,
122
+ jeelink: this.config.jeelinkDevices,
123
+ lupusec: this.config.lupusecDevices,
124
+ maxcube: this.config.maxcubeDevices,
125
+ meross: this.config.merossDevices,
126
+ mihome: this.config.mihomeDevices,
127
+ mihomeGW: this.config.mihomeDevices,
128
+ mihomeVacuum: this.config.mihomeVacuumDevices,
129
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttDevices,
130
+ mqttNuki: this.config.mqttNukiDevices,
131
+ musiccast: this.config.musiccastDevices,
132
+ netatmo: this.config.netatmoDevices,
133
+ nukiExt: this.config.nukiExtDevices,
134
+ nut: this.config.nutDevices,
135
+ ping: this.config.pingDevices,
136
+ proxmox: this.config.proxmoxDevices,
137
+ roomba: this.config.roombaDevices,
138
+ shelly: this.config.shellyDevices,
139
+ smartgarden: this.config.smartgardenDevices,
140
+ sonoff: this.config.sonoffDevices,
141
+ sonos: this.config.sonosDevices,
142
+ sureflap: this.config.sureflapDevices,
143
+ switchbotBle: this.config.switchbotBleDevices,
144
+ tado: this.config.tadoDevices,
145
+ tapo: this.config.tapoDevices,
146
+ tradfri: this.config.tradfriDevices,
147
+ unifi: this.config.unifiDevices,
148
+ wled: this.config.wledDevices,
149
+ yeelight: this.config.yeelightDevices,
150
+ zigbee: this.config.zigbeeDevices,
151
+ zigbee2MQTT: this.config.zigbee2mqttDevices,
152
+ zwave: this.config.zwaveDevices,
153
+ };
154
+
155
+ this.configMaxMinutes = {
156
+ alexa2: this.config.alexa2MaxMinutes,
157
+ apcups: this.config.apcupsMaxMinutes,
158
+ ble: this.config.bleMaxMinutes,
159
+ deconz: this.config.deconzMaxMinutes,
160
+ enocean: this.config.enoceanMaxMinutes,
161
+ esphome: this.config.esphomeMaxMinutes,
162
+ eusec: this.config.eusecMaxMinutes,
163
+ fhemTFAsensors: this.config.fhemTFAsensorsMaxMinutes,
164
+ fritzdect: this.config.fritzdectMaxMinutes,
165
+ fullybrowser: this.config.fullybrowserMaxMinutes,
166
+ ham: this.config.hamMaxMinutes,
167
+ harmony: this.config.harmonyMaxMinutes,
168
+ hmiP: this.config.hmiPMaxMinutes,
169
+ hmrpc: this.config.hmrpcMaxMinutes,
170
+ homeconnect: this.config.homeconnectMaxMinutes,
171
+ hs100: this.config.hs100MaxMinutes,
172
+ hue: this.config.hueMaxMinutes,
173
+ hueExt: this.config.hueextMaxMinutes,
174
+ innogy: this.config.innogyMaxMinutes,
175
+ jeelink: this.config.jeelinkMaxMinutes,
176
+ lupusec: this.config.lupusecMaxMinutes,
177
+ maxcube: this.config.maxcubeMaxMinutes,
178
+ meross: this.config.merossMaxMinutes,
179
+ mihome: this.config.mihomeMaxMinutes,
180
+ mihomeGW: this.config.mihomeMaxMinutes,
181
+ mihomeVacuum: this.config.mihomeVacuumMaxMinutes,
182
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttMaxMinutes,
183
+ mqttNuki: this.config.mqttNukiMaxMinutes,
184
+ musiccast: this.config.musiccastMaxMinutes,
185
+ netatmo: this.config.netatmoMaxMinutes,
186
+ nukiExt: this.config.nukiextendMaxMinutes,
187
+ nut: this.config.nutMaxMinutes,
188
+ ping: this.config.pingMaxMinutes,
189
+ proxmox: this.config.proxmoxMaxMinutes,
190
+ roomba: this.config.roombaMaxMinutes,
191
+ shelly: this.config.shellyMaxMinutes,
192
+ smartgarden: this.config.smartgardenMaxMinutes,
193
+ sonoff: this.config.sonoffMaxMinutes,
194
+ sonos: this.config.sonosMaxMinutes,
195
+ sureflap: this.config.sureflapMaxMinutes,
196
+ switchbotBle: this.config.switchbotMaxMinutes,
197
+ tado: this.config.tadoMaxMinutes,
198
+ tapo: this.config.tapoMaxMinutes,
199
+ tradfri: this.config.tradfriMaxMinutes,
200
+ unifi: this.config.unifiMaxMinutes,
201
+ wled: this.config.wledMaxMinutes,
202
+ yeelight: this.config.yeelightMaxMinutes,
203
+ zigbee: this.config.zigbeeMaxMinutes,
204
+ zigbee2MQTT: this.config.zigbee2mqttMaxMinutes,
205
+ zwave: this.config.zwaveMaxMinutes,
206
+ };
197
207
 
208
+ try {
198
209
  for (const [id] of Object.entries(arrApart)) {
199
210
  if (this.configSetAdapter[id]) {
200
211
  this.selAdapter.push(arrApart[id]);
201
- this.adapterSelected.push(await this.capitalize(id));
212
+ this.adapterSelected.push(this.capitalize(id));
202
213
  }
203
214
  }
204
215
 
@@ -214,19 +225,23 @@ class DeviceWatcher extends utils.Adapter {
214
225
  }
215
226
 
216
227
  //create Blacklist
217
- try {
218
- await this.createBlacklist();
219
- } catch (error) {
220
- this.errorReporting('[onReady - create blacklist]', error);
221
- }
228
+ await this.createBlacklist();
222
229
 
223
- //create and fill datapoints for each adapter if selected
224
- if (this.createOwnFolder) {
230
+ //create datapoints for each adapter if selected
231
+ for (const [id] of Object.entries(arrApart)) {
225
232
  try {
226
- for (const [id] of Object.entries(arrApart)) {
227
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
233
+ if (!this.configCreateOwnFolder) {
234
+ await this.deleteDPsForEachAdapter(id);
235
+ await this.deleteHtmlListDatapoints(id);
236
+ } else {
237
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
228
238
  await this.createDPsForEachAdapter(id);
229
- if (this.createHtmlList) await this.createHtmlListDatapoints(id);
239
+ // create HTML list datapoints
240
+ if (!this.configCreateHtmlList) {
241
+ await this.deleteHtmlListDatapoints(id);
242
+ } else {
243
+ await this.createHtmlListDatapoints(id);
244
+ }
230
245
  this.log.debug(`Created datapoints for ${this.capitalize(id)}`);
231
246
  }
232
247
  }
@@ -236,36 +251,98 @@ class DeviceWatcher extends utils.Adapter {
236
251
  }
237
252
 
238
253
  // create HTML list datapoints
239
- if (this.createHtmlList) await this.createHtmlListDatapoints();
254
+ if (!this.configCreateHtmlList) {
255
+ await this.deleteHtmlListDatapoints();
256
+ } else {
257
+ await this.createHtmlListDatapoints();
258
+ }
240
259
 
241
- //read data first at start
260
+ // read data first at start
261
+ // devices
242
262
  await this.main();
243
263
 
244
- if (this.config.checkAdapterInstances) {
245
- await this.getInstanceData();
264
+ // instances and adapters
265
+ if (this.configCreateInstanceList) {
266
+ // instances
267
+ await this.createDPsForInstances();
268
+ await this.getAllInstanceData();
269
+ // adapter updates
246
270
  await this.createAdapterUpdateData();
271
+ } else {
272
+ await this.deleteDPsForInstances();
247
273
  }
248
274
 
249
275
  // update last contact data in interval
250
276
  await this.refreshData();
251
277
 
252
278
  // send overview for low battery devices
253
- if (this.config.checkSendBatteryMsgDaily) await this.sendBatteryNotifyShedule();
279
+ if (this.config.checkSendBatteryMsgDaily) this.sendScheduleNotifications('lowBatteryDevices');
254
280
 
255
281
  // send overview of offline devices
256
- if (this.config.checkSendOfflineMsgDaily) await this.sendOfflineNotificationsShedule();
282
+ if (this.config.checkSendOfflineMsgDaily) this.sendScheduleNotifications('offlineDevices');
257
283
 
258
284
  // send overview of upgradeable devices
259
- if (this.config.checkSendUpgradeMsgDaily) await this.sendDeviceUpdateNotificationsShedule();
285
+ if (this.config.checkSendUpgradeMsgDaily) this.sendScheduleNotifications('updateDevices');
286
+
287
+ // send overview of updatable adapters
288
+ if (this.config.checkSendAdapterUpdateMsgDaily) this.sendScheduleNotifications('updateAdapter');
260
289
 
261
290
  // send overview of instances with error
262
- if (this.config.checkSendInstanceFailedDaily) await this.sendInstanceErrorNotificationShedule();
291
+ if (this.config.checkSendInstanceFailedDaily) this.sendScheduleNotifications('errorInstance');
263
292
  } catch (error) {
264
293
  this.errorReporting('[onReady]', error);
265
294
  this.terminate ? this.terminate(15) : process.exit(15);
266
295
  }
267
296
  } // <-- onReady end
268
297
 
298
+ // If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.
299
+ // You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.
300
+ //
301
+ /**
302
+ * Is called if a subscribed object changes
303
+ * @param {string} id
304
+ * @param {ioBroker.Object | null | undefined} obj
305
+ */
306
+ async onObjectChange(id, obj) {
307
+ if (obj) {
308
+ try {
309
+ // The object was changed
310
+ //this.log.debug(`object ${id} changed: ${JSON.stringify(obj)}`);
311
+
312
+ if (id.startsWith('system.adapter.')) {
313
+ //read new instance data and add it to the lists
314
+ await this.getInstanceData(id);
315
+ } else {
316
+ //read devices data and renew the lists
317
+ await this.main();
318
+ }
319
+ } catch (error) {
320
+ this.log.error(`Issue at object change: ${error}`);
321
+ }
322
+ } else {
323
+ try {
324
+ // The object was deleted
325
+ this.log.info(`object ${id} deleted`);
326
+
327
+ // delete instance data in map
328
+ if (this.listInstanceRaw.has(id)) {
329
+ this.listInstanceRaw.delete(id);
330
+ }
331
+
332
+ // delete device data in map
333
+ if (this.listAllDevicesRaw.has(id)) {
334
+ this.listAllDevicesRaw.delete(id);
335
+ }
336
+
337
+ //unsubscribe of Objects and states
338
+ this.unsubscribeForeignObjects(id);
339
+ this.unsubscribeForeignStates(id);
340
+ } catch (error) {
341
+ this.log.error(`Issue at object deletion: ${error}`);
342
+ }
343
+ }
344
+ }
345
+
269
346
  /**
270
347
  * Is called if a subscribed state changes
271
348
  * @param {string} id
@@ -273,199 +350,221 @@ class DeviceWatcher extends utils.Adapter {
273
350
  */
274
351
  async onStateChange(id, state) {
275
352
  // Admin JSON for Adapter updates
276
- if (id && state) {
277
- this.log.debug(`State changed: ${id} changed ${state.val}`);
353
+ if (state) {
354
+ // this.log.debug(`State changed: ${id} changed ${state.val}`);
278
355
  let batteryData;
356
+ let signalData;
279
357
  let oldLowBatState;
280
358
  let contactData;
281
359
  let oldStatus;
282
360
  let isLowBatValue;
283
361
  let instanceStatusRaw;
284
- let instanceDeviceConnectionDpTS;
285
- const instanceDeviceConnectionDpTSminTime = 10;
362
+ let oldInstanceHostState;
363
+ let oldInstanceDeviceState;
286
364
 
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);
365
+ try {
366
+ if (id.endsWith('updatesJson')) {
367
+ await this.getAdapterUpdateData(id);
368
+ await this.createAdapterUpdateList();
369
+ if (this.config.checkSendAdapterUpdateMsg) {
370
+ await this.sendStateNotifications('updateAdapter', null);
294
371
  }
295
- }
296
- }*/
297
-
298
- for (const instance of this.listInstanceRaw) {
299
- switch (id) {
300
- case instance.instanceAlivePath:
301
- if (state.val !== instance.isAlive) {
302
- instanceStatusRaw = await this.setInstanceStatus(
303
- instance.instanceMode,
304
- instance.schedule,
305
- instance.instanceAlivePath,
306
- state.val,
307
- instance.isConnectedHost,
308
- instance.isConnectedDevice,
309
- );
310
- instance.isAlive = instanceStatusRaw[1];
311
- instance.status = instanceStatusRaw[0];
312
- instance.isHealthy = instanceStatusRaw[2];
313
- }
314
- break;
315
- case instance.connectedHostPath:
316
- if (instance.isAlive && state.val !== instance.isConnectedHost) {
317
- instance.isConnectedHost = state.val;
318
- instanceStatusRaw = await this.setInstanceStatus(
319
- instance.instanceMode,
320
- instance.schedule,
321
- instance.instanceAlivePath,
322
- instance.isAlive,
323
- state.val,
324
- instance.isConnectedDevice,
325
- );
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);
372
+ for (const instance of this.listInstanceRaw.values()) {
373
+ if (this.adapterUpdatesJsonRaw.has(instance.Adapter)) {
374
+ for (const adapter of this.adapterUpdatesJsonRaw.values()) {
375
+ instance.updateAvailable = adapter.newVersion;
332
376
  }
377
+ } else {
378
+ instance.updateAvailable = ' - ';
333
379
  }
334
- break;
335
- case instance.connectedDevicePath:
336
- if (instance.isAlive && state.val !== instance.isConnectedDevice) {
337
- instance.isConnectedDevice = state.val;
338
- instanceStatusRaw = await this.setInstanceStatus(
339
- instance.instanceMode,
340
- instance.schedule,
341
- instance.instanceAlivePath,
342
- instance.isAlive,
343
- instance.isConnectedHost,
344
- state.val,
345
- );
346
- instance.isAlive = instanceStatusRaw[1];
347
- instance.status = instanceStatusRaw[0];
348
- instance.isHealthy = instanceStatusRaw[2];
380
+ }
381
+ }
349
382
 
350
- if (this.config.checkSendInstanceFailedMsg && !instance.isHealthy && !this.blacklistNotify.includes(instance.instanceAlivePath)) {
351
- await this.sendInstanceErrorNotification(instance.InstanceName, instance.status);
383
+ for (const [instance, instanceData] of this.listInstanceRaw) {
384
+ switch (id) {
385
+ case instanceData.instanceAlivePath:
386
+ if (state.val !== instanceData.isAlive) {
387
+ instanceStatusRaw = await this.setInstanceStatus(
388
+ instanceData.instanceMode,
389
+ instanceData.schedule,
390
+ instanceData.instanceAlivePath,
391
+ instanceData.connectedHostPath,
392
+ instanceData.connectedDevicePath,
393
+ );
394
+ instanceData.isAlive = instanceStatusRaw[1];
395
+ instanceData.status = instanceStatusRaw[0];
396
+ instanceData.isHealthy = instanceStatusRaw[2];
352
397
  }
353
- }
354
- break;
398
+ break;
399
+ case instanceData.connectedHostPath:
400
+ oldInstanceHostState = instanceData.isConnectedHost;
401
+ instanceData.isConnectedHost = state.val;
402
+ if (oldInstanceHostState !== instanceData.isConnectedHost) {
403
+ instanceStatusRaw = await this.setInstanceStatus(
404
+ instanceData.instanceMode,
405
+ instanceData.schedule,
406
+ instanceData.instanceAlivePath,
407
+ instanceData.connectedHostPath,
408
+ instanceData.connectedDevicePath,
409
+ );
410
+ instanceData.isAlive = instanceStatusRaw[1];
411
+ instanceData.status = instanceStatusRaw[0];
412
+ instanceData.isHealthy = instanceStatusRaw[2];
413
+
414
+ if (!instanceData.isAlive) continue;
415
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
416
+ if (!instanceData.isHealthy) {
417
+ await this.sendStateNotifications('errorInstance', instance);
418
+ }
419
+ }
420
+ }
421
+ break;
422
+ case instanceData.connectedDevicePath:
423
+ oldInstanceDeviceState = instanceData.isConnectedDevice;
424
+ instanceData.isConnectedDevice = state.val;
425
+ if (oldInstanceDeviceState !== instanceData.isConnectedDevice) {
426
+ instanceStatusRaw = await this.setInstanceStatus(
427
+ instanceData.instanceMode,
428
+ instanceData.schedule,
429
+ instanceData.instanceAlivePath,
430
+ instanceData.connectedHostPath,
431
+ instanceData.connectedDevicePath,
432
+ );
433
+ instanceData.isAlive = instanceStatusRaw[1];
434
+ instanceData.status = instanceStatusRaw[0];
435
+ instanceData.isHealthy = instanceStatusRaw[2];
436
+
437
+ if (!instanceData.isAlive) continue;
438
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
439
+ if (!instanceData.isHealthy) {
440
+ await this.sendStateNotifications('errorInstance', instance);
441
+ }
442
+ }
443
+ }
444
+ break;
445
+ }
355
446
  }
356
- }
357
447
 
358
- for (const device of this.listAllDevicesRaw) {
359
- // On statechange update available datapoint
360
- switch (id) {
361
- case device.instanceDeviceConnectionDP:
362
- if (state.val !== device.instancedeviceConnected) {
363
- device.instancedeviceConnected = state.val;
364
- }
365
- break;
448
+ for (const [device, deviceData] of this.listAllDevicesRaw) {
449
+ // On statechange update available datapoint
450
+ switch (id) {
451
+ case deviceData.instanceDeviceConnectionDP:
452
+ if (state.val !== deviceData.instancedeviceConnected) {
453
+ deviceData.instancedeviceConnected = state.val;
454
+ }
455
+ break;
366
456
 
367
- case device.UpdateDP:
368
- if (state.val !== device.Upgradable) {
369
- device.Upgradable = state.val;
370
- if (state.val) {
371
- if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(device.Path)) {
372
- await this.sendDeviceUpdatesNotification(device.Device, device.Adapter);
457
+ case deviceData.UpdateDP:
458
+ if (state.val !== deviceData.Upgradable) {
459
+ deviceData.Upgradable = state.val;
460
+ if (state.val) {
461
+ if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(deviceData.Path)) {
462
+ await this.sendStateNotifications('updateDevice', device);
463
+ }
373
464
  }
374
465
  }
375
- }
376
- break;
466
+ break;
377
467
 
378
- case device.SignalStrengthDP:
379
- device.SignalStrength = await this.calculateSignalStrength(state, device.adapterID);
380
- break;
468
+ case deviceData.SignalStrengthDP:
469
+ signalData = await this.calculateSignalStrength(state, deviceData.adapterID);
470
+ deviceData.SignalStrength = signalData[0];
381
471
 
382
- case device.batteryDP:
383
- if (device.isBatteryDevice) {
384
- oldLowBatState = device.LowBat;
385
- batteryData = await this.getBatteryData(state.val, oldLowBatState, device.adapterID);
472
+ break;
386
473
 
387
- device.Battery = batteryData[0];
388
- device.BatteryRaw = batteryData[2];
389
- if (device.LowBatDP !== 'none') {
390
- isLowBatValue = await this.getInitValue(device.LowBatDP);
391
- } else {
392
- isLowBatValue = undefined;
393
- }
394
- device.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, device.faultReport, device.adapterID);
474
+ case deviceData.batteryDP:
475
+ if (deviceData.isBatteryDevice) {
476
+ oldLowBatState = deviceData.LowBat;
477
+ batteryData = await this.getBatteryData(state.val, oldLowBatState, deviceData.faultReport, deviceData.adapterID);
478
+
479
+ deviceData.Battery = batteryData[0];
480
+ deviceData.BatteryRaw = batteryData[2];
481
+ deviceData.BatteryUnitRaw = batteryData[3];
482
+ if (deviceData.LowBatDP !== 'none') {
483
+ isLowBatValue = await this.getInitValue(deviceData.LowBatDP);
484
+ } else {
485
+ isLowBatValue = undefined;
486
+ }
487
+ deviceData.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, deviceData.faultReport, deviceData.adapterID);
395
488
 
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);
489
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
490
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
491
+ await this.sendStateNotifications('lowBatDevice', device);
492
+ }
399
493
  }
400
494
  }
401
- }
402
- break;
495
+ break;
403
496
 
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);
497
+ case deviceData.LowBatDP:
498
+ if (deviceData.isBatteryDevice) {
499
+ oldLowBatState = deviceData.LowBat;
500
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
501
+ deviceData.Battery = batteryData[0];
502
+ deviceData.BatteryRaw = batteryData[2];
503
+ deviceData.BatteryUnitRaw = batteryData[3];
504
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
505
+
506
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
507
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
508
+ await this.sendStateNotifications('lowBatDevice', device);
509
+ }
415
510
  }
416
511
  }
417
- }
418
- break;
512
+ break;
419
513
 
420
- case device.faultReportDP:
421
- if (device.isBatteryDevice) {
422
- oldLowBatState = device.LowBat;
423
- batteryData = await this.getBatteryData(device.BatteryRaw, oldLowBatState, device.adapterID);
514
+ case deviceData.faultReportDP:
515
+ if (deviceData.isBatteryDevice) {
516
+ oldLowBatState = deviceData.LowBat;
517
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, oldLowBatState, state.val, deviceData.adapterID);
424
518
 
425
- device.Battery = batteryData[0];
426
- device.BatteryRaw = batteryData[2];
427
- device.LowBat = await this.setLowbatIndicator(device.BatteryRaw, undefined, state.val, device.adapterID);
519
+ deviceData.Battery = batteryData[0];
520
+ deviceData.BatteryRaw = batteryData[2];
521
+ deviceData.BatteryUnitRaw = batteryData[3];
522
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, undefined, state.val, deviceData.adapterID);
428
523
 
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);
524
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
525
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
526
+ await this.sendStateNotifications('lowBatDevice', device);
527
+ }
432
528
  }
433
529
  }
434
- }
435
- break;
530
+ break;
436
531
 
437
- case device.UnreachDP:
438
- oldStatus = device.Status;
439
- device.UnreachState = await this.getInitValue(device.UnreachDP);
440
- 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,
448
- );
449
- if (contactData !== undefined) {
450
- device.LastContact = contactData[0];
451
- device.Status = contactData[1];
452
- device.SignalStrength = contactData[2];
453
- }
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);
459
- }
532
+ case deviceData.UnreachDP:
533
+ oldStatus = deviceData.Status;
534
+ deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
535
+ contactData = await this.getOnlineState(
536
+ deviceData.timeSelector,
537
+ deviceData.adapterID,
538
+ deviceData.UnreachDP,
539
+ deviceData.SignalStrength,
540
+ deviceData.UnreachState,
541
+ deviceData.DeviceStateSelectorDP,
542
+ deviceData.rssiPeerSelectorDP,
543
+ );
544
+ if (contactData !== undefined) {
545
+ deviceData.LastContact = contactData[0];
546
+ deviceData.Status = contactData[1];
547
+ deviceData.SignalStrength = contactData[2];
460
548
  }
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);
549
+ if (this.config.checkSendOfflineMsg && oldStatus !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
550
+ if (deviceData.instanceDeviceConnectionDP !== undefined) {
551
+ // check if the generally deviceData connected state is for a while true
552
+ if (await this.getTimestampConnectionDP(deviceData.instanceDeviceConnectionDP, 20000)) {
553
+ await this.sendStateNotifications('onlineStateDevice', device);
554
+ }
555
+ } else {
556
+ await this.sendStateNotifications('onlineStateDevice', device);
557
+ }
464
558
  }
465
- }
466
- break;
559
+ break;
560
+ }
467
561
  }
562
+ } catch (error) {
563
+ this.log.error(`Issue at state change: ${error}`);
468
564
  }
565
+ } else {
566
+ // The state was deleted
567
+ this.log.debug(`state ${id} deleted`);
469
568
  }
470
569
  }
471
570
 
@@ -474,26 +573,23 @@ class DeviceWatcher extends utils.Adapter {
474
573
  */
475
574
  onMessage(obj) {
476
575
  const devices = [];
477
- let myCount = 0;
478
- let result;
479
576
  const instances = [];
480
- let myCountInstances = 0;
481
- let resultInstances;
577
+ let countDevices = 0;
578
+ let countInstances = 0;
482
579
 
483
580
  switch (obj.command) {
484
581
  case 'devicesList':
485
582
  if (obj.message) {
486
583
  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,
584
+ for (const deviceData of this.listAllDevicesRaw.values()) {
585
+ const label = `${deviceData.Adapter}: ${deviceData.Device}`;
586
+ const valueObjectDevices = {
587
+ deviceName: deviceData.Device,
588
+ adapter: deviceData.Adapter,
589
+ path: deviceData.Path,
494
590
  };
495
- devices[myCount] = { label: label, value: JSON.stringify(myValueObject) };
496
- myCount++;
591
+ devices[countDevices] = { label: label, value: JSON.stringify(valueObjectDevices) };
592
+ countDevices++;
497
593
  }
498
594
  const sortDevices = devices.slice(0);
499
595
  sortDevices.sort(function (a, b) {
@@ -503,7 +599,7 @@ class DeviceWatcher extends utils.Adapter {
503
599
  });
504
600
  this.sendTo(obj.from, obj.command, sortDevices, obj.callback);
505
601
  } catch (error) {
506
- this.sendTo(obj.from, obj.command, obj.callback);
602
+ this.errorReporting('[onMessage - deviceList for blacklisttable]', error);
507
603
  }
508
604
  } else {
509
605
  this.sendTo(obj.from, obj.command, obj.callback);
@@ -513,16 +609,15 @@ class DeviceWatcher extends utils.Adapter {
513
609
  case 'instancesList':
514
610
  if (obj.message) {
515
611
  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,
612
+ for (const instanceData of this.listInstanceRaw.values()) {
613
+ const label = `${instanceData.Adapter}: ${instanceData.InstanceName}`;
614
+ const valueObjectInstances = {
615
+ adapter: instanceData.Adapter,
616
+ instanceName: instanceData.InstanceName,
617
+ path: instanceData.instanceAlivePath,
523
618
  };
524
- instances[myCountInstances] = { label: label, value: JSON.stringify(myValueObject) };
525
- myCountInstances++;
619
+ instances[countInstances] = { label: label, value: JSON.stringify(valueObjectInstances) };
620
+ countInstances++;
526
621
  }
527
622
  const sortInstances = instances.slice(0);
528
623
  sortInstances.sort(function (a, b) {
@@ -532,7 +627,7 @@ class DeviceWatcher extends utils.Adapter {
532
627
  });
533
628
  this.sendTo(obj.from, obj.command, sortInstances, obj.callback);
534
629
  } catch (error) {
535
- this.sendTo(obj.from, obj.command, obj.callback);
630
+ this.errorReporting('[onMessage - instanceList for blacklisttable]', error);
536
631
  }
537
632
  } else {
538
633
  this.sendTo(obj.from, obj.command, obj.callback);
@@ -549,18 +644,27 @@ class DeviceWatcher extends utils.Adapter {
549
644
 
550
645
  // fill counts and lists of all selected adapter
551
646
  try {
552
- await this.createDataOfAllAdapter();
647
+ for (let i = 0; i < this.selAdapter.length; i++) {
648
+ await this.createData(i);
649
+ await this.createLists();
650
+ }
651
+ await this.writeDatapoints(); // fill the datapoints
553
652
  this.log.debug(`Created and filled data for all adapters`);
554
653
  } catch (error) {
555
654
  this.errorReporting('[main - create data of all adapter]', error);
556
655
  }
557
656
 
558
657
  // fill datapoints for each adapter if selected
559
- if (this.createOwnFolder) {
658
+ if (this.configCreateOwnFolder) {
560
659
  try {
561
660
  for (const [id] of Object.entries(arrApart)) {
562
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
563
- await this.createDataForEachAdapter(id);
661
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
662
+ for (const deviceData of this.listAllDevicesRaw.values()) {
663
+ // list device only if selected adapter matched with device
664
+ if (!deviceData.adapterID.includes(id)) continue;
665
+ await this.createLists(id);
666
+ }
667
+ await this.writeDatapoints(id); // fill the datapoints
564
668
  this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
565
669
  }
566
670
  }
@@ -577,15 +681,18 @@ class DeviceWatcher extends utils.Adapter {
577
681
  * is neccessary to refresh lastContact data, especially of devices without state changes
578
682
  */
579
683
  async refreshData() {
684
+ if (isUnloaded) return; // cancel run if unloaded was called.
580
685
  const nextTimeout = this.config.updateinterval * 1000;
581
686
 
687
+ // devices data
582
688
  await this.checkLastContact();
583
689
  await this.createLists();
584
690
  await this.writeDatapoints();
585
691
 
586
- if (this.createOwnFolder) {
692
+ // devices data in own adapter folder
693
+ if (this.configCreateOwnFolder) {
587
694
  for (const [id] of Object.entries(arrApart)) {
588
- if (this.configSetAdapter !== undefined && this.configSetAdapter[id]) {
695
+ if (this.configSetAdapter && this.configSetAdapter[id]) {
589
696
  await this.createLists(id);
590
697
  await this.writeDatapoints(id);
591
698
  this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
@@ -593,26 +700,22 @@ class DeviceWatcher extends utils.Adapter {
593
700
  }
594
701
  }
595
702
 
596
- if (this.config.checkAdapterInstances) {
703
+ // instance and adapter data
704
+ if (this.configCreateInstanceList) {
597
705
  await this.createInstanceList();
598
706
  await this.writeInstanceDPs();
599
707
  }
600
708
 
601
709
  // Clear existing timeout
602
710
  if (this.refreshDataTimeout) {
603
- this.log.debug('clearing old refresh timeout');
604
- this.clearTimeout(this.refreshDataTimeout);
711
+ clearTimeout(this.refreshDataTimeout);
712
+ this.refreshDataTimeout = null;
605
713
  }
606
- if (!isUnloaded) {
607
- this.refreshDataTimeout = this.setTimeout(() => {
608
- this.log.debug('Updating Data');
609
714
 
610
- this.refreshDataTimeout = null;
611
- this.refreshData();
612
- }, nextTimeout);
613
- } else {
614
- return; // cancel run if unloaded was called.
615
- }
715
+ this.refreshDataTimeout = setTimeout(() => {
716
+ this.log.debug('Updating Data');
717
+ this.refreshData();
718
+ }, nextTimeout);
616
719
  } // <-- refreshData end
617
720
 
618
721
  /**
@@ -626,7 +729,7 @@ class DeviceWatcher extends utils.Adapter {
626
729
 
627
730
  for (const i in myBlacklist) {
628
731
  try {
629
- const blacklistParse = await this.parseData(myBlacklist[i].devices);
732
+ const blacklistParse = this.parseData(myBlacklist[i].devices);
630
733
  // push devices in list to ignor device in lists
631
734
  if (myBlacklist[i].checkIgnorLists) {
632
735
  this.blacklistLists.push(blacklistParse.path);
@@ -645,14 +748,14 @@ class DeviceWatcher extends utils.Adapter {
645
748
 
646
749
  if (this.blacklistLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistLists}`);
647
750
  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}`);
751
+ if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistNotify}`);
649
752
 
650
753
  // INSTANCES
651
754
  const myBlacklistInstances = this.config.tableBlacklistInstances;
652
755
 
653
756
  for (const i in myBlacklistInstances) {
654
757
  try {
655
- const blacklistParse = await this.parseData(myBlacklistInstances[i].instances);
758
+ const blacklistParse = this.parseData(myBlacklistInstances[i].instances);
656
759
  // push devices in list to ignor device in lists
657
760
  if (myBlacklistInstances[i].checkIgnorLists) {
658
761
  this.blacklistInstancesLists.push(blacklistParse.path);
@@ -667,7 +770,7 @@ class DeviceWatcher extends utils.Adapter {
667
770
  }
668
771
 
669
772
  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}`);
773
+ if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistInstancesNotify}`);
671
774
 
672
775
  this.log.debug(`Function finished: ${this.createBlacklist.name}`);
673
776
  }
@@ -676,189 +779,209 @@ class DeviceWatcher extends utils.Adapter {
676
779
  * @param {object} i - Device Object
677
780
  */
678
781
  async createData(i) {
679
- const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
680
- const adapterID = this.selAdapter[i].adapterID;
782
+ try {
783
+ const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
784
+ const adapterID = this.selAdapter[i].adapterID;
681
785
 
682
- /*---------- Start of loop ----------*/
683
- for (const [id] of Object.entries(devices)) {
684
- /*=============================================
786
+ /*---------- Start of loop ----------*/
787
+ for (const [id] of Object.entries(devices)) {
788
+ /*=============================================
685
789
  = get Instanz =
686
790
  =============================================*/
687
- const instance = id.slice(0, id.indexOf('.') + 2);
688
- const instanceDeviceConnectionDP = `${instance}.info.connection`;
689
- const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
690
- this.subscribeForeignStates(instanceDeviceConnectionDP);
791
+ const instance = id.slice(0, id.indexOf('.') + 2);
792
+ const instanceDeviceConnectionDP = `${instance}.info.connection`;
793
+ const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
794
+ this.subscribeForeignStates(instanceDeviceConnectionDP);
795
+ this.subscribeForeignObjects(`${this.selAdapter[i].Selektor}`);
691
796
 
692
- /*=============================================
797
+ /*=============================================
693
798
  = Get device name =
694
799
  =============================================*/
695
- const deviceName = await this.getDeviceName(id, i);
800
+ const deviceName = await this.getDeviceName(id, i);
696
801
 
697
- /*=============================================
802
+ /*=============================================
698
803
  = Get adapter name =
699
804
  =============================================*/
700
- const adapter = this.selAdapter[i].adapter;
805
+ const adapter = this.selAdapter[i].adapter;
701
806
 
702
- /*=============================================
807
+ /*=============================================
703
808
  = Get path to datapoints =
704
809
  =============================================*/
705
- const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
706
- const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
810
+ const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
811
+ const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
707
812
 
708
- /*=============================================
813
+ // subscribe to object device path
814
+ this.subscribeForeignObjects(currDeviceString);
815
+
816
+ /*=============================================
709
817
  = Get signal strength =
710
818
  =============================================*/
711
- let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
712
- let deviceQualityState;
819
+ let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
820
+ let deviceQualityState;
713
821
 
714
- switch (adapterID) {
715
- case 'mihomeVacuum':
716
- deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
717
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
718
- break;
822
+ switch (adapterID) {
823
+ case 'mihomeVacuum':
824
+ deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
825
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
826
+ break;
719
827
 
720
- case 'netatmo':
721
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
722
- if (!deviceQualityState) {
723
- deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
828
+ case 'netatmo':
724
829
  deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
725
- }
726
- break;
830
+ if (!deviceQualityState) {
831
+ deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
832
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
833
+ }
834
+ break;
727
835
 
728
- default:
729
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
730
- break;
731
- }
732
- //subscribe to states
733
- this.subscribeForeignStates(deviceQualityDP);
836
+ default:
837
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
838
+ break;
839
+ }
840
+ //subscribe to states
841
+ this.subscribeForeignStates(deviceQualityDP);
734
842
 
735
- let linkQuality = await this.calculateSignalStrength(deviceQualityState, adapterID);
843
+ const signalData = await this.calculateSignalStrength(deviceQualityState, adapterID);
844
+ let linkQuality = signalData[0];
845
+ const linkQualityRaw = signalData[1];
736
846
 
737
- /*=============================================
847
+ /*=============================================
738
848
  = Get battery data =
739
849
  =============================================*/
740
- let deviceBatteryStateDP;
741
- let deviceBatteryState;
742
- let batteryHealth;
743
- let batteryHealthRaw;
744
- let lowBatIndicator;
745
- let isBatteryDevice;
746
- let isLowBatDP;
747
- let faultReportingDP;
748
- let faultReportingState;
749
-
750
- const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
751
- const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
752
-
753
- if (deviceChargerState === undefined || deviceChargerState === false) {
754
- // Get battery states
755
- switch (adapterID) {
756
- case 'hueExt':
757
- case 'mihomeVacuum':
758
- case 'mqttNuki':
759
- deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
760
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
761
- if (deviceBatteryState === undefined) {
762
- deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
850
+ let deviceBatteryStateDP;
851
+ let deviceBatteryState;
852
+ let batteryHealth;
853
+ let batteryHealthRaw;
854
+ let batteryUnitRaw;
855
+ let lowBatIndicator;
856
+ let isBatteryDevice;
857
+ let isLowBatDP;
858
+ let faultReportingDP;
859
+ let faultReportingState;
860
+
861
+ const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
862
+ const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
863
+
864
+ if (deviceChargerState === undefined || deviceChargerState === false) {
865
+ // Get battery states
866
+ switch (adapterID) {
867
+ case 'hmrpc':
868
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
763
869
  deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
764
- }
765
- break;
766
- default:
767
- deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
768
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
769
- if (deviceBatteryState === undefined) {
770
- deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
870
+ if (deviceBatteryState === undefined) {
871
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].hmDNBattery;
872
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
873
+ }
874
+ break;
875
+ case 'hueExt':
876
+ case 'mihomeVacuum':
877
+ case 'mqttNuki':
878
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
771
879
  deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
772
- }
773
- break;
774
- }
880
+ if (deviceBatteryState === undefined) {
881
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
882
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
883
+ }
884
+ break;
885
+ default:
886
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
887
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
888
+ if (deviceBatteryState === undefined) {
889
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
890
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
891
+ }
892
+ break;
893
+ }
775
894
 
776
- // Get low bat states
777
- isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
778
- let deviceLowBatState = await this.getInitValue(isLowBatDP);
779
- if (deviceLowBatState === undefined) {
780
- isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
781
- deviceLowBatState = await this.getInitValue(isLowBatDP);
782
- }
783
- if (deviceLowBatState === undefined) isLowBatDP = 'none';
895
+ // Get low bat states
896
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
897
+ let deviceLowBatState = await this.getInitValue(isLowBatDP);
898
+ if (deviceLowBatState === undefined) {
899
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
900
+ deviceLowBatState = await this.getInitValue(isLowBatDP);
901
+ }
902
+ if (deviceLowBatState === undefined) isLowBatDP = 'none';
784
903
 
785
- faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
786
- faultReportingState = await this.getInitValue(faultReportingDP);
904
+ faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
905
+ faultReportingState = await this.getInitValue(faultReportingDP);
787
906
 
788
- //subscribe to states
789
- this.subscribeForeignStates(deviceBatteryStateDP);
790
- this.subscribeForeignStates(isLowBatDP);
791
- this.subscribeForeignStates(faultReportingDP);
907
+ //subscribe to states
908
+ this.subscribeForeignStates(deviceBatteryStateDP);
909
+ this.subscribeForeignStates(isLowBatDP);
910
+ this.subscribeForeignStates(faultReportingDP);
792
911
 
793
- const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, adapterID);
794
- batteryHealth = batteryData[0];
795
- batteryHealthRaw = batteryData[2];
796
- isBatteryDevice = batteryData[1];
912
+ const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
913
+ batteryHealth = batteryData[0];
914
+ batteryHealthRaw = batteryData[2];
915
+ batteryUnitRaw = batteryData[3];
916
+ isBatteryDevice = batteryData[1];
797
917
 
798
- if (isBatteryDevice) {
799
- lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
918
+ if (isBatteryDevice) {
919
+ lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
920
+ }
800
921
  }
801
- }
802
922
 
803
- /*=============================================
923
+ /*=============================================
804
924
  = Get last contact of device =
805
925
  =============================================*/
806
- let unreachDP = currDeviceString + this.selAdapter[i].reach;
807
- const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
808
- const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
809
- const timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
810
-
811
- let deviceUnreachState = await this.getInitValue(unreachDP);
812
- if (deviceUnreachState === undefined) {
813
- unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
814
- deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
815
- }
816
-
817
- // subscribe to states
818
- this.subscribeForeignStates(timeSelector);
819
- this.subscribeForeignStates(unreachDP);
820
- this.subscribeForeignStates(deviceStateSelectorDP);
821
- this.subscribeForeignStates(rssiPeerSelectorDP);
926
+ let unreachDP = currDeviceString + this.selAdapter[i].reach;
927
+ const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
928
+ const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
929
+ const timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
930
+
931
+ let deviceUnreachState = await this.getInitValue(unreachDP);
932
+ if (deviceUnreachState === undefined) {
933
+ unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
934
+ deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
935
+ }
822
936
 
823
- const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
824
- let deviceState;
825
- let lastContactString;
937
+ // subscribe to states
938
+ this.subscribeForeignStates(timeSelector);
939
+ this.subscribeForeignStates(unreachDP);
940
+ this.subscribeForeignStates(deviceStateSelectorDP);
941
+ this.subscribeForeignStates(rssiPeerSelectorDP);
942
+
943
+ const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
944
+ let deviceState;
945
+ let lastContactString;
946
+
947
+ if (onlineState) {
948
+ lastContactString = onlineState[0];
949
+ deviceState = onlineState[1];
950
+ linkQuality = onlineState[2];
951
+ }
826
952
 
827
- if (onlineState) {
828
- lastContactString = onlineState[0];
829
- deviceState = onlineState[1];
830
- linkQuality = onlineState[2];
831
- }
953
+ /*=============================================
954
+ = Get update data =
955
+ =============================================*/
956
+ const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
957
+ let isUpgradable;
832
958
 
833
- /*=============================================
834
- = Get update data =
835
- =============================================*/
836
- const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
837
- let isUpgradable;
959
+ if (this.config.checkSendDeviceUpgrade) {
960
+ const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
838
961
 
839
- if (this.config.checkSendDeviceUpgrade) {
840
- const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
962
+ if (deviceUpdateSelector !== undefined) {
963
+ if (deviceUpdateSelector) {
964
+ isUpgradable = true;
965
+ } else if (!deviceUpdateSelector) {
966
+ isUpgradable = false;
967
+ }
968
+ } else {
969
+ isUpgradable = ' - ';
970
+ }
841
971
 
842
- if (deviceUpdateSelector) {
843
- isUpgradable = true;
844
- } else if (!deviceUpdateSelector) {
845
- isUpgradable = false;
972
+ // subscribe to states
973
+ this.subscribeForeignStates(deviceUpdateDP);
846
974
  }
847
- // subscribe to states
848
- this.subscribeForeignStates(deviceUpdateDP);
849
- }
850
975
 
851
- /*=============================================
976
+ /*=============================================
852
977
  = Fill Raw Lists =
853
978
  =============================================*/
854
-
855
- /* Add only devices with battery in the rawlist */
856
- if (this.listOnlyBattery) {
857
- if (isBatteryDevice) {
858
- this.listAllDevicesRaw.push({
979
+ const setupList = () => {
980
+ this.listAllDevicesRaw.set(currDeviceString, {
859
981
  Path: id,
860
982
  instanceDeviceConnectionDP: instanceDeviceConnectionDP,
861
983
  instancedeviceConnected: instancedeviceConnected,
984
+ instance: instance,
862
985
  Device: deviceName,
863
986
  adapterID: adapterID,
864
987
  Adapter: adapter,
@@ -866,6 +989,7 @@ class DeviceWatcher extends utils.Adapter {
866
989
  isBatteryDevice: isBatteryDevice,
867
990
  Battery: batteryHealth,
868
991
  BatteryRaw: batteryHealthRaw,
992
+ BatteryUnitRaw: batteryUnitRaw,
869
993
  batteryDP: deviceBatteryStateDP,
870
994
  LowBat: lowBatIndicator,
871
995
  LowBatDP: isLowBatDP,
@@ -873,6 +997,7 @@ class DeviceWatcher extends utils.Adapter {
873
997
  faultReportDP: faultReportingDP,
874
998
  SignalStrengthDP: deviceQualityDP,
875
999
  SignalStrength: linkQuality,
1000
+ SignalStrengthRaw: linkQualityRaw,
876
1001
  UnreachState: deviceUnreachState,
877
1002
  UnreachDP: unreachDP,
878
1003
  DeviceStateSelectorDP: deviceStateSelectorDP,
@@ -882,38 +1007,20 @@ class DeviceWatcher extends utils.Adapter {
882
1007
  UpdateDP: deviceUpdateDP,
883
1008
  Upgradable: isUpgradable,
884
1009
  });
1010
+ };
1011
+
1012
+ if (!this.configListOnlyBattery) {
1013
+ // Add all devices
1014
+ setupList();
1015
+ } else {
1016
+ // Add only devices with battery in the rawlist
1017
+ if (!isBatteryDevice) continue;
1018
+ setupList();
885
1019
  }
886
- } else {
887
- /* Add all devices */
888
- this.listAllDevicesRaw.push({
889
- Path: id,
890
- instanceDeviceConnectionDP: instanceDeviceConnectionDP,
891
- instancedeviceConnected: instancedeviceConnected,
892
- Device: deviceName,
893
- adapterID: adapterID,
894
- Adapter: adapter,
895
- timeSelector: timeSelector,
896
- isBatteryDevice: isBatteryDevice,
897
- Battery: batteryHealth,
898
- BatteryRaw: batteryHealthRaw,
899
- batteryDP: deviceBatteryStateDP,
900
- LowBat: lowBatIndicator,
901
- LowBatDP: isLowBatDP,
902
- faultReport: faultReportingState,
903
- faultReportDP: faultReportingDP,
904
- SignalStrengthDP: deviceQualityDP,
905
- SignalStrength: linkQuality,
906
- UnreachState: deviceUnreachState,
907
- UnreachDP: unreachDP,
908
- DeviceStateSelectorDP: deviceStateSelectorDP,
909
- rssiPeerSelectorDP: rssiPeerSelectorDP,
910
- LastContact: lastContactString,
911
- Status: deviceState,
912
- UpdateDP: deviceUpdateDP,
913
- Upgradable: isUpgradable,
914
- });
915
- }
916
- } // <-- end of loop
1020
+ } // <-- end of loop
1021
+ } catch (error) {
1022
+ this.errorReporting('[createData - create data of devices]', error);
1023
+ }
917
1024
  } // <-- end of createData
918
1025
 
919
1026
  /*=============================================
@@ -1015,6 +1122,7 @@ class DeviceWatcher extends utils.Adapter {
1015
1122
  */
1016
1123
  async calculateSignalStrength(deviceQualityState, adapterID) {
1017
1124
  let linkQuality;
1125
+ let linkQualityRaw;
1018
1126
  let mqttNukiValue;
1019
1127
 
1020
1128
  if (deviceQualityState != null) {
@@ -1028,6 +1136,7 @@ class DeviceWatcher extends utils.Adapter {
1028
1136
  case 'sonoff':
1029
1137
  case 'smartgarden':
1030
1138
  linkQuality = deviceQualityState.val + '%'; // If quality state is already an percent value
1139
+ linkQualityRaw = deviceQualityState.val;
1031
1140
  break;
1032
1141
  case 'lupusec':
1033
1142
  linkQuality = deviceQualityState.val;
@@ -1039,9 +1148,12 @@ class DeviceWatcher extends utils.Adapter {
1039
1148
  linkQuality = ' - ';
1040
1149
  } else if (deviceQualityState.val < 0) {
1041
1150
  linkQuality = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100) + '%';
1151
+ linkQualityRaw = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100);
1152
+
1042
1153
  // If Quality State is an value between 0-255 (zigbee) calculate in percent:
1043
1154
  } else if (deviceQualityState.val >= 0) {
1044
1155
  linkQuality = parseFloat(((100 / 255) * deviceQualityState.val).toFixed(0)) + '%';
1156
+ linkQualityRaw = parseFloat(((100 / 255) * deviceQualityState.val).toFixed(0));
1045
1157
  }
1046
1158
  break;
1047
1159
  }
@@ -1064,7 +1176,7 @@ class DeviceWatcher extends utils.Adapter {
1064
1176
  linkQuality = deviceQualityState.val;
1065
1177
  } else if (mqttNukiValue < 0) {
1066
1178
  linkQuality = Math.min(Math.max(2 * (mqttNukiValue + 100), 0), 100) + '%';
1067
- // If Quality State is an value between 0-255 (zigbee) calculate in percent:
1179
+ linkQualityRaw = Math.min(Math.max(2 * (mqttNukiValue + 100), 0), 100);
1068
1180
  }
1069
1181
  }
1070
1182
  break;
@@ -1072,24 +1184,33 @@ class DeviceWatcher extends utils.Adapter {
1072
1184
  } else {
1073
1185
  linkQuality = ' - ';
1074
1186
  }
1075
- return linkQuality;
1187
+ return [linkQuality, linkQualityRaw];
1076
1188
  }
1077
1189
 
1078
1190
  /**
1079
1191
  * get battery data
1080
1192
  * @param {object} deviceBatteryState - State value
1081
1193
  * @param {object} deviceLowBatState - State value
1194
+ * @param {object} faultReportingState - State value
1082
1195
  * @param {object} adapterID - adapter name
1083
1196
  */
1084
- async getBatteryData(deviceBatteryState, deviceLowBatState, adapterID) {
1197
+ async getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID) {
1085
1198
  let batteryHealthRaw;
1199
+ let batteryHealthUnitRaw;
1086
1200
  let batteryHealth;
1087
1201
  let isBatteryDevice;
1088
1202
 
1089
1203
  switch (adapterID) {
1090
1204
  case 'hmrpc':
1091
1205
  if (deviceBatteryState === undefined) {
1092
- if (deviceLowBatState !== undefined) {
1206
+ if (faultReportingState !== undefined) {
1207
+ if (faultReportingState !== 6) {
1208
+ batteryHealth = 'ok';
1209
+ } else {
1210
+ batteryHealth = 'low';
1211
+ }
1212
+ isBatteryDevice = true;
1213
+ } else if (deviceLowBatState !== undefined) {
1093
1214
  if (deviceLowBatState !== 1) {
1094
1215
  batteryHealth = 'ok';
1095
1216
  } else {
@@ -1105,6 +1226,7 @@ class DeviceWatcher extends utils.Adapter {
1105
1226
  } else {
1106
1227
  batteryHealth = deviceBatteryState + 'V';
1107
1228
  batteryHealthRaw = deviceBatteryState;
1229
+ batteryHealthUnitRaw = 'V';
1108
1230
  isBatteryDevice = true;
1109
1231
  }
1110
1232
  }
@@ -1124,12 +1246,13 @@ class DeviceWatcher extends utils.Adapter {
1124
1246
  } else {
1125
1247
  batteryHealth = deviceBatteryState + '%';
1126
1248
  batteryHealthRaw = deviceBatteryState;
1249
+ batteryHealthUnitRaw = '%';
1127
1250
  isBatteryDevice = true;
1128
1251
  }
1129
1252
  break;
1130
1253
  }
1131
1254
 
1132
- return [batteryHealth, isBatteryDevice, batteryHealthRaw];
1255
+ return [batteryHealth, isBatteryDevice, batteryHealthRaw, batteryHealthUnitRaw];
1133
1256
  }
1134
1257
 
1135
1258
  /**
@@ -1187,7 +1310,7 @@ class DeviceWatcher extends utils.Adapter {
1187
1310
  * @param {object} selector - Selector
1188
1311
  */
1189
1312
  async getLastContact(selector) {
1190
- const lastContact = await this.getTimestamp(selector);
1313
+ const lastContact = this.getTimestamp(selector);
1191
1314
  let lastContactString;
1192
1315
 
1193
1316
  lastContactString = this.formatDate(new Date(selector), 'hh:mm') + ' Uhr';
@@ -1220,8 +1343,8 @@ class DeviceWatcher extends utils.Adapter {
1220
1343
  const deviceUnreachSelector = await this.getForeignStateAsync(unreachDP);
1221
1344
  const deviceStateSelector = await this.getForeignStateAsync(deviceStateSelectorDP); // for hmrpc devices
1222
1345
  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);
1346
+ const lastContact = this.getTimestamp(deviceTimeSelector.ts);
1347
+ const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? this.getTimestamp(deviceUnreachSelector.lc) : this.getTimestamp(timeSelector.ts);
1225
1348
  // If there is no contact since user sets minutes add device in offline list
1226
1349
  // calculate to days after 48 hours
1227
1350
  switch (unreachDP) {
@@ -1273,6 +1396,16 @@ class DeviceWatcher extends utils.Adapter {
1273
1396
  linkQuality = '0%'; // set linkQuality to nothing
1274
1397
  }
1275
1398
  break;
1399
+ case 'proxmox':
1400
+ if (this.configMaxMinutes[adapterID] <= 0) {
1401
+ if (deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1402
+ deviceState = 'Offline'; //set online state to offline
1403
+ }
1404
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1405
+ deviceState = 'Offline'; //set online state to offline
1406
+ linkQuality = '0%'; // set linkQuality to nothing
1407
+ }
1408
+ break;
1276
1409
  case 'hmiP':
1277
1410
  case 'maxcube':
1278
1411
  if (this.configMaxMinutes[adapterID] <= 0) {
@@ -1374,26 +1507,26 @@ class DeviceWatcher extends utils.Adapter {
1374
1507
  * when was last contact of device
1375
1508
  */
1376
1509
  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);
1510
+ for (const [device, deviceData] of this.listAllDevicesRaw) {
1511
+ if (deviceData.instancedeviceConnected !== false) {
1512
+ const oldContactState = deviceData.Status;
1513
+ deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
1381
1514
  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,
1515
+ deviceData.timeSelector,
1516
+ deviceData.adapterID,
1517
+ deviceData.UnreachDP,
1518
+ deviceData.SignalStrength,
1519
+ deviceData.UnreachState,
1520
+ deviceData.DeviceStateSelectorDP,
1521
+ deviceData.rssiPeerSelectorDP,
1389
1522
  );
1390
1523
  if (contactData !== undefined) {
1391
- device.LastContact = contactData[0];
1392
- device.Status = contactData[1];
1393
- device.linkQuality = contactData[2];
1524
+ deviceData.LastContact = contactData[0];
1525
+ deviceData.Status = contactData[1];
1526
+ deviceData.linkQuality = contactData[2];
1394
1527
  }
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);
1528
+ if (this.config.checkSendOfflineMsg && oldContactState !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
1529
+ await this.sendStateNotifications('onlineStateDevice', device);
1397
1530
  }
1398
1531
  }
1399
1532
  }
@@ -1406,6 +1539,7 @@ class DeviceWatcher extends utils.Adapter {
1406
1539
  this.linkQualityDevices = [];
1407
1540
  this.batteryPowered = [];
1408
1541
  this.batteryLowPowered = [];
1542
+ this.listAllDevicesUserRaw = [];
1409
1543
  this.listAllDevices = [];
1410
1544
  this.offlineDevices = [];
1411
1545
  this.batteryLowPoweredRaw = [];
@@ -1417,47 +1551,45 @@ class DeviceWatcher extends utils.Adapter {
1417
1551
  adptName = '';
1418
1552
  }
1419
1553
 
1420
- for (const device of this.listAllDevicesRaw) {
1554
+ for (const deviceData of this.listAllDevicesRaw.values()) {
1421
1555
  /*---------- fill raw lists ----------*/
1422
1556
  // low bat list
1423
- if (device.LowBat && device.Status !== 'Offline') {
1557
+ if (deviceData.LowBat && deviceData.Status !== 'Offline') {
1424
1558
  this.batteryLowPoweredRaw.push({
1425
- Path: device.Path,
1426
- Device: device.Device,
1427
- Adapter: device.Adapter,
1428
- Battery: device.Battery,
1559
+ Path: deviceData.Path,
1560
+ Device: deviceData.Device,
1561
+ Adapter: deviceData.Adapter,
1562
+ Battery: deviceData.Battery,
1429
1563
  });
1430
1564
  }
1431
1565
  // offline raw list
1432
- if (device.Status === 'Offline') {
1566
+ if (deviceData.Status === 'Offline') {
1433
1567
  this.offlineDevicesRaw.push({
1434
- Path: device.Path,
1435
- Device: device.Device,
1436
- Adapter: device.Adapter,
1437
- LastContact: device.LastContact,
1568
+ Path: deviceData.Path,
1569
+ Device: deviceData.Device,
1570
+ Adapter: deviceData.Adapter,
1571
+ LastContact: deviceData.LastContact,
1438
1572
  });
1439
1573
  }
1440
1574
 
1441
1575
  // upgradable raw list
1442
- if (device.Upgradable) {
1576
+ if (deviceData.Upgradable === true) {
1443
1577
  this.upgradableDevicesRaw.push({
1444
- Path: device.Path,
1445
- Device: device.Device,
1446
- Adapter: device.Adapter,
1578
+ Path: deviceData.Path,
1579
+ Device: deviceData.Device,
1580
+ Adapter: deviceData.Adapter,
1447
1581
  });
1448
1582
  }
1449
1583
 
1450
- if (adptName === '' && !this.blacklistLists.includes(device.Path)) {
1451
- await this.theLists(device);
1584
+ if (adptName === '' && !this.blacklistLists.includes(deviceData.Path)) {
1585
+ await this.theLists(deviceData);
1452
1586
  }
1453
1587
 
1454
1588
  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
- }
1589
+ if (!deviceData.adapterID.includes(adptName)) continue;
1590
+ /*---------- fill user lists for each adapter ----------*/
1591
+ if (this.blacklistAdapterLists.includes(deviceData.Path)) continue;
1592
+ await this.theLists(deviceData);
1461
1593
  }
1462
1594
  }
1463
1595
  await this.countDevices();
@@ -1468,6 +1600,24 @@ class DeviceWatcher extends utils.Adapter {
1468
1600
  * @param {object} device
1469
1601
  */
1470
1602
  async theLists(device) {
1603
+ // Raw List with all devices for user
1604
+ this.listAllDevicesUserRaw.push({
1605
+ Device: device.Device,
1606
+ Adapter: device.Adapter,
1607
+ Instance: device.instance,
1608
+ 'Instance connected': device.instancedeviceConnected,
1609
+ isBatteryDevice: device.isBatteryDevice,
1610
+ Battery: device.Battery,
1611
+ BatteryRaw: device.BatteryRaw,
1612
+ BatteryUnitRaw: device.BatteryUnitRaw,
1613
+ isLowBat: device.LowBat,
1614
+ 'Signal strength': device.SignalStrength,
1615
+ 'Signal strength Raw': device.SignalStrengthRaw,
1616
+ 'Last contact': device.LastContact,
1617
+ 'Update Available': device.Upgradable,
1618
+ Status: device.Status,
1619
+ });
1620
+
1471
1621
  // List with all devices
1472
1622
  this.listAllDevices.push({
1473
1623
  Device: device.Device,
@@ -1516,7 +1666,7 @@ class DeviceWatcher extends utils.Adapter {
1516
1666
  }
1517
1667
 
1518
1668
  // Device update List
1519
- if (device.Upgradable) {
1669
+ if (device.Upgradable === true) {
1520
1670
  this.upgradableList.push({
1521
1671
  Device: device.Device,
1522
1672
  Adapter: device.Adapter,
@@ -1547,47 +1697,6 @@ class DeviceWatcher extends utils.Adapter {
1547
1697
  this.upgradableDevicesCount = this.upgradableList.length;
1548
1698
  }
1549
1699
 
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
1700
  /**
1592
1701
  * @param {string} [adptName] - Adaptername
1593
1702
  */
@@ -1606,26 +1715,58 @@ class DeviceWatcher extends utils.Adapter {
1606
1715
  }
1607
1716
 
1608
1717
  // Write Datapoints for counts
1609
- await this.setStateAsync(`devices.${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1610
- await this.setStateAsync(`devices.${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1611
- await this.setStateAsync(`devices.${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1612
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1613
- await this.setStateAsync(`devices.${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1718
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1719
+ await this.setStateChangedAsync(`devices.${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1720
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1721
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1722
+ await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1614
1723
 
1615
1724
  // List all devices
1616
1725
  if (this.deviceCounter === 0) {
1617
1726
  // if no device is count, write the JSON List with default value
1618
- this.listAllDevices = [{ Device: '--none--', Adapter: '', Battery: '', 'Last contact': '', 'Signal strength': '' }];
1727
+ this.listAllDevices = [
1728
+ {
1729
+ Device: '--none--',
1730
+ Adapter: '',
1731
+ Battery: '',
1732
+ 'Signal strength': '',
1733
+ 'Last contact': '',
1734
+ Status: '',
1735
+ },
1736
+ ];
1737
+ this.listAllDevicesUserRaw = [
1738
+ {
1739
+ Device: '--none--',
1740
+ Adapter: '',
1741
+ Instance: '',
1742
+ 'Instance connected': '',
1743
+ isBatteryDevice: '',
1744
+ Battery: '',
1745
+ BatteryRaw: '',
1746
+ isLowBat: '',
1747
+ 'Signal strength': '',
1748
+ 'Last contact': '',
1749
+ UpdateAvailable: '',
1750
+ Status: '',
1751
+ },
1752
+ ];
1619
1753
  }
1620
- await this.setStateAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1754
+ await this.setStateChangedAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1755
+ await this.setStateChangedAsync(`devices.${dpSubFolder}listAllRawJSON`, { val: JSON.stringify(this.listAllDevicesUserRaw), ack: true });
1621
1756
 
1622
1757
  // List link quality
1623
1758
  if (this.linkQualityCount === 0) {
1624
1759
  // if no device is count, write the JSON List with default value
1625
- this.linkQualityDevices = [{ Device: '--none--', Adapter: '', 'Signal strength': '' }];
1760
+ this.linkQualityDevices = [
1761
+ {
1762
+ Device: '--none--',
1763
+ Adapter: '',
1764
+ 'Signal strength': '',
1765
+ },
1766
+ ];
1626
1767
  }
1627
1768
  //write JSON list
1628
- await this.setStateAsync(`devices.${dpSubFolder}linkQualityList`, {
1769
+ await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityList`, {
1629
1770
  val: JSON.stringify(this.linkQualityDevices),
1630
1771
  ack: true,
1631
1772
  });
@@ -1633,10 +1774,16 @@ class DeviceWatcher extends utils.Adapter {
1633
1774
  // List offline devices
1634
1775
  if (this.offlineDevicesCount === 0) {
1635
1776
  // if no device is count, write the JSON List with default value
1636
- this.offlineDevices = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1777
+ this.offlineDevices = [
1778
+ {
1779
+ Device: '--none--',
1780
+ Adapter: '',
1781
+ 'Last contact': '',
1782
+ },
1783
+ ];
1637
1784
  }
1638
1785
  //write JSON list
1639
- await this.setStateAsync(`devices.${dpSubFolder}offlineList`, {
1786
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineList`, {
1640
1787
  val: JSON.stringify(this.offlineDevices),
1641
1788
  ack: true,
1642
1789
  });
@@ -1644,10 +1791,16 @@ class DeviceWatcher extends utils.Adapter {
1644
1791
  // List updatable
1645
1792
  if (this.upgradableDevicesCount === 0) {
1646
1793
  // if no device is count, write the JSON List with default value
1647
- this.upgradableList = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1794
+ this.upgradableList = [
1795
+ {
1796
+ Device: '--none--',
1797
+ Adapter: '',
1798
+ 'Last contact': '',
1799
+ },
1800
+ ];
1648
1801
  }
1649
1802
  //write JSON list
1650
- await this.setStateAsync(`devices.${dpSubFolder}upgradableList`, {
1803
+ await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableList`, {
1651
1804
  val: JSON.stringify(this.upgradableList),
1652
1805
  ack: true,
1653
1806
  });
@@ -1658,7 +1811,7 @@ class DeviceWatcher extends utils.Adapter {
1658
1811
  this.batteryPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1659
1812
  }
1660
1813
  //write JSON list
1661
- await this.setStateAsync(`devices.${dpSubFolder}batteryList`, {
1814
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryList`, {
1662
1815
  val: JSON.stringify(this.batteryPowered),
1663
1816
  ack: true,
1664
1817
  });
@@ -1669,71 +1822,71 @@ class DeviceWatcher extends utils.Adapter {
1669
1822
  this.batteryLowPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1670
1823
  }
1671
1824
  //write JSON list
1672
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryList`, {
1825
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryList`, {
1673
1826
  val: JSON.stringify(this.batteryLowPowered),
1674
1827
  ack: true,
1675
1828
  });
1676
1829
 
1677
1830
  // set booleans datapoints
1678
1831
  if (this.offlineDevicesCount === 0) {
1679
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1832
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1680
1833
  val: false,
1681
1834
  ack: true,
1682
1835
  });
1683
1836
  } else {
1684
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1837
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1685
1838
  val: true,
1686
1839
  ack: true,
1687
1840
  });
1688
1841
  }
1689
1842
 
1690
1843
  if (this.lowBatteryPoweredCount === 0) {
1691
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1844
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1692
1845
  val: false,
1693
1846
  ack: true,
1694
1847
  });
1695
1848
  } else {
1696
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1849
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1697
1850
  val: true,
1698
1851
  ack: true,
1699
1852
  });
1700
1853
  }
1701
1854
 
1702
1855
  if (this.upgradableDevicesCount === 0) {
1703
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1856
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1704
1857
  val: false,
1705
1858
  ack: true,
1706
1859
  });
1707
1860
  } else {
1708
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1861
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1709
1862
  val: true,
1710
1863
  ack: true,
1711
1864
  });
1712
1865
  }
1713
1866
 
1714
1867
  //write HTML list
1715
- if (this.createHtmlList) {
1716
- await this.setStateAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1717
- val: await this.creatLinkQualityListHTML(this.linkQualityDevices, this.linkQualityCount),
1868
+ if (this.configCreateHtmlList) {
1869
+ await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1870
+ val: await this.createListHTML('linkQualityList', this.linkQualityDevices, this.linkQualityCount, null),
1718
1871
  ack: true,
1719
1872
  });
1720
- await this.setStateAsync(`devices.${dpSubFolder}offlineListHTML`, {
1721
- val: await this.createOfflineListHTML(this.offlineDevices, this.offlineDevicesCount),
1873
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineListHTML`, {
1874
+ val: await this.createListHTML('offlineList', this.offlineDevices, this.offlineDevicesCount, null),
1722
1875
  ack: true,
1723
1876
  });
1724
- await this.setStateAsync(`devices.${dpSubFolder}batteryListHTML`, {
1725
- val: await this.createBatteryListHTML(this.batteryPowered, this.batteryPoweredCount, false),
1877
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryListHTML`, {
1878
+ val: await this.createListHTML('batteryList', this.batteryPowered, this.batteryPoweredCount, false),
1726
1879
  ack: true,
1727
1880
  });
1728
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1729
- val: await this.createBatteryListHTML(this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1881
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1882
+ val: await this.createListHTML('batteryList', this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1730
1883
  ack: true,
1731
1884
  });
1732
1885
  }
1733
1886
 
1734
1887
  // create timestamp of last run
1735
1888
  const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
1736
- await this.setStateAsync('lastCheck', lastCheck, true);
1889
+ await this.setStateChangedAsync('lastCheck', lastCheck, true);
1737
1890
  } catch (error) {
1738
1891
  this.errorReporting('[writeDatapoints]', error);
1739
1892
  }
@@ -1741,13 +1894,25 @@ class DeviceWatcher extends utils.Adapter {
1741
1894
  } //<--End of writing Datapoints
1742
1895
 
1743
1896
  /**
1744
- * get Instances
1897
+ * get all Instances at start
1898
+ */
1899
+ async getAllInstanceData() {
1900
+ try {
1901
+ const allInstances = `system.adapter.*`;
1902
+ await this.getInstanceData(allInstances);
1903
+ } catch (error) {
1904
+ this.errorReporting('[getInstance]', error);
1905
+ }
1906
+ }
1907
+
1908
+ /**
1909
+ * get instance data
1910
+ *@param {string} instanceObject
1745
1911
  */
1746
- async getInstanceData() {
1912
+ async getInstanceData(instanceObject) {
1747
1913
  try {
1748
- await this.createDPsForInstances();
1914
+ const instanceAliveDP = await this.getForeignStatesAsync(`${instanceObject}.alive`);
1749
1915
 
1750
- const instanceAliveDP = await this.getForeignStatesAsync(`system.adapter.*.alive`);
1751
1916
  for (const [id] of Object.entries(instanceAliveDP)) {
1752
1917
  if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
1753
1918
 
@@ -1771,6 +1936,7 @@ class DeviceWatcher extends utils.Adapter {
1771
1936
  const instanceObjectPath = `system.adapter.${instanceName}`;
1772
1937
  let adapterName;
1773
1938
  let adapterVersion;
1939
+ let adapterAvailableUpdate = '';
1774
1940
  let instanceMode;
1775
1941
  let scheduleTime = 'N/A';
1776
1942
  const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
@@ -1785,20 +1951,30 @@ class DeviceWatcher extends utils.Adapter {
1785
1951
  }
1786
1952
  }
1787
1953
 
1954
+ await this.getAdapterUpdateData(`admin.*.info.updatesJson`);
1955
+
1956
+ if (this.adapterUpdatesJsonRaw.has(adapterName)) {
1957
+ for (const adapter of this.adapterUpdatesJsonRaw.values()) {
1958
+ adapterAvailableUpdate = adapter.newVersion;
1959
+ }
1960
+ } else {
1961
+ adapterAvailableUpdate = ' - ';
1962
+ }
1963
+
1788
1964
  //const adapterVersionVal = await this.getInitValue(adapterVersionDP);
1789
- const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceAliveDP[id].val, instanceConnectedHostVal, instanceConnectedDeviceVal);
1965
+ const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceConnectedHostDP, instanceConnectedDeviceDP);
1790
1966
  const isAlive = instanceStatusRaw[1];
1791
1967
  const instanceStatus = instanceStatusRaw[0];
1792
1968
  const isHealthy = instanceStatusRaw[2];
1793
1969
 
1794
1970
  //subscribe to statechanges
1795
- this.subscribeForeignStatesAsync(id);
1796
- this.subscribeForeignStatesAsync(instanceConnectedHostDP);
1797
- this.subscribeForeignStatesAsync(instanceConnectedDeviceDP);
1798
- //this.subscribeForeignObjectsAsync(instanceObjectPath);
1971
+ this.subscribeForeignStates(id);
1972
+ this.subscribeForeignStates(instanceConnectedHostDP);
1973
+ this.subscribeForeignStates(instanceConnectedDeviceDP);
1974
+ this.subscribeForeignObjects(`system.adapter.*`);
1799
1975
 
1800
1976
  // create raw list
1801
- this.listInstanceRaw.push({
1977
+ this.listInstanceRaw.set(instanceObjectPath, {
1802
1978
  Adapter: adapterName,
1803
1979
  InstanceName: instanceName,
1804
1980
  instanceObjectPath: instanceObjectPath,
@@ -1806,6 +1982,7 @@ class DeviceWatcher extends utils.Adapter {
1806
1982
  instanceMode: instanceMode,
1807
1983
  schedule: scheduleTime,
1808
1984
  adapterVersion: adapterVersion,
1985
+ updateAvailable: adapterAvailableUpdate,
1809
1986
  isAlive: isAlive,
1810
1987
  isHealthy: isHealthy,
1811
1988
  connectedHostPath: instanceConnectedHostDP,
@@ -1818,7 +1995,7 @@ class DeviceWatcher extends utils.Adapter {
1818
1995
  await this.createInstanceList();
1819
1996
  await this.writeInstanceDPs();
1820
1997
  } catch (error) {
1821
- this.errorReporting('[getInstance]', error);
1998
+ this.errorReporting('[getInstanceData]', error);
1822
1999
  }
1823
2000
  }
1824
2001
 
@@ -1835,28 +2012,29 @@ class DeviceWatcher extends utils.Adapter {
1835
2012
 
1836
2013
  /**
1837
2014
  * set status for instance
1838
- * @param {object} instanceMode
1839
- * @param {object} scheduleTime
2015
+ * @param {string} instanceMode
2016
+ * @param {string} scheduleTime
1840
2017
  * @param {object} instanceAlivePath
1841
- * @param {object} isAliveVal
1842
- * @param {object} connectedHostVal
1843
- * @param {object} connectedDeviceVal
2018
+ * @param {string} hostConnectedPath
2019
+ * @param {string} isDeviceConnctedPath
1844
2020
  */
1845
- async setInstanceStatus(instanceMode, scheduleTime, instanceAlivePath, isAliveVal, connectedHostVal, connectedDeviceVal) {
1846
- let instanceStatusString = 'not enabled';
2021
+ async setInstanceStatus(instanceMode, scheduleTime, instanceAlivePath, hostConnectedPath, isDeviceConnctedPath) {
2022
+ const isAliveSchedule = await this.getForeignStateAsync(instanceAlivePath);
2023
+ let isHostConnected = await this.getInitValue(hostConnectedPath);
2024
+ let isAlive = await this.getInitValue(instanceAlivePath);
2025
+ let isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
2026
+ let instanceStatusString = 'Instance deactivated';
1847
2027
  let lastUpdate;
1848
2028
  let lastCronRun;
1849
2029
  let diff;
1850
2030
  let previousCronRun = null;
1851
- let isAlive = false;
1852
2031
  let isHealthy = false;
1853
- let dpValue;
2032
+
1854
2033
  switch (instanceMode) {
1855
2034
  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
2035
+ if (isAliveSchedule) {
2036
+ lastUpdate = Math.round((Date.now() - isAliveSchedule.lc) / 1000); // Last state change in seconds
2037
+ previousCronRun = this.getPreviousCronRun(scheduleTime); // When was the last cron run
1860
2038
  if (previousCronRun) {
1861
2039
  lastCronRun = Math.round(previousCronRun / 1000); // change distance to last run in seconds
1862
2040
  diff = lastCronRun - lastUpdate;
@@ -1864,42 +2042,43 @@ class DeviceWatcher extends utils.Adapter {
1864
2042
  // if 5 minutes difference exceeded, instance is not alive
1865
2043
  isAlive = true;
1866
2044
  isHealthy = true;
1867
- instanceStatusString = 'Instance okay';
2045
+ instanceStatusString = 'Instanz okay';
1868
2046
  }
1869
2047
  }
1870
2048
  }
1871
2049
  break;
1872
2050
  case 'daemon':
1873
- if (!isAliveVal) return ['Instance deactivated', false, null]; // if instance is turned off
1874
-
2051
+ if (!isAlive) return ['Instanz deaktiviert', false, null]; // if instance is turned off
2052
+ if (isDeviceConnected === undefined) isDeviceConnected = true;
1875
2053
  // In case of (re)start, connection may take some time. We take 3 attempts.
1876
2054
  // Attempt 1/3 - immediately
1877
- if (connectedHostVal && connectedDeviceVal) {
1878
- isAlive = true;
2055
+ if (isHostConnected && isDeviceConnected) {
1879
2056
  isHealthy = true;
1880
- instanceStatusString = 'Instance okay';
2057
+ instanceStatusString = 'Instanz okay';
1881
2058
  } else {
1882
2059
  // Attempt 2/3 - after 10 seconds
1883
2060
  await this.wait(10000);
1884
- if (connectedHostVal && connectedDeviceVal) {
1885
- isAlive = true;
2061
+ isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
2062
+ isHostConnected = await this.getInitValue(hostConnectedPath);
2063
+
2064
+ if (isHostConnected && isDeviceConnected) {
1886
2065
  isHealthy = true;
1887
- instanceStatusString = 'Instance okay';
2066
+ instanceStatusString = 'Instanz okay';
1888
2067
  } else {
1889
2068
  // Attempt 3/3 - after 20 seconds in total
1890
2069
  await this.wait(10000);
1891
- if (connectedHostVal && connectedDeviceVal) {
1892
- isAlive = true;
2070
+ isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
2071
+ isHostConnected = await this.getInitValue(hostConnectedPath);
2072
+
2073
+ if (isHostConnected && isDeviceConnected) {
1893
2074
  isHealthy = true;
1894
- instanceStatusString = 'Instance okay';
2075
+ instanceStatusString = 'Instanz okay';
1895
2076
  } else {
1896
- if (!connectedDeviceVal) {
1897
- instanceStatusString = 'not connected to Device';
1898
- isAlive = true;
2077
+ if (!isDeviceConnected) {
2078
+ instanceStatusString = 'Nicht verbunden mit Gerät oder Dienst';
1899
2079
  isHealthy = false;
1900
- } else if (!connectedHostVal) {
1901
- instanceStatusString = 'not connected to host';
1902
- isAlive = true;
2080
+ } else if (!isHostConnected) {
2081
+ instanceStatusString = 'Nicht verbunden mit Host';
1903
2082
  isHealthy = false;
1904
2083
  }
1905
2084
  }
@@ -1911,27 +2090,44 @@ class DeviceWatcher extends utils.Adapter {
1911
2090
  return [instanceStatusString, isAlive, isHealthy];
1912
2091
  }
1913
2092
 
1914
- async createAdapterUpdateData() {
1915
- const adapterUpdateListDP = `admin.*.info.updatesJson`;
2093
+ /**
2094
+ * create adapter update data
2095
+ */
2096
+ async createAdapterUpdateData() {
2097
+ const adapterUpdateListDP = `admin.*.info.updatesJson`;
2098
+
2099
+ // subscribe to datapoint
2100
+ this.subscribeForeignStates(adapterUpdateListDP);
2101
+
2102
+ await this.getAdapterUpdateData(adapterUpdateListDP);
2103
+
2104
+ await this.createAdapterUpdateList();
2105
+ }
2106
+
2107
+ /**
2108
+ * create adapter update raw lists
2109
+ * @param {string} adapterUpdateListDP
2110
+ */
2111
+ async getAdapterUpdateData(adapterUpdateListDP) {
2112
+ this.adapterUpdatesJsonRaw.clear();
1916
2113
  const adapterUpdatesListVal = await this.getForeignStatesAsync(adapterUpdateListDP);
1917
2114
 
1918
- // subscribe to datapoint
1919
- this.subscribeForeignStates(adapterUpdateListDP);
1920
2115
  let adapterJsonList;
2116
+ let adapterUpdatesJsonPath;
1921
2117
 
1922
2118
  for (const [id] of Object.entries(adapterUpdatesListVal)) {
1923
- adapterJsonList = await this.parseData(adapterUpdatesListVal[id].val);
2119
+ adapterJsonList = this.parseData(adapterUpdatesListVal[id].val);
2120
+ adapterUpdatesJsonPath = id;
1924
2121
  }
1925
2122
 
1926
2123
  for (const [id] of Object.entries(adapterJsonList)) {
1927
- this.adapterUpdatesJsonRaw.push({
1928
- Path: adapterUpdateListDP,
1929
- Adapter: this.capitalize(id),
2124
+ this.adapterUpdatesJsonRaw.set(this.capitalize(id), {
2125
+ Path: adapterUpdatesJsonPath,
1930
2126
  newVersion: adapterJsonList[id].availableVersion,
1931
2127
  oldVersion: adapterJsonList[id].installedVersion,
1932
2128
  });
1933
2129
  }
1934
- await this.createAdapterUpdateList();
2130
+ return this.adapterUpdatesJsonRaw;
1935
2131
  }
1936
2132
 
1937
2133
  /**
@@ -1941,11 +2137,11 @@ class DeviceWatcher extends utils.Adapter {
1941
2137
  this.listAdapterUpdates = [];
1942
2138
  this.countAdapterUpdates = 0;
1943
2139
 
1944
- for (const adapter of this.adapterUpdatesJsonRaw) {
2140
+ for (const [adapter, updateData] of this.adapterUpdatesJsonRaw) {
1945
2141
  this.listAdapterUpdates.push({
1946
- Adapter: adapter.Adapter,
1947
- 'Available Version': adapter.newVersion,
1948
- 'Installed Version': adapter.oldVersion,
2142
+ Adapter: adapter,
2143
+ 'Available Version': updateData.newVersion,
2144
+ 'Installed Version': updateData.oldVersion,
1949
2145
  });
1950
2146
  }
1951
2147
  this.countAdapterUpdates = this.listAdapterUpdates.length;
@@ -1957,13 +2153,13 @@ class DeviceWatcher extends utils.Adapter {
1957
2153
  */
1958
2154
  async writeAdapterUpdatesDPs() {
1959
2155
  // Write Datapoints for counts
1960
- await this.setStateAsync(`adapterAndInstances.countAdapterUpdates`, { val: this.countAdapterUpdates, ack: true });
2156
+ await this.setStateChangedAsync(`adapterAndInstances.countAdapterUpdates`, { val: this.countAdapterUpdates, ack: true });
1961
2157
 
1962
2158
  // list deactivated instances
1963
2159
  if (this.countAdapterUpdates === 0) {
1964
2160
  this.listAdapterUpdates = [{ Adapter: '--none--', 'Available Version': '', 'Installed Version': '' }];
1965
2161
  }
1966
- await this.setStateAsync(`adapterAndInstances.listAdapterUpdates`, { val: JSON.stringify(this.listAdapterUpdates), ack: true });
2162
+ await this.setStateChangedAsync(`adapterAndInstances.listAdapterUpdates`, { val: JSON.stringify(this.listAdapterUpdates), ack: true });
1967
2163
  }
1968
2164
 
1969
2165
  /**
@@ -1975,7 +2171,7 @@ class DeviceWatcher extends utils.Adapter {
1975
2171
  this.listErrorInstanceRaw = [];
1976
2172
  this.listErrorInstance = [];
1977
2173
 
1978
- for (const instance of this.listInstanceRaw) {
2174
+ for (const instance of this.listInstanceRaw.values()) {
1979
2175
  // fill raw list
1980
2176
  if (instance.isAlive && !instance.isHealthy) {
1981
2177
  this.listErrorInstanceRaw.push({
@@ -1993,6 +2189,7 @@ class DeviceWatcher extends utils.Adapter {
1993
2189
  Mode: instance.instanceMode,
1994
2190
  Schedule: instance.schedule,
1995
2191
  Version: instance.adapterVersion,
2192
+ Updateable: instance.updateAvailable,
1996
2193
  Status: instance.status,
1997
2194
  });
1998
2195
  if (!instance.isAlive) {
@@ -2034,25 +2231,25 @@ class DeviceWatcher extends utils.Adapter {
2034
2231
  */
2035
2232
  async writeInstanceDPs() {
2036
2233
  // Write Datapoints for counts
2037
- await this.setStateAsync(`adapterAndInstances.countAllInstances`, { val: this.countAllInstances, ack: true });
2038
- await this.setStateAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2234
+ await this.setStateChangedAsync(`adapterAndInstances.countAllInstances`, { val: this.countAllInstances, ack: true });
2235
+ await this.setStateChangedAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2039
2236
 
2040
2237
  // List all instances
2041
- await this.setStateAsync(`adapterAndInstances.listAllInstances`, { val: JSON.stringify(this.listAllInstances), ack: true });
2238
+ await this.setStateChangedAsync(`adapterAndInstances.listAllInstances`, { val: JSON.stringify(this.listAllInstances), ack: true });
2042
2239
 
2043
2240
  // list deactivated instances
2044
2241
  if (this.countDeactivatedInstances === 0) {
2045
2242
  this.listDeactivatedInstances = [{ Instance: '--none--', Version: '', Status: '' }];
2046
2243
  }
2047
- await this.setStateAsync(`adapterAndInstances.listDeactivatedInstances`, { val: JSON.stringify(this.listDeactivatedInstances), ack: true });
2048
- await this.setStateAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2244
+ await this.setStateChangedAsync(`adapterAndInstances.listDeactivatedInstances`, { val: JSON.stringify(this.listDeactivatedInstances), ack: true });
2245
+ await this.setStateChangedAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2049
2246
 
2050
2247
  // list error instances
2051
2248
  if (this.countErrorInstance === 0) {
2052
2249
  this.listErrorInstance = [{ Instance: '--none--', Mode: '', Status: '' }];
2053
2250
  }
2054
- await this.setStateAsync(`adapterAndInstances.listInstancesError`, { val: JSON.stringify(this.listErrorInstance), ack: true });
2055
- await this.setStateAsync(`adapterAndInstances.countInstancesError`, { val: this.countErrorInstance, ack: true });
2251
+ await this.setStateChangedAsync(`adapterAndInstances.listInstancesError`, { val: JSON.stringify(this.listErrorInstance), ack: true });
2252
+ await this.setStateChangedAsync(`adapterAndInstances.countInstancesError`, { val: this.countErrorInstance, ack: true });
2056
2253
  }
2057
2254
 
2058
2255
  /**
@@ -2268,6 +2465,21 @@ class DeviceWatcher extends utils.Adapter {
2268
2465
  });
2269
2466
  }
2270
2467
 
2468
+ /**
2469
+ * delete Datapoints for Instances
2470
+ */
2471
+ async deleteDPsForInstances() {
2472
+ await this.delObjectAsync(`adapterAndInstances`);
2473
+ await this.delObjectAsync(`adapterAndInstances.listAllInstances`);
2474
+ await this.delObjectAsync(`adapterAndInstances.countAllInstances`);
2475
+ await this.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
2476
+ await this.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
2477
+ await this.delObjectAsync(`adapterAndInstances.listInstancesError`);
2478
+ await this.delObjectAsync(`adapterAndInstances.countInstancesError`);
2479
+ await this.delObjectAsync(`adapterAndInstances.listAdapterUpdates`);
2480
+ await this.delObjectAsync(`adapterAndInstances.countAdapterUpdates`);
2481
+ }
2482
+
2271
2483
  /*=============================================
2272
2484
  = functions to send notifications =
2273
2485
  =============================================*/
@@ -2337,6 +2549,25 @@ class DeviceWatcher extends utils.Adapter {
2337
2549
  this.errorReporting('[sendNotification Whatsapp]', error);
2338
2550
  }
2339
2551
 
2552
+ // Signal
2553
+ try {
2554
+ if (this.config.instanceSignal) {
2555
+ //first check if instance is living
2556
+ const signalAliveState = await this.getInitValue('system.adapter.' + this.config.instanceSignal + '.alive');
2557
+
2558
+ if (!signalAliveState) {
2559
+ this.log.warn('Signal instance is not running. Message could not be sent. Please check your instance configuration.');
2560
+ } else {
2561
+ await this.sendToAsync(this.config.instanceSignal, 'send', {
2562
+ text: text,
2563
+ phone: this.config.phoneSignal,
2564
+ });
2565
+ }
2566
+ }
2567
+ } catch (error) {
2568
+ this.errorReporting('[sendNotification Signal]', error);
2569
+ }
2570
+
2340
2571
  // Email
2341
2572
  try {
2342
2573
  if (this.config.instanceEmail) {
@@ -2418,539 +2649,378 @@ class DeviceWatcher extends utils.Adapter {
2418
2649
  }
2419
2650
  } // <-- End of sendNotification function
2420
2651
 
2421
- /*---------- Battery notifications ----------*/
2652
+ /*---------- Notifications ----------*/
2422
2653
  /**
2423
- * send shedule message for low battery devices
2654
+ * Notifications on state changes
2655
+ * @param {string} type
2656
+ * @param {object} id
2424
2657
  */
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
- }
2658
+ async sendStateNotifications(type, id) {
2659
+ if (isUnloaded) return;
2660
+ let objectData;
2661
+ let list = '';
2662
+ let message = '';
2663
+ const setMessage = async (message) => {
2664
+ this.log.info(`${message}`);
2665
+ await this.setStateAsync('lastNotification', `${message}`, true);
2666
+ await this.sendNotification(`${message}`);
2667
+ return (message = '');
2668
+ };
2669
+ switch (type) {
2670
+ case 'lowBatDevice':
2671
+ objectData = this.listAllDevicesRaw.get(id);
2672
+ if (!this.config.showAdapterNameinMsg) {
2673
+ message = `Gerät mit geringer Batterie erkannt: \n${objectData.Device} (${objectData.Battery})`;
2674
+ } else {
2675
+ message = `Gerät mit geringer Batterie erkannt: \n${objectData.Adapter}: ${objectData.Device} (${objectData.Battery})`;
2676
+ }
2677
+ setMessage(message);
2678
+ break;
2679
+ case 'onlineStateDevice':
2680
+ objectData = this.listAllDevicesRaw.get(id);
2681
+ switch (objectData.Status) {
2682
+ case 'Online':
2683
+ if (!this.config.showAdapterNameinMsg) {
2684
+ message = `Folgendes Gerät ist wieder erreichbar: \n${objectData.Device} (${objectData.LastContact})`;
2685
+ } else {
2686
+ message = `Folgendes Gerät ist wieder erreichbar: \n${objectData.Adapter}: ${objectData.Device} (${objectData.LastContact})`;
2461
2687
  }
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);
2688
+ break;
2689
+ case 'Offline':
2690
+ if (!this.config.showAdapterNameinMsg) {
2691
+ message = `Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n${objectData.Device} (${objectData.LastContact})`;
2692
+ } else {
2693
+ message = `Folgendes Gerät ist seit einiger Zeit nicht erreichbar: \n${objectData.Adapter}: ${objectData.Device} (${objectData.LastContact})`;
2694
+ }
2695
+ break;
2471
2696
  }
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`;
2495
-
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);
2697
+ setMessage(message);
2698
+ break;
2699
+ case 'updateDevice':
2700
+ objectData = this.listAllDevicesRaw.get(id);
2701
+ if (!this.config.showAdapterNameinMsg) {
2702
+ message = `Neue Geräte Updates vorhanden: \n${objectData.Device}`;
2703
+ } else {
2704
+ message = `Neue Geräte Updates vorhanden: \n${objectData.Adapter}: ${objectData.Device}`;
2705
+ }
2706
+ setMessage(message);
2707
+ break;
2708
+ case 'updateAdapter':
2709
+ if (this.countAdapterUpdates === 0) return;
2710
+ objectData = this.listAdapterUpdates;
2711
+ list = '';
2712
+ for (const id of objectData) {
2713
+ list = `${list}\n${id.Adapter}: v${id['Available Version']}`;
2714
+ }
2715
+ message = `Neue Adapter Updates vorhanden: ${list}`;
2716
+ setMessage(message);
2717
+ break;
2718
+ case 'errorInstance':
2719
+ objectData = this.listInstanceRaw.get(id);
2720
+ message = `Instanz Watchdog:\n${objectData.InstanceName}: ${objectData.status}`;
2721
+ setMessage(message);
2722
+ break;
2501
2723
  }
2502
- this.log.debug(`Finished the function: ${this.sendLowBatNoticiation.name}`);
2503
2724
  }
2504
2725
 
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
2726
  /**
2544
- * send shedule message with offline devices
2727
+ * Notifications per user defined schedule
2728
+ * @param {string} type
2545
2729
  */
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 = '';
2730
+ sendScheduleNotifications(type) {
2731
+ if (isUnloaded) return;
2732
+
2733
+ let time;
2734
+ let cron;
2735
+ let list = '';
2736
+ let message = '';
2737
+ const checkDays = [];
2738
+ const setMessage = async (message) => {
2739
+ this.log.info(`${message}`);
2740
+ await this.setStateAsync('lastNotification', `${message}`, true);
2741
+ await this.sendNotification(`${message}`);
2742
+ return (message = '');
2743
+ };
2744
+
2745
+ switch (type) {
2746
+ case 'lowBatteryDevices':
2747
+ // push the selected days in list
2748
+ if (this.config.checkMonday) checkDays.push(1);
2749
+ if (this.config.checkTuesday) checkDays.push(2);
2750
+ if (this.config.checkWednesday) checkDays.push(3);
2751
+ if (this.config.checkThursday) checkDays.push(4);
2752
+ if (this.config.checkFriday) checkDays.push(5);
2753
+ if (this.config.checkSaturday) checkDays.push(6);
2754
+ if (this.config.checkSunday) checkDays.push(0);
2755
+
2756
+ time = this.config.checkSendBatteryTime.split(':');
2757
+
2758
+ if (checkDays.length === 0) {
2759
+ this.log.warn(`No days selected for daily low battery devices message. Please check the instance configuration!`);
2760
+ return; // cancel function if no day is selected
2761
+ }
2762
+ this.log.debug(`Number of selected days for daily low battery devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2573
2763
 
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
- }
2764
+ cron = '1 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2765
+ schedule.scheduleJob(cron, () => {
2766
+ list = '';
2767
+ for (const id of this.batteryLowPoweredRaw) {
2768
+ if (this.blacklistNotify.includes(id.Path)) continue;
2769
+ if (!this.config.showAdapterNameinMsg) {
2770
+ list = `${list}\n${id.Device} (${id.Battery})`;
2771
+ } else {
2772
+ // Add adaptername if checkbox is checked true in options by user
2773
+ list = `${list}\n${id.Adapter}: ${id.Device} (${id.Battery})`;
2581
2774
  }
2582
2775
  }
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);
2776
+ if (list.length === 0) return;
2777
+ message = `Tägliche Meldung über Geräte mit niedrigen Batteriezuständen: ${list}`;
2778
+ setMessage(message);
2779
+ });
2780
+ break;
2781
+ case 'offlineDevices':
2782
+ // push the selected days in list
2783
+ if (this.config.checkOfflineMonday) checkDays.push(1);
2784
+ if (this.config.checkOfflineTuesday) checkDays.push(2);
2785
+ if (this.config.checkOfflineWednesday) checkDays.push(3);
2786
+ if (this.config.checkOfflineThursday) checkDays.push(4);
2787
+ if (this.config.checkOfflineFriday) checkDays.push(5);
2788
+ if (this.config.checkOfflineSaturday) checkDays.push(6);
2789
+ if (this.config.checkOfflineSunday) checkDays.push(0);
2790
+
2791
+ time = this.config.checkSendOfflineTime.split(':');
2792
+
2793
+ if (checkDays.length === 0) {
2794
+ this.log.warn(`No days selected for daily offline devices message. Please check the instance configuration!`);
2795
+ return; // cancel function if no day is selected
2592
2796
  }
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}`);
2797
+ this.log.debug(`Number of selected days for daily offline devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2605
2798
 
2606
- try {
2607
- let msg = '';
2608
- let deviceList = '';
2609
-
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 = '';
2799
+ cron = '2 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2800
+ schedule.scheduleJob(cron, () => {
2801
+ list = '';
2657
2802
 
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
- }
2803
+ for (const id of this.offlineDevicesRaw) {
2804
+ if (this.blacklistNotify.includes(id.Path)) continue;
2805
+ if (!this.config.showAdapterNameinMsg) {
2806
+ list = `${list}\n${id.Device} (${id.LastContact})`;
2807
+ } else {
2808
+ list = `${list}\n${id.Adapter}: ${id.Device} (${id.LastContact})`;
2665
2809
  }
2666
2810
  }
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
2811
 
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}`;
2697
- }
2698
- if (adapterList.length !== 0) {
2699
- msg = `Neue Adapter Updates vorhanden: \n`;
2700
-
2701
- this.log.info(msg + adapterList);
2702
- await this.setStateAsync('lastNotification', msg + adapterList, true);
2703
- await this.sendNotification(msg + adapterList);
2812
+ if (list.length === 0) return;
2813
+ message = `Tägliche Meldung über offline Geräte: ${list}`;
2814
+ setMessage(message);
2815
+ });
2816
+ break;
2817
+ case 'updateDevices':
2818
+ // push the selected days in list
2819
+ if (this.config.checkUpgradeMonday) checkDays.push(1);
2820
+ if (this.config.checkUpgradeTuesday) checkDays.push(2);
2821
+ if (this.config.checkUpgradeWednesday) checkDays.push(3);
2822
+ if (this.config.checkUpgradeThursday) checkDays.push(4);
2823
+ if (this.config.checkUpgradeFriday) checkDays.push(5);
2824
+ if (this.config.checkUpgradeSaturday) checkDays.push(6);
2825
+ if (this.config.checkUpgradeSunday) checkDays.push(0);
2826
+
2827
+ time = this.config.checkSendUpgradeTime.split(':');
2828
+
2829
+ if (checkDays.length === 0) {
2830
+ this.log.warn(`No days selected for daily updatable devices message. Please check the instance configuration!`);
2831
+ return; // cancel function if no day is selected
2704
2832
  }
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
- }
2833
+ this.log.debug(`Number of selected days for daily updatable devices message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2736
2834
 
2737
- if (!isUnloaded) {
2738
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2739
- schedule.scheduleJob(cron, () => {
2740
- try {
2741
- let deviceList = '';
2835
+ cron = '3 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2836
+ schedule.scheduleJob(cron, () => {
2837
+ list = '';
2742
2838
 
2743
2839
  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
- }
2840
+ if (this.blacklistNotify.includes(id.Path)) continue;
2841
+ if (!this.config.showAdapterNameinMsg) {
2842
+ list = `${list}\n${id.Device}`;
2843
+ } else {
2844
+ list = `${list}\n${id.Adapter}: ${id.Device}`;
2750
2845
  }
2751
2846
  }
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);
2847
+ if (list.length === 0) return;
2848
+ message = `Tägliche Meldung über verfügbare Geräte Updates: ${list}`;
2849
+ setMessage(message);
2850
+ });
2851
+ break;
2852
+ case 'updateAdapter':
2853
+ // push the selected days in list
2854
+ if (this.config.checkAdapterUpdateMonday) checkDays.push(1);
2855
+ if (this.config.checkAdapterUpdateTuesday) checkDays.push(2);
2856
+ if (this.config.checkAdapterUpdateWednesday) checkDays.push(3);
2857
+ if (this.config.checkAdapterUpdateThursday) checkDays.push(4);
2858
+ if (this.config.checkAdapterUpdateFriday) checkDays.push(5);
2859
+ if (this.config.checkAdapterUpdateSaturday) checkDays.push(6);
2860
+ if (this.config.checkAdapterUpdateSunday) checkDays.push(0);
2861
+
2862
+ time = this.config.checkSendAdapterUpdateTime.split(':');
2863
+
2864
+ if (checkDays.length === 0) {
2865
+ this.log.warn(`No days selected for daily adapter update message. Please check the instance configuration!`);
2866
+ return; // cancel function if no day is selected
2760
2867
  }
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}`;
2868
+ this.log.debug(`Number of selected days for daily adapter update message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2779
2869
 
2780
- msg = `Fehler einer Instanz entdeckt: \n`;
2870
+ cron = '4 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2871
+ schedule.scheduleJob(cron, () => {
2872
+ list = '';
2781
2873
 
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
- }
2815
-
2816
- if (!isUnloaded) {
2817
- const cron = '10 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2818
- schedule.scheduleJob(cron, () => {
2819
- try {
2820
- let instanceList = '';
2821
-
2822
- for (const id of this.listErrorInstanceRaw) {
2823
- if (!this.blacklistInstancesNotify.includes(id.instanceAlivePath)) {
2824
- instanceList = `${instanceList}\n${id.Instance}: ${id.Status}`;
2825
- }
2874
+ for (const id of this.listAdapterUpdates) {
2875
+ list = `${list}\n${id.Adapter}: v${id['Available Version']}`;
2826
2876
  }
2827
- if (instanceList.length > 0) {
2828
- this.log.info(`Instanz Fehler: ${instanceList}`);
2829
- this.setStateAsync('lastNotification', `Instanz Fehler: ${instanceList}`, true);
2877
+ if (list.length === 0) return;
2878
+ message = `Tägliche Meldung über verfügbare Adapter Updates: ${list}`;
2879
+ setMessage(message);
2880
+ });
2881
+ break;
2882
+ case 'errorInstance':
2883
+ // push the selected days in list
2884
+ if (this.config.checkFailedInstancesMonday) checkDays.push(1);
2885
+ if (this.config.checkFailedInstancesTuesday) checkDays.push(2);
2886
+ if (this.config.checkFailedInstancesWednesday) checkDays.push(3);
2887
+ if (this.config.checkFailedInstancesThursday) checkDays.push(4);
2888
+ if (this.config.checkFailedInstancesFriday) checkDays.push(5);
2889
+ if (this.config.checkFailedInstancesSaturday) checkDays.push(6);
2890
+ if (this.config.checkFailedInstancesSunday) checkDays.push(0);
2891
+
2892
+ time = this.config.checkSendInstanceFailedTime.split(':');
2893
+
2894
+ if (checkDays.length === 0) {
2895
+ this.log.warn(`No days selected for daily instance error message. Please check the instance configuration!`);
2896
+ return; // cancel function if no day is selected
2897
+ }
2898
+ this.log.debug(`Number of selected days for daily instance error message: ${checkDays.length}. Send Message on: ${checkDays.join(', ')} ...`);
2899
+ cron = '5 ' + time[1] + ' ' + time[0] + ' * * ' + checkDays;
2900
+ schedule.scheduleJob(cron, () => {
2901
+ list = '';
2830
2902
 
2831
- this.sendNotification(`Instanz Fehler:\n${instanceList}`);
2903
+ for (const id of this.listErrorInstanceRaw) {
2904
+ if (this.blacklistInstancesNotify.includes(id.instanceAlivePath)) continue;
2905
+ list = `${list}\n${id.Instance}: ${id.Status}`;
2832
2906
  }
2833
- } catch (error) {
2834
- this.errorReporting('[sendInstanceErrorNotificationShedule]', error);
2835
- }
2836
- });
2907
+ if (list.length === 0) return;
2908
+ message = `Tägliche Meldung über fehlerhafte Instanzen: ${list}`;
2909
+ setMessage(message);
2910
+ });
2911
+ break;
2837
2912
  }
2838
- } //<--End of daily device updates notification
2913
+ }
2839
2914
 
2840
2915
  /*=============================================
2841
2916
  = functions to create html lists =
2842
2917
  =============================================*/
2843
-
2844
2918
  /**
2919
+ * @param {string} type - type of list
2845
2920
  * @param {object} devices - Device
2846
2921
  * @param {number} deviceCount - Counted devices
2922
+ * @param {object} isLowBatteryList - list Low Battery Devices
2847
2923
  */
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>
2924
+ async createListHTML(type, devices, deviceCount, isLowBatteryList) {
2925
+ let html;
2926
+ switch (type) {
2927
+ case 'linkQualityList':
2928
+ devices = devices.sort((a, b) => {
2929
+ a = a.Device || '';
2930
+ b = b.Device || '';
2931
+ return a.localeCompare(b);
2932
+ });
2933
+ html = `<center>
2934
+ <b>Link Quality Devices:<font> ${deviceCount}</b><small></small></font>
2935
+ <p></p>
2936
+ </center>
2937
+ <table width=100%>
2938
+ <tr>
2939
+ <th align=left>Device</th>
2940
+ <th align=center width=120>Adapter</th>
2941
+ <th align=right>Link Quality</th>
2942
+ </tr>
2943
+ <tr>
2944
+ <td colspan="5"><hr></td>
2873
2945
  </tr>`;
2874
- }
2875
2946
 
2876
- html += '</table>';
2877
- return html;
2878
- }
2947
+ for (const device of devices) {
2948
+ html += `<tr>
2949
+ <td><font>${device.Device}</font></td>
2950
+ <td align=center><font>${device.Adapter}</font></td>
2951
+ <td align=right><font>${device['Signal strength']}</font></td>
2952
+ </tr>`;
2953
+ }
2879
2954
 
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>
2955
+ html += '</table>';
2956
+ break;
2957
+
2958
+ case 'offlineList':
2959
+ devices = devices.sort((a, b) => {
2960
+ a = a.Device || '';
2961
+ b = b.Device || '';
2962
+ return a.localeCompare(b);
2963
+ });
2964
+ html = `<center>
2965
+ <b>Offline Devices: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
2966
+ <p></p>
2967
+ </center>
2968
+ <table width=100%>
2969
+ <tr>
2970
+ <th align=left>Device</th>
2971
+ <th align=center width=120>Adapter</th>
2972
+ <th align=center>Letzter Kontakt</th>
2973
+ </tr>
2974
+ <tr>
2975
+ <td colspan="5"><hr></td>
2909
2976
  </tr>`;
2910
- }
2911
2977
 
2912
- html += '</table>';
2913
- return html;
2914
- }
2978
+ for (const device of devices) {
2979
+ html += `<tr>
2980
+ <td><font>${device.Device}</font></td>
2981
+ <td align=center><font>${device.Adapter}</font></td>
2982
+ <td align=center><font color=orange>${device['Last contact']}</font></td>
2983
+ </tr>`;
2984
+ }
2915
2985
 
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
- }
2986
+ html += '</table>';
2987
+ break;
2988
+
2989
+ case 'batteryList':
2990
+ devices = devices.sort((a, b) => {
2991
+ a = a.Device || '';
2992
+ b = b.Device || '';
2993
+ return a.localeCompare(b);
2994
+ });
2995
+ html = `<center>
2996
+ <b>${isLowBatteryList === true ? 'Schwache ' : ''}Batterie Devices: <font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
2997
+ <p></p>
2998
+ </center>
2999
+ <table width=100%>
3000
+ <tr>
3001
+ <th align=left>Device</th>
3002
+ <th align=center width=120>Adapter</th>
3003
+ <th align=${isLowBatteryList ? 'center' : 'right'}>Batterie</th>
3004
+ </tr>
3005
+ <tr>
3006
+ <td colspan="5"><hr></td>
3007
+ </tr>`;
3008
+ for (const device of devices) {
3009
+ html += `<tr>
3010
+ <td><font>${device.Device}</font></td>
3011
+ <td align=center><font>${device.Adapter}</font></td>`;
3012
+
3013
+ if (isLowBatteryList) {
3014
+ html += `<td align=center><font color=orange>${device.Battery}</font></td>`;
3015
+ } else {
3016
+ html += `<td align=right><font color=#3bcf0e>${device.Battery}</font></td>`;
3017
+ }
3018
+ html += `</tr>`;
3019
+ }
2952
3020
 
2953
- html += '</table>';
3021
+ html += '</table>';
3022
+ break;
3023
+ }
2954
3024
  return html;
2955
3025
  }
2956
3026
 
@@ -3041,6 +3111,30 @@ class DeviceWatcher extends utils.Adapter {
3041
3111
  native: {},
3042
3112
  });
3043
3113
 
3114
+ await this.setObjectNotExistsAsync(`devices.${adptName}.listAllRawJSON`, {
3115
+ type: 'state',
3116
+ common: {
3117
+ name: {
3118
+ en: 'JSON RAW List of all devices',
3119
+ de: 'JSON RAW Liste aller Geräte',
3120
+ ru: 'ДЖСОН РАВ Список всех устройств',
3121
+ pt: 'JSON RAW Lista de todos os dispositivos',
3122
+ nl: 'JSON RAW List van alle apparaten',
3123
+ fr: 'JSON RAW Liste de tous les dispositifs',
3124
+ it: 'JSON RAW Elenco di tutti i dispositivi',
3125
+ es: 'JSON RAW Lista de todos los dispositivos',
3126
+ pl: 'JSON RAW Lista wszystkich urządzeń',
3127
+ uk: 'ДЖСОН РАВ Список всіх пристроїв',
3128
+ 'zh-cn': 'JSONRAW 所有装置清单',
3129
+ },
3130
+ type: 'array',
3131
+ role: 'json',
3132
+ read: true,
3133
+ write: false,
3134
+ },
3135
+ native: {},
3136
+ });
3137
+
3044
3138
  await this.setObjectNotExistsAsync(`devices.${adptName}.listAll`, {
3045
3139
  type: 'state',
3046
3140
  common: {
@@ -3302,6 +3396,30 @@ class DeviceWatcher extends utils.Adapter {
3302
3396
  }
3303
3397
 
3304
3398
  /**
3399
+ * delete datapoints for each adapter
3400
+ * @param {object} adptName - Adaptername of devices
3401
+ */
3402
+ async deleteDPsForEachAdapter(adptName) {
3403
+ await this.delObjectAsync(`devices.${adptName}`);
3404
+ await this.delObjectAsync(`devices.${adptName}.offlineCount`);
3405
+ await this.delObjectAsync(`devices.${adptName}.offlineList`);
3406
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
3407
+ await this.delObjectAsync(`devices.${adptName}.listAllRawJSON`);
3408
+ await this.delObjectAsync(`devices.${adptName}.listAll`);
3409
+ await this.delObjectAsync(`devices.${adptName}.linkQualityList`);
3410
+ await this.delObjectAsync(`devices.${adptName}.countAll`);
3411
+ await this.delObjectAsync(`devices.${adptName}.batteryList`);
3412
+ await this.delObjectAsync(`devices.${adptName}.lowBatteryList`);
3413
+ await this.delObjectAsync(`devices.${adptName}.lowBatteryCount`);
3414
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceLowBat`);
3415
+ await this.delObjectAsync(`devices.${adptName}.batteryCount`);
3416
+ await this.delObjectAsync(`devices.${adptName}.upgradableCount`);
3417
+ await this.delObjectAsync(`devices.${adptName}.upgradableList`);
3418
+ await this.delObjectAsync(`devices.${adptName}.oneDeviceUpdatable`);
3419
+ }
3420
+
3421
+ /**
3422
+ * create HTML list datapoints
3305
3423
  * @param {object} [adptName] - Adaptername of devices
3306
3424
  **/
3307
3425
  async createHtmlListDatapoints(adptName) {
@@ -3406,6 +3524,25 @@ class DeviceWatcher extends utils.Adapter {
3406
3524
  });
3407
3525
  }
3408
3526
 
3527
+ /**
3528
+ * delete html datapoints
3529
+ * @param {object} [adptName] - Adaptername of devices
3530
+ **/
3531
+ async deleteHtmlListDatapoints(adptName) {
3532
+ // delete the datapoints in subfolders with the adaptername otherwise delete the dP's in the root folder
3533
+ let dpSubFolder;
3534
+ if (adptName) {
3535
+ dpSubFolder = `${adptName}.`;
3536
+ } else {
3537
+ dpSubFolder = '';
3538
+ }
3539
+
3540
+ await this.delObjectAsync(`devices.${dpSubFolder}offlineListHTML`);
3541
+ await this.delObjectAsync(`devices.${dpSubFolder}linkQualityListHTML`);
3542
+ await this.delObjectAsync(`devices.${dpSubFolder}batteryListHTML`);
3543
+ await this.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
3544
+ }
3545
+
3409
3546
  /*=============================================
3410
3547
  = help functions =
3411
3548
  =============================================*/
@@ -3421,20 +3558,27 @@ class DeviceWatcher extends utils.Adapter {
3421
3558
  /**
3422
3559
  * @param {number} dpValue - get Time of this datapoint
3423
3560
  */
3424
- async getTimestamp(dpValue) {
3561
+ getTimestamp(dpValue) {
3425
3562
  const time = new Date();
3426
3563
  return (dpValue = Math.round((time.getTime() - dpValue) / 1000 / 60));
3427
3564
  }
3428
3565
 
3429
3566
  /**
3430
3567
  * @param {string} dp - get Time of this datapoint
3568
+ * @param {number} ms - milliseconds
3431
3569
  */
3432
- async getTimestampConnectionDP(dp) {
3570
+ async getTimestampConnectionDP(dp, ms) {
3433
3571
  const time = new Date();
3434
3572
  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;
3573
+ if (dpValue) {
3574
+ if (!dpValue.val) return false;
3575
+
3576
+ const dpLastStateChange = Math.round(time.getTime() - dpValue.lc); // calculate in ms
3577
+ if (dpLastStateChange >= ms) {
3578
+ return true;
3579
+ } else {
3580
+ return false;
3581
+ }
3438
3582
  }
3439
3583
  }
3440
3584
 
@@ -3459,7 +3603,7 @@ class DeviceWatcher extends utils.Adapter {
3459
3603
  /**
3460
3604
  * @param {object} data - object
3461
3605
  */
3462
- async parseData(data) {
3606
+ parseData(data) {
3463
3607
  if (!data) return {};
3464
3608
  if (typeof data === 'object') return data;
3465
3609
  if (typeof data === 'string') return JSON.parse(data);
@@ -3467,12 +3611,11 @@ class DeviceWatcher extends utils.Adapter {
3467
3611
  }
3468
3612
 
3469
3613
  /**
3470
- * @param {number} time
3614
+ * @param {number} ms
3471
3615
  */
3472
- async wait(time) {
3473
- return new Promise((resolve) => {
3474
- setTimeout(resolve, time);
3475
- });
3616
+ async wait(ms) {
3617
+ if (isUnloaded) return;
3618
+ return new Promise((resolve) => setTimeout(resolve, ms));
3476
3619
  }
3477
3620
 
3478
3621
  /**
@@ -3481,7 +3624,7 @@ class DeviceWatcher extends utils.Adapter {
3481
3624
  * Inspired by https://stackoverflow.com/questions/68134104/
3482
3625
  * @param {string} lastCronRun
3483
3626
  */
3484
- async getPreviousCronRun(lastCronRun) {
3627
+ getPreviousCronRun(lastCronRun) {
3485
3628
  try {
3486
3629
  const interval = cronParser.parseExpression(lastCronRun);
3487
3630
  const previous = interval.prev();
@@ -3516,11 +3659,14 @@ class DeviceWatcher extends utils.Adapter {
3516
3659
  */
3517
3660
  onUnload(callback) {
3518
3661
  try {
3662
+ this.log.debug('clearing timeouts');
3663
+
3664
+ isUnloaded = true;
3665
+
3519
3666
  if (this.refreshDataTimeout) {
3520
- this.log.debug('clearing refresh timeout');
3521
- this.clearTimeout(this.refreshDataTimeout);
3667
+ clearTimeout(this.refreshDataTimeout);
3668
+ this.refreshDataTimeout = null;
3522
3669
  }
3523
- isUnloaded = true;
3524
3670
 
3525
3671
  this.log.info('cleaned everything up...');
3526
3672