iobroker.device-watcher 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/main.js CHANGED
@@ -27,17 +27,19 @@ class DeviceWatcher extends utils.Adapter {
27
27
  // instances and adapters
28
28
  // raw arrays
29
29
  this.listInstanceRaw = new Map();
30
- this.adapterUpdatesJsonRaw = [];
30
+ this.adapterUpdatesJsonRaw = new Map();
31
31
  this.listErrorInstanceRaw = [];
32
32
 
33
33
  // user arrays
34
34
  this.listAllInstances = [];
35
+ this.listAllActiveInstances = [];
35
36
  this.listDeactivatedInstances = [];
36
37
  this.listAdapterUpdates = [];
37
38
  this.listErrorInstance = [];
38
39
 
39
40
  //counts
40
41
  this.countAllInstances = 0;
42
+ this.countAllActiveInstances = 0;
41
43
  this.countDeactivatedInstances = 0;
42
44
  this.countAdapterUpdates = 0;
43
45
  this.countErrorInstance = 0;
@@ -50,11 +52,12 @@ class DeviceWatcher extends utils.Adapter {
50
52
  this.upgradableDevicesRaw = [];
51
53
 
52
54
  // arrays
55
+ this.listAllDevicesUserRaw = [];
56
+ this.listAllDevices = [];
53
57
  this.offlineDevices = [];
54
58
  this.linkQualityDevices = [];
55
59
  this.batteryPowered = [];
56
60
  this.batteryLowPowered = [];
57
- this.listAllDevices = [];
58
61
  this.selAdapter = [];
59
62
  this.adapterSelected = [];
60
63
  this.upgradableList = [];
@@ -77,6 +80,9 @@ class DeviceWatcher extends utils.Adapter {
77
80
  this.blacklistAdapterLists = [];
78
81
  this.blacklistNotify = [];
79
82
 
83
+ // Timelist instances
84
+ this.userTimeInstancesList = new Map();
85
+
80
86
  // Interval timer
81
87
  this.refreshDataTimeout = null;
82
88
 
@@ -93,119 +99,124 @@ class DeviceWatcher extends utils.Adapter {
93
99
  async onReady() {
94
100
  this.log.debug(`Adapter ${adapterName} was started`);
95
101
 
96
- try {
97
- this.listOnlyBattery = this.config.listOnlyBattery;
98
- this.createOwnFolder = this.config.createOwnFolder;
99
- this.createHtmlList = this.config.createHtmlList;
100
-
101
- this.configSetAdapter = {
102
- alexa2: this.config.alexa2Devices,
103
- apcups: this.config.apcupsDevices,
104
- ble: this.config.bleDevices,
105
- deconz: this.config.deconzDevices,
106
- enocean: this.config.enoceanDevices,
107
- esphome: this.config.esphomeDevices,
108
- eusec: this.config.eusecDevices,
109
- fritzdect: this.config.fritzdectDevices,
110
- fullybrowser: this.config.fullybrowserDevices,
111
- ham: this.config.hamDevices,
112
- harmony: this.config.harmonyDevices,
113
- hmiP: this.config.hmiPDevices,
114
- hmrpc: this.config.hmrpcDevices,
115
- homeconnect: this.config.homeconnectDevices,
116
- hs100: this.config.hs100Devices,
117
- hue: this.config.hueDevices,
118
- hueExt: this.config.hueExtDevices,
119
- innogy: this.config.innogyDevices,
120
- jeelink: this.config.jeelinkDevices,
121
- lupusec: this.config.lupusecDevices,
122
- maxcube: this.config.maxcubeDevices,
123
- meross: this.config.merossDevices,
124
- mihome: this.config.mihomeDevices,
125
- mihomeGW: this.config.mihomeDevices,
126
- mihomeVacuum: this.config.mihomeVacuumDevices,
127
- mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttDevices,
128
- mqttNuki: this.config.mqttNukiDevices,
129
- musiccast: this.config.musiccastDevices,
130
- netatmo: this.config.netatmoDevices,
131
- nukiExt: this.config.nukiExtDevices,
132
- nut: this.config.nutDevices,
133
- ping: this.config.pingDevices,
134
- proxmox: this.config.proxmoxDevices,
135
- roomba: this.config.roombaDevices,
136
- shelly: this.config.shellyDevices,
137
- smartgarden: this.config.smartgardenDevices,
138
- sonoff: this.config.sonoffDevices,
139
- sonos: this.config.sonosDevices,
140
- sureflap: this.config.sureflapDevices,
141
- switchbotBle: this.config.switchbotBleDevices,
142
- tado: this.config.tadoDevices,
143
- tapo: this.config.tapoDevices,
144
- tradfri: this.config.tradfriDevices,
145
- unifi: this.config.unifiDevices,
146
- wled: this.config.wledDevices,
147
- yeelight: this.config.yeelightDevices,
148
- zigbee: this.config.zigbeeDevices,
149
- zigbee2MQTT: this.config.zigbee2mqttDevices,
150
- zwave: this.config.zwaveDevices,
151
- };
152
-
153
- this.configMaxMinutes = {
154
- alexa2: this.config.alexa2MaxMinutes,
155
- apcups: this.config.apcupsMaxMinutes,
156
- ble: this.config.bleMaxMinutes,
157
- deconz: this.config.deconzMaxMinutes,
158
- enocean: this.config.enoceanMaxMinutes,
159
- esphome: this.config.esphomeMaxMinutes,
160
- eusec: this.config.eusecMaxMinutes,
161
- fritzdect: this.config.fritzdectMaxMinutes,
162
- fullybrowser: this.config.fullybrowserMaxMinutes,
163
- ham: this.config.hamMaxMinutes,
164
- harmony: this.config.harmonyMaxMinutes,
165
- hmiP: this.config.hmiPMaxMinutes,
166
- hmrpc: this.config.hmrpcMaxMinutes,
167
- homeconnect: this.config.homeconnectMaxMinutes,
168
- hs100: this.config.hs100MaxMinutes,
169
- hue: this.config.hueMaxMinutes,
170
- hueExt: this.config.hueextMaxMinutes,
171
- innogy: this.config.innogyMaxMinutes,
172
- jeelink: this.config.jeelinkMaxMinutes,
173
- lupusec: this.config.lupusecMaxMinutes,
174
- maxcube: this.config.maxcubeMaxMinutes,
175
- meross: this.config.merossMaxMinutes,
176
- mihome: this.config.mihomeMaxMinutes,
177
- mihomeGW: this.config.mihomeMaxMinutes,
178
- mihomeVacuum: this.config.mihomeVacuumMaxMinutes,
179
- mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttMaxMinutes,
180
- mqttNuki: this.config.mqttNukiMaxMinutes,
181
- musiccast: this.config.musiccastMaxMinutes,
182
- netatmo: this.config.netatmoMaxMinutes,
183
- nukiExt: this.config.nukiextendMaxMinutes,
184
- nut: this.config.nutMaxMinutes,
185
- ping: this.config.pingMaxMinutes,
186
- proxmox: this.config.proxmoxMaxMinutes,
187
- roomba: this.config.roombaMaxMinutes,
188
- shelly: this.config.shellyMaxMinutes,
189
- smartgarden: this.config.smartgardenMaxMinutes,
190
- sonoff: this.config.sonoffMaxMinutes,
191
- sonos: this.config.sonosMaxMinutes,
192
- sureflap: this.config.sureflapMaxMinutes,
193
- switchbotBle: this.config.switchbotMaxMinutes,
194
- tado: this.config.tadoMaxMinutes,
195
- tapo: this.config.tapoMaxMinutes,
196
- tradfri: this.config.tradfriMaxMinutes,
197
- unifi: this.config.unifiMaxMinutes,
198
- wled: this.config.wledMaxMinutes,
199
- yeelight: this.config.yeelightMaxMinutes,
200
- zigbee: this.config.zigbeeMaxMinutes,
201
- zigbee2MQTT: this.config.zigbee2mqttMaxMinutes,
202
- zwave: this.config.zwaveMaxMinutes,
203
- };
102
+ this.configCreateInstanceList = this.config.checkAdapterInstances;
103
+ this.configListOnlyBattery = this.config.listOnlyBattery;
104
+ this.configCreateOwnFolder = this.config.createOwnFolder;
105
+ this.configCreateHtmlList = this.config.createHtmlList;
106
+
107
+ this.configSetAdapter = {
108
+ alexa2: this.config.alexa2Devices,
109
+ apcups: this.config.apcupsDevices,
110
+ ble: this.config.bleDevices,
111
+ deconz: this.config.deconzDevices,
112
+ enocean: this.config.enoceanDevices,
113
+ esphome: this.config.esphomeDevices,
114
+ eusec: this.config.eusecDevices,
115
+ fhemTFAsensors: this.config.fhemTFAsensorsDevices,
116
+ fritzdect: this.config.fritzdectDevices,
117
+ fullybrowser: this.config.fullybrowserDevices,
118
+ fullyMQTT: this.config.fullyMQTTDevices,
119
+ ham: this.config.hamDevices,
120
+ harmony: this.config.harmonyDevices,
121
+ hmiP: this.config.hmiPDevices,
122
+ hmrpc: this.config.hmrpcDevices,
123
+ homeconnect: this.config.homeconnectDevices,
124
+ hs100: this.config.hs100Devices,
125
+ hue: this.config.hueDevices,
126
+ hueExt: this.config.hueExtDevices,
127
+ innogy: this.config.innogyDevices,
128
+ jeelink: this.config.jeelinkDevices,
129
+ lupusec: this.config.lupusecDevices,
130
+ maxcube: this.config.maxcubeDevices,
131
+ meross: this.config.merossDevices,
132
+ mihome: this.config.mihomeDevices,
133
+ mihomeGW: this.config.mihomeDevices,
134
+ mihomeVacuum: this.config.mihomeVacuumDevices,
135
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttDevices,
136
+ mqttNuki: this.config.mqttNukiDevices,
137
+ musiccast: this.config.musiccastDevices,
138
+ netatmo: this.config.netatmoDevices,
139
+ nukiExt: this.config.nukiExtDevices,
140
+ nut: this.config.nutDevices,
141
+ ping: this.config.pingDevices,
142
+ proxmox: this.config.proxmoxDevices,
143
+ roomba: this.config.roombaDevices,
144
+ shelly: this.config.shellyDevices,
145
+ smartgarden: this.config.smartgardenDevices,
146
+ sonoff: this.config.sonoffDevices,
147
+ sonos: this.config.sonosDevices,
148
+ sureflap: this.config.sureflapDevices,
149
+ switchbotBle: this.config.switchbotBleDevices,
150
+ tado: this.config.tadoDevices,
151
+ tapo: this.config.tapoDevices,
152
+ tradfri: this.config.tradfriDevices,
153
+ unifi: this.config.unifiDevices,
154
+ wled: this.config.wledDevices,
155
+ yeelight: this.config.yeelightDevices,
156
+ zigbee: this.config.zigbeeDevices,
157
+ zigbee2MQTT: this.config.zigbee2mqttDevices,
158
+ zwave: this.config.zwaveDevices,
159
+ };
204
160
 
161
+ this.configMaxMinutes = {
162
+ alexa2: this.config.alexa2MaxMinutes,
163
+ apcups: this.config.apcupsMaxMinutes,
164
+ ble: this.config.bleMaxMinutes,
165
+ deconz: this.config.deconzMaxMinutes,
166
+ enocean: this.config.enoceanMaxMinutes,
167
+ esphome: this.config.esphomeMaxMinutes,
168
+ eusec: this.config.eusecMaxMinutes,
169
+ fhemTFAsensors: this.config.fhemTFAsensorsMaxMinutes,
170
+ fritzdect: this.config.fritzdectMaxMinutes,
171
+ fullybrowser: this.config.fullybrowserMaxMinutes,
172
+ fullyMQTT: this.config.fullyMQTTMaxMinutes,
173
+ ham: this.config.hamMaxMinutes,
174
+ harmony: this.config.harmonyMaxMinutes,
175
+ hmiP: this.config.hmiPMaxMinutes,
176
+ hmrpc: this.config.hmrpcMaxMinutes,
177
+ homeconnect: this.config.homeconnectMaxMinutes,
178
+ hs100: this.config.hs100MaxMinutes,
179
+ hue: this.config.hueMaxMinutes,
180
+ hueExt: this.config.hueextMaxMinutes,
181
+ innogy: this.config.innogyMaxMinutes,
182
+ jeelink: this.config.jeelinkMaxMinutes,
183
+ lupusec: this.config.lupusecMaxMinutes,
184
+ maxcube: this.config.maxcubeMaxMinutes,
185
+ meross: this.config.merossMaxMinutes,
186
+ mihome: this.config.mihomeMaxMinutes,
187
+ mihomeGW: this.config.mihomeMaxMinutes,
188
+ mihomeVacuum: this.config.mihomeVacuumMaxMinutes,
189
+ mqttClientZigbee2Mqtt: this.config.mqttClientZigbee2MqttMaxMinutes,
190
+ mqttNuki: this.config.mqttNukiMaxMinutes,
191
+ musiccast: this.config.musiccastMaxMinutes,
192
+ netatmo: this.config.netatmoMaxMinutes,
193
+ nukiExt: this.config.nukiextendMaxMinutes,
194
+ nut: this.config.nutMaxMinutes,
195
+ ping: this.config.pingMaxMinutes,
196
+ proxmox: this.config.proxmoxMaxMinutes,
197
+ roomba: this.config.roombaMaxMinutes,
198
+ shelly: this.config.shellyMaxMinutes,
199
+ smartgarden: this.config.smartgardenMaxMinutes,
200
+ sonoff: this.config.sonoffMaxMinutes,
201
+ sonos: this.config.sonosMaxMinutes,
202
+ sureflap: this.config.sureflapMaxMinutes,
203
+ switchbotBle: this.config.switchbotMaxMinutes,
204
+ tado: this.config.tadoMaxMinutes,
205
+ tapo: this.config.tapoMaxMinutes,
206
+ tradfri: this.config.tradfriMaxMinutes,
207
+ unifi: this.config.unifiMaxMinutes,
208
+ wled: this.config.wledMaxMinutes,
209
+ yeelight: this.config.yeelightMaxMinutes,
210
+ zigbee: this.config.zigbeeMaxMinutes,
211
+ zigbee2MQTT: this.config.zigbee2mqttMaxMinutes,
212
+ zwave: this.config.zwaveMaxMinutes,
213
+ };
214
+
215
+ try {
205
216
  for (const [id] of Object.entries(arrApart)) {
206
217
  if (this.configSetAdapter[id]) {
207
218
  this.selAdapter.push(arrApart[id]);
208
- this.adapterSelected.push(await this.capitalize(id));
219
+ this.adapterSelected.push(this.capitalize(id));
209
220
  }
210
221
  }
211
222
 
@@ -223,17 +234,20 @@ class DeviceWatcher extends utils.Adapter {
223
234
  //create Blacklist
224
235
  await this.createBlacklist();
225
236
 
237
+ // create user defined list with time of error for instances
238
+ await this.createTimeListInstances();
239
+
226
240
  //create datapoints for each adapter if selected
227
241
  for (const [id] of Object.entries(arrApart)) {
228
242
  try {
229
- if (!this.createOwnFolder) {
243
+ if (!this.configCreateOwnFolder) {
230
244
  await this.deleteDPsForEachAdapter(id);
231
245
  await this.deleteHtmlListDatapoints(id);
232
246
  } else {
233
247
  if (this.configSetAdapter && this.configSetAdapter[id]) {
234
248
  await this.createDPsForEachAdapter(id);
235
249
  // create HTML list datapoints
236
- if (!this.createHtmlList) {
250
+ if (!this.configCreateHtmlList) {
237
251
  await this.deleteHtmlListDatapoints(id);
238
252
  } else {
239
253
  await this.createHtmlListDatapoints(id);
@@ -247,25 +261,28 @@ class DeviceWatcher extends utils.Adapter {
247
261
  }
248
262
 
249
263
  // create HTML list datapoints
250
- if (!this.createHtmlList) {
264
+ if (!this.configCreateHtmlList) {
251
265
  await this.deleteHtmlListDatapoints();
266
+ await this.deleteHtmlListDatapointsInstances();
252
267
  } else {
253
268
  await this.createHtmlListDatapoints();
269
+ if (this.config.checkAdapterInstances) await this.createHtmlListDatapointsInstances();
254
270
  }
271
+ if (!this.config.checkAdapterInstances) await this.deleteHtmlListDatapointsInstances();
255
272
 
256
273
  // read data first at start
257
274
  // devices
258
275
  await this.main();
259
276
 
260
277
  // instances and adapters
261
- if (!this.config.checkAdapterInstances) {
262
- await this.deleteDPsForInstances();
263
- } else {
278
+ if (this.configCreateInstanceList) {
264
279
  // instances
265
280
  await this.createDPsForInstances();
266
281
  await this.getAllInstanceData();
267
282
  // adapter updates
268
283
  await this.createAdapterUpdateData();
284
+ } else {
285
+ await this.deleteDPsForInstances();
269
286
  }
270
287
 
271
288
  // update last contact data in interval
@@ -301,27 +318,41 @@ class DeviceWatcher extends utils.Adapter {
301
318
  */
302
319
  async onObjectChange(id, obj) {
303
320
  if (obj) {
304
- // The object was changed
305
- //this.log.warn(`object ${id} changed: ${JSON.stringify(obj)}`);
306
-
307
- //read new instance data and add it to the lists
308
- await this.getInstanceData(id);
321
+ try {
322
+ // The object was changed
323
+ //this.log.debug(`object ${id} changed: ${JSON.stringify(obj)}`);
309
324
 
310
- //read devices data and renew the lists
311
- await this.main();
325
+ if (id.startsWith('system.adapter.')) {
326
+ //read new instance data and add it to the lists
327
+ await this.getInstanceData(id);
328
+ } else {
329
+ //read devices data and renew the lists
330
+ await this.main();
331
+ }
332
+ } catch (error) {
333
+ this.log.error(`Issue at object change: ${error}`);
334
+ }
312
335
  } else {
313
- // The object was deleted
314
- //this.log.warn(`object ${id} deleted`);
336
+ try {
337
+ // The object was deleted
338
+ this.log.info(`object ${id} deleted`);
315
339
 
316
- // delete instance data in map
317
- this.listInstanceRaw.delete(id);
340
+ // delete instance data in map
341
+ if (this.listInstanceRaw.has(id)) {
342
+ this.listInstanceRaw.delete(id);
343
+ }
318
344
 
319
- // delete device data in map
320
- this.listAllDevicesRaw.delete(id);
345
+ // delete device data in map
346
+ if (this.listAllDevicesRaw.has(id)) {
347
+ this.listAllDevicesRaw.delete(id);
348
+ }
321
349
 
322
- //unsubscribe of Objects and states
323
- this.unsubscribeForeignObjects(id);
324
- this.unsubscribeForeignStates(id);
350
+ //unsubscribe of Objects and states
351
+ this.unsubscribeForeignObjects(id);
352
+ this.unsubscribeForeignStates(id);
353
+ } catch (error) {
354
+ this.log.error(`Issue at object deletion: ${error}`);
355
+ }
325
356
  }
326
357
  }
327
358
 
@@ -332,9 +363,10 @@ class DeviceWatcher extends utils.Adapter {
332
363
  */
333
364
  async onStateChange(id, state) {
334
365
  // Admin JSON for Adapter updates
335
- if (id && state) {
366
+ if (state) {
336
367
  // this.log.debug(`State changed: ${id} changed ${state.val}`);
337
368
  let batteryData;
369
+ let signalData;
338
370
  let oldLowBatState;
339
371
  let contactData;
340
372
  let oldStatus;
@@ -342,192 +374,212 @@ class DeviceWatcher extends utils.Adapter {
342
374
  let instanceStatusRaw;
343
375
  let oldInstanceHostState;
344
376
  let oldInstanceDeviceState;
377
+ let oldAdapterUpdatesCounts;
345
378
 
346
- for (const adapter of this.adapterUpdatesJsonRaw) {
347
- switch (id) {
348
- case adapter.Path:
349
- await this.getAdapterUpdateData(id);
350
- await this.createAdapterUpdateList();
351
- if (this.config.checkSendAdapterUpdateMsg) {
352
- await this.sendStateNotifications('updateAdapter', null);
379
+ try {
380
+ if (id.endsWith('updatesJson')) {
381
+ oldAdapterUpdatesCounts = this.countAdapterUpdates;
382
+ await this.getAdapterUpdateData(id);
383
+ await this.createAdapterUpdateList();
384
+ if (this.config.checkSendAdapterUpdateMsg && this.countAdapterUpdates > oldAdapterUpdatesCounts) {
385
+ await this.sendStateNotifications('updateAdapter', null);
386
+ }
387
+ for (const instance of this.listInstanceRaw.values()) {
388
+ if (this.adapterUpdatesJsonRaw.has(instance.Adapter)) {
389
+ for (const adapter of this.adapterUpdatesJsonRaw.values()) {
390
+ instance.updateAvailable = adapter.newVersion;
391
+ }
392
+ } else {
393
+ instance.updateAvailable = ' - ';
353
394
  }
395
+ }
354
396
  }
355
- }
356
397
 
357
- for (const [instance, instanceData] of this.listInstanceRaw) {
358
- switch (id) {
359
- case instanceData.instanceAlivePath:
360
- if (state.val !== instanceData.isAlive) {
361
- instanceStatusRaw = await this.setInstanceStatus(
362
- instanceData.instanceMode,
363
- instanceData.schedule,
364
- instanceData.instanceAlivePath,
365
- instanceData.connectedHostPath,
366
- instanceData.connectedDevicePath,
367
- );
368
- instanceData.isAlive = instanceStatusRaw[1];
369
- instanceData.status = instanceStatusRaw[0];
370
- instanceData.isHealthy = instanceStatusRaw[2];
371
- }
372
- break;
373
- case instanceData.connectedHostPath:
374
- oldInstanceHostState = instanceData.isConnectedHost;
375
- instanceData.isConnectedHost = state.val;
376
- if (oldInstanceHostState !== instanceData.isConnectedHost) {
377
- instanceStatusRaw = await this.setInstanceStatus(
378
- instanceData.instanceMode,
379
- instanceData.schedule,
380
- instanceData.instanceAlivePath,
381
- instanceData.connectedHostPath,
382
- instanceData.connectedDevicePath,
383
- );
384
- instanceData.isAlive = instanceStatusRaw[1];
385
- instanceData.status = instanceStatusRaw[0];
386
- instanceData.isHealthy = instanceStatusRaw[2];
387
-
388
- if (!instanceData.isAlive) continue;
389
- if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
390
- if (!instanceData.isHealthy) {
391
- await this.sendStateNotifications('errorInstance', instance);
398
+ for (const [instance, instanceData] of this.listInstanceRaw) {
399
+ switch (id) {
400
+ case instanceData.instanceAlivePath:
401
+ if (state.val !== instanceData.isAlive) {
402
+ instanceStatusRaw = await this.setInstanceStatus(
403
+ instanceData.instanceMode,
404
+ instanceData.schedule,
405
+ instanceData.instanceAlivePath,
406
+ instanceData.connectedHostPath,
407
+ instanceData.connectedDevicePath,
408
+ );
409
+ instanceData.isAlive = instanceStatusRaw[1];
410
+ instanceData.status = instanceStatusRaw[0];
411
+ instanceData.isHealthy = instanceStatusRaw[2];
412
+ }
413
+ break;
414
+ case instanceData.connectedHostPath:
415
+ oldInstanceHostState = instanceData.isConnectedHost;
416
+ instanceData.isConnectedHost = state.val;
417
+ if (oldInstanceHostState !== instanceData.isConnectedHost) {
418
+ instanceStatusRaw = await this.setInstanceStatus(
419
+ instanceData.instanceMode,
420
+ instanceData.schedule,
421
+ instanceData.instanceAlivePath,
422
+ instanceData.connectedHostPath,
423
+ instanceData.connectedDevicePath,
424
+ );
425
+ instanceData.isAlive = instanceStatusRaw[1];
426
+ instanceData.status = instanceStatusRaw[0];
427
+ instanceData.isHealthy = instanceStatusRaw[2];
428
+
429
+ if (!instanceData.isAlive) continue;
430
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
431
+ if (!instanceData.isHealthy) {
432
+ await this.sendStateNotifications('errorInstance', instance);
433
+ }
392
434
  }
393
435
  }
394
- }
395
- break;
396
- case instanceData.connectedDevicePath:
397
- oldInstanceDeviceState = instanceData.isConnectedDevice;
398
- instanceData.isConnectedDevice = state.val;
399
- if (oldInstanceDeviceState !== instanceData.isConnectedDevice) {
400
- instanceStatusRaw = await this.setInstanceStatus(
401
- instanceData.instanceMode,
402
- instanceData.schedule,
403
- instanceData.instanceAlivePath,
404
- instanceData.connectedHostPath,
405
- instanceData.connectedDevicePath,
406
- );
407
- instanceData.isAlive = instanceStatusRaw[1];
408
- instanceData.status = instanceStatusRaw[0];
409
- instanceData.isHealthy = instanceStatusRaw[2];
410
-
411
- if (!instanceData.isAlive) continue;
412
- if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
413
- if (!instanceData.isHealthy) {
414
- await this.sendStateNotifications('errorInstance', instance);
436
+ break;
437
+ case instanceData.connectedDevicePath:
438
+ oldInstanceDeviceState = instanceData.isConnectedDevice;
439
+ instanceData.isConnectedDevice = state.val;
440
+ if (oldInstanceDeviceState !== instanceData.isConnectedDevice) {
441
+ instanceStatusRaw = await this.setInstanceStatus(
442
+ instanceData.instanceMode,
443
+ instanceData.schedule,
444
+ instanceData.instanceAlivePath,
445
+ instanceData.connectedHostPath,
446
+ instanceData.connectedDevicePath,
447
+ );
448
+ instanceData.isAlive = instanceStatusRaw[1];
449
+ instanceData.status = instanceStatusRaw[0];
450
+ instanceData.isHealthy = instanceStatusRaw[2];
451
+
452
+ if (!instanceData.isAlive) continue;
453
+ if (this.config.checkSendInstanceFailedMsg && !this.blacklistInstancesNotify.includes(instanceData.instanceAlivePath)) {
454
+ if (!instanceData.isHealthy) {
455
+ await this.sendStateNotifications('errorInstance', instance);
456
+ }
415
457
  }
416
458
  }
417
- }
418
- break;
459
+ break;
460
+ }
419
461
  }
420
- }
421
462
 
422
- for (const [device, deviceData] of this.listAllDevicesRaw) {
423
- // On statechange update available datapoint
424
- switch (id) {
425
- case deviceData.instanceDeviceConnectionDP:
426
- if (state.val !== deviceData.instancedeviceConnected) {
427
- deviceData.instancedeviceConnected = state.val;
428
- }
429
- break;
463
+ for (const [device, deviceData] of this.listAllDevicesRaw) {
464
+ // On statechange update available datapoint
465
+ switch (id) {
466
+ case deviceData.instanceDeviceConnectionDP:
467
+ if (state.val !== deviceData.instancedeviceConnected) {
468
+ deviceData.instancedeviceConnected = state.val;
469
+ }
470
+ break;
430
471
 
431
- case deviceData.UpdateDP:
432
- if (state.val !== deviceData.Upgradable) {
433
- deviceData.Upgradable = state.val;
434
- if (state.val) {
435
- if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(deviceData.Path)) {
436
- await this.sendStateNotifications('updateDevice', device);
472
+ case deviceData.UpdateDP:
473
+ if (state.val !== deviceData.Upgradable) {
474
+ deviceData.Upgradable = state.val;
475
+ if (state.val === true || state.val === 1) {
476
+ if (this.config.checkSendDeviceUpgrade && !this.blacklistNotify.includes(deviceData.Path)) {
477
+ await this.sendStateNotifications('updateDevice', device);
478
+ }
437
479
  }
438
480
  }
439
- }
440
- break;
481
+ break;
441
482
 
442
- case deviceData.SignalStrengthDP:
443
- deviceData.SignalStrength = await this.calculateSignalStrength(state, deviceData.adapterID);
444
- break;
483
+ case deviceData.SignalStrengthDP:
484
+ signalData = await this.calculateSignalStrength(state, deviceData.adapterID);
485
+ deviceData.SignalStrength = signalData[0];
445
486
 
446
- case deviceData.batteryDP:
447
- if (deviceData.isBatteryDevice) {
448
- oldLowBatState = deviceData.LowBat;
449
- batteryData = await this.getBatteryData(state.val, oldLowBatState, deviceData.adapterID);
487
+ break;
450
488
 
451
- deviceData.Battery = batteryData[0];
452
- deviceData.BatteryRaw = batteryData[2];
453
- if (deviceData.LowBatDP !== 'none') {
454
- isLowBatValue = await this.getInitValue(deviceData.LowBatDP);
455
- } else {
456
- isLowBatValue = undefined;
457
- }
458
- deviceData.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, deviceData.faultReport, deviceData.adapterID);
489
+ case deviceData.batteryDP:
490
+ if (deviceData.isBatteryDevice) {
491
+ oldLowBatState = deviceData.LowBat;
492
+ batteryData = await this.getBatteryData(state.val, oldLowBatState, deviceData.faultReport, deviceData.adapterID);
459
493
 
460
- if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
461
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
462
- await this.sendStateNotifications('lowBatDevice', device);
494
+ deviceData.Battery = batteryData[0];
495
+ deviceData.BatteryRaw = batteryData[2];
496
+ deviceData.BatteryUnitRaw = batteryData[3];
497
+ if (deviceData.LowBatDP !== 'none') {
498
+ isLowBatValue = await this.getInitValue(deviceData.LowBatDP);
499
+ } else {
500
+ isLowBatValue = undefined;
501
+ }
502
+ deviceData.LowBat = await this.setLowbatIndicator(state.val, isLowBatValue, deviceData.faultReport, deviceData.adapterID);
503
+
504
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
505
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
506
+ await this.sendStateNotifications('lowBatDevice', device);
507
+ }
463
508
  }
464
509
  }
465
- }
466
- break;
510
+ break;
467
511
 
468
- case deviceData.LowBatDP:
469
- if (deviceData.isBatteryDevice) {
470
- oldLowBatState = deviceData.LowBat;
471
- batteryData = await this.getBatteryData(deviceData.BatteryRaw, state.val, deviceData.adapterID);
472
- deviceData.Battery = batteryData[0];
473
- deviceData.BatteryRaw = batteryData[2];
474
- deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
475
-
476
- if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
477
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
478
- await this.sendStateNotifications('lowBatDevice', device);
512
+ case deviceData.LowBatDP:
513
+ if (deviceData.isBatteryDevice) {
514
+ oldLowBatState = deviceData.LowBat;
515
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
516
+ deviceData.Battery = batteryData[0];
517
+ deviceData.BatteryRaw = batteryData[2];
518
+ deviceData.BatteryUnitRaw = batteryData[3];
519
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, state.val, deviceData.faultReport, deviceData.adapterID);
520
+
521
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
522
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
523
+ await this.sendStateNotifications('lowBatDevice', device);
524
+ }
479
525
  }
480
526
  }
481
- }
482
- break;
527
+ break;
483
528
 
484
- case deviceData.faultReportDP:
485
- if (deviceData.isBatteryDevice) {
486
- oldLowBatState = deviceData.LowBat;
487
- batteryData = await this.getBatteryData(deviceData.BatteryRaw, oldLowBatState, deviceData.adapterID);
529
+ case deviceData.faultReportDP:
530
+ if (deviceData.isBatteryDevice) {
531
+ oldLowBatState = deviceData.LowBat;
532
+ batteryData = await this.getBatteryData(deviceData.BatteryRaw, oldLowBatState, state.val, deviceData.adapterID);
488
533
 
489
- deviceData.Battery = batteryData[0];
490
- deviceData.BatteryRaw = batteryData[2];
491
- deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, undefined, state.val, deviceData.adapterID);
534
+ deviceData.Battery = batteryData[0];
535
+ deviceData.BatteryRaw = batteryData[2];
536
+ deviceData.BatteryUnitRaw = batteryData[3];
537
+ deviceData.LowBat = await this.setLowbatIndicator(deviceData.BatteryRaw, undefined, state.val, deviceData.adapterID);
492
538
 
493
- if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
494
- if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
495
- await this.sendStateNotifications('lowBatDevice', device);
539
+ if (deviceData.LowBat && oldLowBatState !== deviceData.LowBat) {
540
+ if (this.config.checkSendBatteryMsg && !this.blacklistNotify.includes(deviceData.Path)) {
541
+ await this.sendStateNotifications('lowBatDevice', device);
542
+ }
496
543
  }
497
544
  }
498
- }
499
- break;
545
+ break;
500
546
 
501
- case deviceData.UnreachDP:
502
- oldStatus = deviceData.Status;
503
- deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
504
- contactData = await this.getOnlineState(
505
- deviceData.timeSelector,
506
- deviceData.adapterID,
507
- deviceData.UnreachDP,
508
- deviceData.SignalStrength,
509
- deviceData.UnreachState,
510
- deviceData.DeviceStateSelectorDP,
511
- deviceData.rssiPeerSelectorDP,
512
- );
513
- if (contactData !== undefined) {
514
- deviceData.LastContact = contactData[0];
515
- deviceData.Status = contactData[1];
516
- deviceData.SignalStrength = contactData[2];
517
- }
518
- if (this.config.checkSendOfflineMsg && oldStatus !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
519
- if (deviceData.instanceDeviceConnectionDP !== undefined) {
520
- // check if the generally deviceData connected state is for a while true
521
- if (await this.getTimestampConnectionDP(deviceData.instanceDeviceConnectionDP, 20000)) {
547
+ case deviceData.UnreachDP:
548
+ oldStatus = deviceData.Status;
549
+ deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
550
+ contactData = await this.getOnlineState(
551
+ deviceData.timeSelector,
552
+ deviceData.adapterID,
553
+ deviceData.UnreachDP,
554
+ deviceData.SignalStrength,
555
+ deviceData.UnreachState,
556
+ deviceData.DeviceStateSelectorDP,
557
+ deviceData.rssiPeerSelectorDP,
558
+ );
559
+ if (contactData !== undefined) {
560
+ deviceData.LastContact = contactData[0];
561
+ deviceData.Status = contactData[1];
562
+ deviceData.SignalStrength = contactData[2];
563
+ }
564
+ if (this.config.checkSendOfflineMsg && oldStatus !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
565
+ if (deviceData.instanceDeviceConnectionDP !== undefined) {
566
+ // check if the generally deviceData connected state is for a while true
567
+ if (await this.getTimestampConnectionDP(deviceData.instanceDeviceConnectionDP, 20000)) {
568
+ await this.sendStateNotifications('onlineStateDevice', device);
569
+ }
570
+ } else {
522
571
  await this.sendStateNotifications('onlineStateDevice', device);
523
572
  }
524
- } else {
525
- await this.sendStateNotifications('onlineStateDevice', device);
526
573
  }
527
- }
528
- break;
574
+ break;
575
+ }
529
576
  }
577
+ } catch (error) {
578
+ this.log.error(`Issue at state change: ${error}`);
530
579
  }
580
+ } else {
581
+ // The state was deleted
582
+ this.log.debug(`state ${id} deleted`);
531
583
  }
532
584
  }
533
585
 
@@ -537,6 +589,7 @@ class DeviceWatcher extends utils.Adapter {
537
589
  onMessage(obj) {
538
590
  const devices = [];
539
591
  const instances = [];
592
+ const instancesTime = [];
540
593
  let countDevices = 0;
541
594
  let countInstances = 0;
542
595
 
@@ -562,10 +615,8 @@ class DeviceWatcher extends utils.Adapter {
562
615
  });
563
616
  this.sendTo(obj.from, obj.command, sortDevices, obj.callback);
564
617
  } catch (error) {
565
- this.sendTo(obj.from, obj.command, obj.callback);
618
+ this.errorReporting('[onMessage - deviceList for blacklisttable]', error);
566
619
  }
567
- } else {
568
- this.sendTo(obj.from, obj.command, obj.callback);
569
620
  }
570
621
  break;
571
622
 
@@ -590,10 +641,33 @@ class DeviceWatcher extends utils.Adapter {
590
641
  });
591
642
  this.sendTo(obj.from, obj.command, sortInstances, obj.callback);
592
643
  } catch (error) {
593
- this.sendTo(obj.from, obj.command, obj.callback);
644
+ this.errorReporting('[onMessage - instanceList]', error);
645
+ }
646
+ }
647
+ break;
648
+ case 'instancesListTime':
649
+ if (obj.message) {
650
+ try {
651
+ for (const instanceData of this.listInstanceRaw.values()) {
652
+ const label = `${instanceData.Adapter}: ${instanceData.InstanceName}`;
653
+ const valueObjectInstances = {
654
+ adapter: instanceData.Adapter,
655
+ instanceName: instanceData.InstanceName,
656
+ path: instanceData.instanceAlivePath,
657
+ };
658
+ instancesTime[countInstances] = { label: label, value: JSON.stringify(valueObjectInstances) };
659
+ countInstances++;
660
+ }
661
+ const sortInstances = instancesTime.slice(0);
662
+ sortInstances.sort(function (a, b) {
663
+ const x = a.label;
664
+ const y = b.label;
665
+ return x < y ? -1 : x > y ? 1 : 0;
666
+ });
667
+ this.sendTo(obj.from, obj.command, sortInstances, obj.callback);
668
+ } catch (error) {
669
+ this.errorReporting('[onMessage - instanceList]', error);
594
670
  }
595
- } else {
596
- this.sendTo(obj.from, obj.command, obj.callback);
597
671
  }
598
672
  break;
599
673
  }
@@ -618,7 +692,7 @@ class DeviceWatcher extends utils.Adapter {
618
692
  }
619
693
 
620
694
  // fill datapoints for each adapter if selected
621
- if (this.createOwnFolder) {
695
+ if (this.configCreateOwnFolder) {
622
696
  try {
623
697
  for (const [id] of Object.entries(arrApart)) {
624
698
  if (this.configSetAdapter && this.configSetAdapter[id]) {
@@ -644,13 +718,16 @@ class DeviceWatcher extends utils.Adapter {
644
718
  * is neccessary to refresh lastContact data, especially of devices without state changes
645
719
  */
646
720
  async refreshData() {
721
+ if (isUnloaded) return; // cancel run if unloaded was called.
647
722
  const nextTimeout = this.config.updateinterval * 1000;
648
723
 
724
+ // devices data
649
725
  await this.checkLastContact();
650
726
  await this.createLists();
651
727
  await this.writeDatapoints();
652
728
 
653
- if (this.createOwnFolder) {
729
+ // devices data in own adapter folder
730
+ if (this.configCreateOwnFolder) {
654
731
  for (const [id] of Object.entries(arrApart)) {
655
732
  if (this.configSetAdapter && this.configSetAdapter[id]) {
656
733
  await this.createLists(id);
@@ -660,26 +737,22 @@ class DeviceWatcher extends utils.Adapter {
660
737
  }
661
738
  }
662
739
 
663
- if (this.config.checkAdapterInstances) {
740
+ // instance and adapter data
741
+ if (this.configCreateInstanceList) {
664
742
  await this.createInstanceList();
665
743
  await this.writeInstanceDPs();
666
744
  }
667
745
 
668
746
  // Clear existing timeout
669
747
  if (this.refreshDataTimeout) {
670
- this.log.debug('clearing old refresh timeout');
671
748
  this.clearTimeout(this.refreshDataTimeout);
749
+ this.refreshDataTimeout = null;
672
750
  }
673
- if (!isUnloaded) {
674
- this.refreshDataTimeout = this.setTimeout(() => {
675
- this.log.debug('Updating Data');
676
751
 
677
- this.refreshDataTimeout = null;
678
- this.refreshData();
679
- }, nextTimeout);
680
- } else {
681
- return; // cancel run if unloaded was called.
682
- }
752
+ this.refreshDataTimeout = this.setTimeout(() => {
753
+ this.log.debug('Updating Data');
754
+ this.refreshData();
755
+ }, nextTimeout);
683
756
  } // <-- refreshData end
684
757
 
685
758
  /**
@@ -690,277 +763,327 @@ class DeviceWatcher extends utils.Adapter {
690
763
 
691
764
  // DEVICES
692
765
  const myBlacklist = this.config.tableBlacklist;
693
-
694
- for (const i in myBlacklist) {
695
- try {
696
- const blacklistParse = this.parseData(myBlacklist[i].devices);
697
- // push devices in list to ignor device in lists
698
- if (myBlacklist[i].checkIgnorLists) {
699
- this.blacklistLists.push(blacklistParse.path);
700
- }
701
- if (myBlacklist[i].checkIgnorAdapterLists) {
702
- this.blacklistAdapterLists.push(blacklistParse.path);
703
- }
704
- // push devices in list to ignor device in notifications
705
- if (myBlacklist[i].checkIgnorNotify) {
706
- this.blacklistNotify.push(blacklistParse.path);
766
+ if (myBlacklist.length >= 1) {
767
+ for (const i in myBlacklist) {
768
+ try {
769
+ const blacklistParse = this.parseData(myBlacklist[i].devices);
770
+ // push devices in list to ignor device in lists
771
+ if (myBlacklist[i].checkIgnorLists) {
772
+ this.blacklistLists.push(blacklistParse.path);
773
+ }
774
+ if (myBlacklist[i].checkIgnorAdapterLists) {
775
+ this.blacklistAdapterLists.push(blacklistParse.path);
776
+ }
777
+ // push devices in list to ignor device in notifications
778
+ if (myBlacklist[i].checkIgnorNotify) {
779
+ this.blacklistNotify.push(blacklistParse.path);
780
+ }
781
+ } catch (error) {
782
+ this.errorReporting('[createBlacklist]', error);
707
783
  }
708
- } catch (error) {
709
- this.errorReporting('[createBlacklist]', error);
784
+ if (this.blacklistLists.length >= 1) this.log.info(`Found devices/services on blacklist for lists: ${this.blacklistLists}`);
785
+ if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found devices/services on blacklist for lists: ${this.blacklistAdapterLists}`);
786
+ if (this.blacklistNotify.length >= 1) this.log.info(`Found devices/services on blacklist for notifications: ${this.blacklistNotify}`);
710
787
  }
711
788
  }
712
789
 
713
- if (this.blacklistLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistLists}`);
714
- if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistAdapterLists}`);
715
- if (this.blacklistNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistNotify}`);
716
-
717
790
  // INSTANCES
718
791
  const myBlacklistInstances = this.config.tableBlacklistInstances;
719
-
720
- for (const i in myBlacklistInstances) {
721
- try {
722
- const blacklistParse = this.parseData(myBlacklistInstances[i].instances);
723
- // push devices in list to ignor device in lists
724
- if (myBlacklistInstances[i].checkIgnorLists) {
725
- this.blacklistInstancesLists.push(blacklistParse.path);
726
- }
727
- // push devices in list to ignor device in notifications
728
- if (myBlacklistInstances[i].checkIgnorNotify) {
729
- this.blacklistInstancesNotify.push(blacklistParse.path);
792
+ if (myBlacklistInstances.length >= 1) {
793
+ for (const i in myBlacklistInstances) {
794
+ try {
795
+ const blacklistParse = this.parseData(myBlacklistInstances[i].instances);
796
+ // push devices in list to ignor device in lists
797
+ if (myBlacklistInstances[i].checkIgnorLists) {
798
+ this.blacklistInstancesLists.push(blacklistParse.path);
799
+ }
800
+ // push devices in list to ignor device in notifications
801
+ if (myBlacklistInstances[i].checkIgnorNotify) {
802
+ this.blacklistInstancesNotify.push(blacklistParse.path);
803
+ }
804
+ } catch (error) {
805
+ this.errorReporting('[createBlacklist]', error);
730
806
  }
731
- } catch (error) {
732
- this.errorReporting('[createBlacklist]', error);
733
807
  }
808
+ if (this.blacklistInstancesLists.length >= 1) this.log.info(`Found instances items on blacklist for lists: ${this.blacklistInstancesLists}`);
809
+ if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found instances items on blacklist for notifications: ${this.blacklistInstancesNotify}`);
734
810
  }
735
-
736
- if (this.blacklistInstancesLists.length >= 1) this.log.info(`Found items on blacklist for lists: ${this.blacklistInstancesLists}`);
737
- if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found items on blacklist for notifications: ${this.blacklistInstancesNotify}`);
738
-
739
811
  this.log.debug(`Function finished: ${this.createBlacklist.name}`);
740
812
  }
741
813
 
814
+ /**
815
+ * create list with time for instances
816
+ */
817
+ async createTimeListInstances() {
818
+ // INSTANCES
819
+ const userTimeListInstances = this.config.tableTimeInstance;
820
+ if (userTimeListInstances.length >= 1) {
821
+ for (const i in userTimeListInstances) {
822
+ try {
823
+ const userTimeListparse = this.parseData(userTimeListInstances[i].instancesTime);
824
+ // push devices in list to ignor device in lists
825
+ if (userTimeListInstances[i].errorTime) {
826
+ this.userTimeInstancesList.set(userTimeListparse.path, {
827
+ instanceName: userTimeListparse.instanceName,
828
+ errorTime: userTimeListInstances[i].errorTime,
829
+ });
830
+ }
831
+ } catch (error) {
832
+ this.errorReporting('[createTimeListInstances]', error);
833
+ }
834
+ }
835
+ if (this.userTimeInstancesList.size >= 1) this.log.info(`Found instances items on lists for timesettings: ${this.blacklistInstancesLists}`);
836
+ }
837
+ }
838
+
742
839
  /**
743
840
  * @param {object} i - Device Object
744
841
  */
745
842
  async createData(i) {
746
- const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
747
- const adapterID = this.selAdapter[i].adapterID;
843
+ try {
844
+ const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
845
+ const adapterID = this.selAdapter[i].adapterID;
748
846
 
749
- /*---------- Start of loop ----------*/
750
- for (const [id] of Object.entries(devices)) {
751
- /*=============================================
847
+ /*---------- Start of loop ----------*/
848
+ for (const [id] of Object.entries(devices)) {
849
+ /*=============================================
752
850
  = get Instanz =
753
851
  =============================================*/
754
- const instance = id.slice(0, id.indexOf('.') + 2);
755
- const instanceDeviceConnectionDP = `${instance}.info.connection`;
756
- const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
757
- this.subscribeForeignStates(instanceDeviceConnectionDP);
758
- this.subscribeForeignObjectsAsync(`${this.selAdapter[i].Selektor}`);
852
+ const instance = id.slice(0, id.indexOf('.') + 2);
853
+ if (id.endsWith('.')) continue; // ! Test - sometimes id's are wrong or has no name so break up here.
759
854
 
760
- /*=============================================
855
+ const instanceDeviceConnectionDP = `${instance}.info.connection`;
856
+ const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
857
+ this.subscribeForeignStates(instanceDeviceConnectionDP);
858
+ this.subscribeForeignObjects(`${this.selAdapter[i].Selektor}`);
859
+
860
+ /*=============================================
761
861
  = Get device name =
762
862
  =============================================*/
763
- const deviceName = await this.getDeviceName(id, i);
863
+ const deviceName = await this.getDeviceName(id, i);
764
864
 
765
- /*=============================================
865
+ /*=============================================
766
866
  = Get adapter name =
767
867
  =============================================*/
768
- const adapter = this.selAdapter[i].adapter;
868
+ const adapter = this.selAdapter[i].adapter;
769
869
 
770
- /*=============================================
870
+ /*=============================================
771
871
  = Get path to datapoints =
772
872
  =============================================*/
773
- const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
774
- const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
873
+ const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
874
+ const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
775
875
 
776
- // subscribe to object device path
777
- this.subscribeForeignObjectsAsync(currDeviceString);
876
+ // subscribe to object device path
877
+ this.subscribeForeignObjects(currDeviceString);
778
878
 
779
- /*=============================================
879
+ /*=============================================
780
880
  = Get signal strength =
781
881
  =============================================*/
782
- let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
783
- let deviceQualityState;
882
+ let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
883
+ let deviceQualityState;
784
884
 
785
- switch (adapterID) {
786
- case 'mihomeVacuum':
787
- deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
788
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
789
- break;
885
+ switch (adapterID) {
886
+ case 'mihomeVacuum':
887
+ deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
888
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
889
+ break;
790
890
 
791
- case 'netatmo':
792
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
793
- if (!deviceQualityState) {
794
- deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
891
+ case 'netatmo':
795
892
  deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
796
- }
797
- break;
893
+ if (!deviceQualityState) {
894
+ deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
895
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
896
+ }
897
+ break;
798
898
 
799
- default:
800
- deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
801
- break;
802
- }
803
- //subscribe to states
804
- this.subscribeForeignStates(deviceQualityDP);
899
+ default:
900
+ deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
901
+ break;
902
+ }
903
+ //subscribe to states
904
+ this.subscribeForeignStates(deviceQualityDP);
805
905
 
806
- let linkQuality = await this.calculateSignalStrength(deviceQualityState, adapterID);
906
+ const signalData = await this.calculateSignalStrength(deviceQualityState, adapterID);
907
+ let linkQuality = signalData[0];
908
+ const linkQualityRaw = signalData[1];
807
909
 
808
- /*=============================================
910
+ /*=============================================
809
911
  = Get battery data =
810
912
  =============================================*/
811
- let deviceBatteryStateDP;
812
- let deviceBatteryState;
813
- let batteryHealth;
814
- let batteryHealthRaw;
815
- let lowBatIndicator;
816
- let isBatteryDevice;
817
- let isLowBatDP;
818
- let faultReportingDP;
819
- let faultReportingState;
820
-
821
- const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
822
- const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
823
-
824
- if (deviceChargerState === undefined || deviceChargerState === false) {
825
- // Get battery states
826
- switch (adapterID) {
827
- case 'hueExt':
828
- case 'mihomeVacuum':
829
- case 'mqttNuki':
830
- deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
831
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
832
- if (deviceBatteryState === undefined) {
833
- deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
913
+ let deviceBatteryStateDP;
914
+ let deviceBatteryState;
915
+ let batteryHealth;
916
+ let batteryHealthRaw;
917
+ let batteryUnitRaw;
918
+ let lowBatIndicator;
919
+ let isBatteryDevice;
920
+ let isLowBatDP;
921
+ let faultReportingDP;
922
+ let faultReportingState;
923
+
924
+ const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
925
+ const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
926
+
927
+ if (deviceChargerState === undefined || deviceChargerState === false) {
928
+ // Get battery states
929
+ switch (adapterID) {
930
+ case 'hmrpc':
931
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
834
932
  deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
835
- }
836
- break;
837
- default:
838
- deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
839
- deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
840
- if (deviceBatteryState === undefined) {
841
- deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
933
+ if (deviceBatteryState === undefined) {
934
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].hmDNBattery;
935
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
936
+ }
937
+ break;
938
+ case 'hueExt':
939
+ case 'mihomeVacuum':
940
+ case 'mqttNuki':
941
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
842
942
  deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
843
- }
844
- break;
845
- }
943
+ if (deviceBatteryState === undefined) {
944
+ deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
945
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
946
+ }
947
+ break;
948
+ default:
949
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
950
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
951
+ if (deviceBatteryState === undefined) {
952
+ deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
953
+ deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
954
+ }
955
+ break;
956
+ }
846
957
 
847
- // Get low bat states
848
- isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
849
- let deviceLowBatState = await this.getInitValue(isLowBatDP);
850
- if (deviceLowBatState === undefined) {
851
- isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
852
- deviceLowBatState = await this.getInitValue(isLowBatDP);
853
- }
854
- if (deviceLowBatState === undefined) isLowBatDP = 'none';
958
+ // Get low bat states
959
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
960
+ let deviceLowBatState = await this.getInitValue(isLowBatDP);
961
+ if (deviceLowBatState === undefined) {
962
+ isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
963
+ deviceLowBatState = await this.getInitValue(isLowBatDP);
964
+ }
965
+ if (deviceLowBatState === undefined) isLowBatDP = 'none';
855
966
 
856
- faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
857
- faultReportingState = await this.getInitValue(faultReportingDP);
967
+ faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
968
+ faultReportingState = await this.getInitValue(faultReportingDP);
858
969
 
859
- //subscribe to states
860
- this.subscribeForeignStates(deviceBatteryStateDP);
861
- this.subscribeForeignStates(isLowBatDP);
862
- this.subscribeForeignStates(faultReportingDP);
970
+ //subscribe to states
971
+ this.subscribeForeignStates(deviceBatteryStateDP);
972
+ this.subscribeForeignStates(isLowBatDP);
973
+ this.subscribeForeignStates(faultReportingDP);
863
974
 
864
- const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, adapterID);
865
- batteryHealth = batteryData[0];
866
- batteryHealthRaw = batteryData[2];
867
- isBatteryDevice = batteryData[1];
975
+ const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
976
+ batteryHealth = batteryData[0];
977
+ batteryHealthRaw = batteryData[2];
978
+ batteryUnitRaw = batteryData[3];
979
+ isBatteryDevice = batteryData[1];
868
980
 
869
- if (isBatteryDevice) {
870
- lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
981
+ if (isBatteryDevice) {
982
+ lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
983
+ }
871
984
  }
872
- }
873
985
 
874
- /*=============================================
986
+ /*=============================================
875
987
  = Get last contact of device =
876
988
  =============================================*/
877
- let unreachDP = currDeviceString + this.selAdapter[i].reach;
878
- const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
879
- const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
880
- const timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
881
-
882
- let deviceUnreachState = await this.getInitValue(unreachDP);
883
- if (deviceUnreachState === undefined) {
884
- unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
885
- deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
886
- }
887
-
888
- // subscribe to states
889
- this.subscribeForeignStates(timeSelector);
890
- this.subscribeForeignStates(unreachDP);
891
- this.subscribeForeignStates(deviceStateSelectorDP);
892
- this.subscribeForeignStates(rssiPeerSelectorDP);
893
-
894
- const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
895
- let deviceState;
896
- let lastContactString;
989
+ let unreachDP = currDeviceString + this.selAdapter[i].reach;
990
+ const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
991
+ const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
992
+ const timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
993
+
994
+ let deviceUnreachState = await this.getInitValue(unreachDP);
995
+ if (deviceUnreachState === undefined) {
996
+ unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
997
+ deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
998
+ }
897
999
 
898
- if (onlineState) {
899
- lastContactString = onlineState[0];
900
- deviceState = onlineState[1];
901
- linkQuality = onlineState[2];
902
- }
1000
+ // subscribe to states
1001
+ this.subscribeForeignStates(timeSelector);
1002
+ this.subscribeForeignStates(unreachDP);
1003
+ this.subscribeForeignStates(deviceStateSelectorDP);
1004
+ this.subscribeForeignStates(rssiPeerSelectorDP);
1005
+
1006
+ const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
1007
+ let deviceState;
1008
+ let lastContactString;
1009
+
1010
+ if (onlineState) {
1011
+ lastContactString = onlineState[0];
1012
+ deviceState = onlineState[1];
1013
+ linkQuality = onlineState[2];
1014
+ }
903
1015
 
904
- /*=============================================
1016
+ /*=============================================
905
1017
  = Get update data =
906
1018
  =============================================*/
907
- const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
908
- let isUpgradable;
1019
+ const deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
1020
+ let isUpgradable;
909
1021
 
910
- if (this.config.checkSendDeviceUpgrade) {
911
- const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
1022
+ if (this.config.checkSendDeviceUpgrade) {
1023
+ const deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
912
1024
 
913
- if (deviceUpdateSelector) {
914
- isUpgradable = true;
915
- } else if (!deviceUpdateSelector) {
916
- isUpgradable = false;
1025
+ if (deviceUpdateSelector !== undefined) {
1026
+ if (deviceUpdateSelector) {
1027
+ isUpgradable = true;
1028
+ } else if (!deviceUpdateSelector) {
1029
+ isUpgradable = false;
1030
+ }
1031
+ } else {
1032
+ isUpgradable = ' - ';
1033
+ }
1034
+
1035
+ // subscribe to states
1036
+ this.subscribeForeignStates(deviceUpdateDP);
917
1037
  }
918
- // subscribe to states
919
- this.subscribeForeignStates(deviceUpdateDP);
920
- }
921
1038
 
922
- /*=============================================
1039
+ /*=============================================
923
1040
  = Fill Raw Lists =
924
1041
  =============================================*/
925
- const setupList = () => {
926
- this.listAllDevicesRaw.set(currDeviceString, {
927
- Path: id,
928
- instanceDeviceConnectionDP: instanceDeviceConnectionDP,
929
- instancedeviceConnected: instancedeviceConnected,
930
- Device: deviceName,
931
- adapterID: adapterID,
932
- Adapter: adapter,
933
- timeSelector: timeSelector,
934
- isBatteryDevice: isBatteryDevice,
935
- Battery: batteryHealth,
936
- BatteryRaw: batteryHealthRaw,
937
- batteryDP: deviceBatteryStateDP,
938
- LowBat: lowBatIndicator,
939
- LowBatDP: isLowBatDP,
940
- faultReport: faultReportingState,
941
- faultReportDP: faultReportingDP,
942
- SignalStrengthDP: deviceQualityDP,
943
- SignalStrength: linkQuality,
944
- UnreachState: deviceUnreachState,
945
- UnreachDP: unreachDP,
946
- DeviceStateSelectorDP: deviceStateSelectorDP,
947
- rssiPeerSelectorDP: rssiPeerSelectorDP,
948
- LastContact: lastContactString,
949
- Status: deviceState,
950
- UpdateDP: deviceUpdateDP,
951
- Upgradable: isUpgradable,
952
- });
953
- };
1042
+ const setupList = () => {
1043
+ this.listAllDevicesRaw.set(currDeviceString, {
1044
+ Path: id,
1045
+ instanceDeviceConnectionDP: instanceDeviceConnectionDP,
1046
+ instancedeviceConnected: instancedeviceConnected,
1047
+ instance: instance,
1048
+ Device: deviceName,
1049
+ adapterID: adapterID,
1050
+ Adapter: adapter,
1051
+ timeSelector: timeSelector,
1052
+ isBatteryDevice: isBatteryDevice,
1053
+ Battery: batteryHealth,
1054
+ BatteryRaw: batteryHealthRaw,
1055
+ BatteryUnitRaw: batteryUnitRaw,
1056
+ batteryDP: deviceBatteryStateDP,
1057
+ LowBat: lowBatIndicator,
1058
+ LowBatDP: isLowBatDP,
1059
+ faultReport: faultReportingState,
1060
+ faultReportDP: faultReportingDP,
1061
+ SignalStrengthDP: deviceQualityDP,
1062
+ SignalStrength: linkQuality,
1063
+ SignalStrengthRaw: linkQualityRaw,
1064
+ UnreachState: deviceUnreachState,
1065
+ UnreachDP: unreachDP,
1066
+ DeviceStateSelectorDP: deviceStateSelectorDP,
1067
+ rssiPeerSelectorDP: rssiPeerSelectorDP,
1068
+ LastContact: lastContactString,
1069
+ Status: deviceState,
1070
+ UpdateDP: deviceUpdateDP,
1071
+ Upgradable: isUpgradable,
1072
+ });
1073
+ };
954
1074
 
955
- if (!this.listOnlyBattery) {
956
- // Add all devices
957
- setupList();
958
- } else {
959
- // Add only devices with battery in the rawlist
960
- if (!isBatteryDevice) continue;
961
- setupList();
962
- }
963
- } // <-- end of loop
1075
+ if (!this.configListOnlyBattery) {
1076
+ // Add all devices
1077
+ setupList();
1078
+ } else {
1079
+ // Add only devices with battery in the rawlist
1080
+ if (!isBatteryDevice) continue;
1081
+ setupList();
1082
+ }
1083
+ } // <-- end of loop
1084
+ } catch (error) {
1085
+ this.errorReporting('[createData - create data of devices]', error);
1086
+ }
964
1087
  } // <-- end of createData
965
1088
 
966
1089
  /*=============================================
@@ -972,11 +1095,13 @@ class DeviceWatcher extends utils.Adapter {
972
1095
  * @param {object} i - each Device
973
1096
  */
974
1097
  async getDeviceName(id, i) {
975
- const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
976
- const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
977
- const shortshortCurrDeviceString = shortCurrDeviceString.slice(0, shortCurrDeviceString.lastIndexOf('.') + 1 - 1);
978
-
979
1098
  try {
1099
+ //id = id.replace(/[\]\\[.*,;'"`<>\\\s?]/g, '-');
1100
+
1101
+ const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
1102
+ const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
1103
+ const shortshortCurrDeviceString = shortCurrDeviceString.slice(0, shortCurrDeviceString.lastIndexOf('.') + 1 - 1);
1104
+
980
1105
  // Get device name
981
1106
  const deviceObject = await this.getForeignObjectAsync(currDeviceString);
982
1107
  const shortDeviceObject = await this.getForeignObjectAsync(shortCurrDeviceString);
@@ -1062,6 +1187,7 @@ class DeviceWatcher extends utils.Adapter {
1062
1187
  */
1063
1188
  async calculateSignalStrength(deviceQualityState, adapterID) {
1064
1189
  let linkQuality;
1190
+ let linkQualityRaw;
1065
1191
  let mqttNukiValue;
1066
1192
 
1067
1193
  if (deviceQualityState != null) {
@@ -1075,6 +1201,7 @@ class DeviceWatcher extends utils.Adapter {
1075
1201
  case 'sonoff':
1076
1202
  case 'smartgarden':
1077
1203
  linkQuality = deviceQualityState.val + '%'; // If quality state is already an percent value
1204
+ linkQualityRaw = deviceQualityState.val;
1078
1205
  break;
1079
1206
  case 'lupusec':
1080
1207
  linkQuality = deviceQualityState.val;
@@ -1086,9 +1213,12 @@ class DeviceWatcher extends utils.Adapter {
1086
1213
  linkQuality = ' - ';
1087
1214
  } else if (deviceQualityState.val < 0) {
1088
1215
  linkQuality = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100) + '%';
1216
+ linkQualityRaw = Math.min(Math.max(2 * (deviceQualityState.val + 100), 0), 100);
1217
+
1089
1218
  // If Quality State is an value between 0-255 (zigbee) calculate in percent:
1090
1219
  } else if (deviceQualityState.val >= 0) {
1091
1220
  linkQuality = parseFloat(((100 / 255) * deviceQualityState.val).toFixed(0)) + '%';
1221
+ linkQualityRaw = parseFloat(((100 / 255) * deviceQualityState.val).toFixed(0));
1092
1222
  }
1093
1223
  break;
1094
1224
  }
@@ -1111,7 +1241,7 @@ class DeviceWatcher extends utils.Adapter {
1111
1241
  linkQuality = deviceQualityState.val;
1112
1242
  } else if (mqttNukiValue < 0) {
1113
1243
  linkQuality = Math.min(Math.max(2 * (mqttNukiValue + 100), 0), 100) + '%';
1114
- // If Quality State is an value between 0-255 (zigbee) calculate in percent:
1244
+ linkQualityRaw = Math.min(Math.max(2 * (mqttNukiValue + 100), 0), 100);
1115
1245
  }
1116
1246
  }
1117
1247
  break;
@@ -1119,24 +1249,33 @@ class DeviceWatcher extends utils.Adapter {
1119
1249
  } else {
1120
1250
  linkQuality = ' - ';
1121
1251
  }
1122
- return linkQuality;
1252
+ return [linkQuality, linkQualityRaw];
1123
1253
  }
1124
1254
 
1125
1255
  /**
1126
1256
  * get battery data
1127
1257
  * @param {object} deviceBatteryState - State value
1128
1258
  * @param {object} deviceLowBatState - State value
1259
+ * @param {object} faultReportingState - State value
1129
1260
  * @param {object} adapterID - adapter name
1130
1261
  */
1131
- async getBatteryData(deviceBatteryState, deviceLowBatState, adapterID) {
1262
+ async getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID) {
1132
1263
  let batteryHealthRaw;
1264
+ let batteryHealthUnitRaw;
1133
1265
  let batteryHealth;
1134
1266
  let isBatteryDevice;
1135
1267
 
1136
1268
  switch (adapterID) {
1137
1269
  case 'hmrpc':
1138
1270
  if (deviceBatteryState === undefined) {
1139
- if (deviceLowBatState !== undefined) {
1271
+ if (faultReportingState !== undefined) {
1272
+ if (faultReportingState !== 6) {
1273
+ batteryHealth = 'ok';
1274
+ } else {
1275
+ batteryHealth = 'low';
1276
+ }
1277
+ isBatteryDevice = true;
1278
+ } else if (deviceLowBatState !== undefined) {
1140
1279
  if (deviceLowBatState !== 1) {
1141
1280
  batteryHealth = 'ok';
1142
1281
  } else {
@@ -1152,6 +1291,7 @@ class DeviceWatcher extends utils.Adapter {
1152
1291
  } else {
1153
1292
  batteryHealth = deviceBatteryState + 'V';
1154
1293
  batteryHealthRaw = deviceBatteryState;
1294
+ batteryHealthUnitRaw = 'V';
1155
1295
  isBatteryDevice = true;
1156
1296
  }
1157
1297
  }
@@ -1171,12 +1311,13 @@ class DeviceWatcher extends utils.Adapter {
1171
1311
  } else {
1172
1312
  batteryHealth = deviceBatteryState + '%';
1173
1313
  batteryHealthRaw = deviceBatteryState;
1314
+ batteryHealthUnitRaw = '%';
1174
1315
  isBatteryDevice = true;
1175
1316
  }
1176
1317
  break;
1177
1318
  }
1178
1319
 
1179
- return [batteryHealth, isBatteryDevice, batteryHealthRaw];
1320
+ return [batteryHealth, isBatteryDevice, batteryHealthRaw, batteryHealthUnitRaw];
1180
1321
  }
1181
1322
 
1182
1323
  /**
@@ -1263,162 +1404,162 @@ class DeviceWatcher extends utils.Adapter {
1263
1404
 
1264
1405
  try {
1265
1406
  const deviceTimeSelector = await this.getForeignStateAsync(timeSelector);
1266
- if (deviceTimeSelector) {
1267
- const deviceUnreachSelector = await this.getForeignStateAsync(unreachDP);
1268
- const deviceStateSelector = await this.getForeignStateAsync(deviceStateSelectorDP); // for hmrpc devices
1269
- const rssiPeerSelector = await this.getForeignStateAsync(rssiPeerSelectorDP);
1270
- const lastContact = this.getTimestamp(deviceTimeSelector.ts);
1271
- const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? this.getTimestamp(deviceUnreachSelector.lc) : this.getTimestamp(timeSelector.ts);
1272
- // If there is no contact since user sets minutes add device in offline list
1273
- // calculate to days after 48 hours
1274
- switch (unreachDP) {
1275
- case 'none':
1276
- lastContactString = await this.getLastContact(deviceTimeSelector.ts);
1277
- break;
1407
+ const deviceUnreachSelector = await this.getForeignStateAsync(unreachDP);
1408
+ const deviceStateSelector = await this.getForeignStateAsync(deviceStateSelectorDP); // for hmrpc devices
1409
+ const rssiPeerSelector = await this.getForeignStateAsync(rssiPeerSelectorDP);
1410
+ const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? this.getTimestamp(deviceUnreachSelector.lc) : this.getTimestamp(timeSelector.ts);
1411
+ // If there is no contact since user sets minutes add device in offline list
1412
+ // calculate to days after 48 hours
1413
+ switch (unreachDP) {
1414
+ case 'none':
1415
+ if (deviceTimeSelector) lastContactString = await this.getLastContact(deviceTimeSelector.ts);
1416
+ break;
1278
1417
 
1279
- default:
1280
- //State changed
1281
- if (adapterID === 'hmrpc') {
1282
- if (linkQuality !== ' - ') {
1283
- if (deviceUnreachState === 1) {
1284
- lastContactString = await this.getLastContact(deviceTimeSelector.lc);
1285
- } else {
1286
- lastContactString = await this.getLastContact(deviceTimeSelector.ts);
1287
- }
1288
- } else {
1289
- if (deviceStateSelector) {
1290
- // because old hm devices don't send rssi states
1291
- lastContactString = await this.getLastContact(deviceStateSelector.ts);
1292
- } else if (rssiPeerSelector) {
1293
- // because old hm sensors don't send rssi/state values
1294
- lastContactString = await this.getLastContact(rssiPeerSelector.ts);
1295
- }
1296
- }
1297
- } else {
1298
- if (deviceUnreachState === 0) {
1418
+ default:
1419
+ //State changed
1420
+ if (adapterID === 'hmrpc') {
1421
+ if (linkQuality !== ' - ' && deviceTimeSelector) {
1422
+ if (deviceUnreachState === 1) {
1299
1423
  lastContactString = await this.getLastContact(deviceTimeSelector.lc);
1300
1424
  } else {
1301
1425
  lastContactString = await this.getLastContact(deviceTimeSelector.ts);
1302
1426
  }
1303
- break;
1427
+ } else {
1428
+ if (deviceStateSelector) {
1429
+ // because old hm devices don't send rssi states
1430
+ lastContactString = await this.getLastContact(deviceStateSelector.ts);
1431
+ } else if (rssiPeerSelector) {
1432
+ // because old hm sensors don't send rssi/state values
1433
+ lastContactString = await this.getLastContact(rssiPeerSelector.ts);
1434
+ }
1304
1435
  }
1305
- }
1436
+ } else {
1437
+ if (deviceUnreachState === 0 && deviceTimeSelector) {
1438
+ lastContactString = await this.getLastContact(deviceTimeSelector.lc);
1439
+ } else {
1440
+ if (deviceTimeSelector) lastContactString = await this.getLastContact(deviceTimeSelector.ts);
1441
+ }
1442
+ break;
1443
+ }
1444
+ }
1306
1445
 
1307
- /*=============================================
1446
+ /*=============================================
1308
1447
  = Set Online Status =
1309
1448
  =============================================*/
1310
- if (this.configMaxMinutes !== undefined) {
1311
- switch (adapterID) {
1312
- case 'hmrpc':
1313
- if (this.configMaxMinutes[adapterID] <= 0) {
1314
- if (deviceUnreachState === 1) {
1315
- deviceState = 'Offline'; //set online state to offline
1316
- linkQuality = '0%'; // set linkQuality to nothing
1317
- }
1318
- } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState === 1) {
1449
+ let lastContact;
1450
+ if (deviceTimeSelector) lastContact = this.getTimestamp(deviceTimeSelector.ts);
1451
+
1452
+ if (this.configMaxMinutes !== undefined) {
1453
+ switch (adapterID) {
1454
+ case 'hmrpc':
1455
+ if (this.configMaxMinutes[adapterID] <= 0) {
1456
+ if (deviceUnreachState === 1) {
1319
1457
  deviceState = 'Offline'; //set online state to offline
1320
1458
  linkQuality = '0%'; // set linkQuality to nothing
1321
1459
  }
1322
- break;
1323
- case 'proxmox':
1324
- if (this.configMaxMinutes[adapterID] <= 0) {
1325
- if (deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1326
- deviceState = 'Offline'; //set online state to offline
1327
- }
1328
- } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1460
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState === 1) {
1461
+ deviceState = 'Offline'; //set online state to offline
1462
+ linkQuality = '0%'; // set linkQuality to nothing
1463
+ }
1464
+ break;
1465
+ case 'proxmox':
1466
+ if (this.configMaxMinutes[adapterID] <= 0) {
1467
+ if (deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1468
+ deviceState = 'Offline'; //set online state to offline
1469
+ }
1470
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState !== 'running' && deviceUnreachState !== 'online') {
1471
+ deviceState = 'Offline'; //set online state to offline
1472
+ linkQuality = '0%'; // set linkQuality to nothing
1473
+ }
1474
+ break;
1475
+ case 'hmiP':
1476
+ case 'maxcube':
1477
+ if (this.configMaxMinutes[adapterID] <= 0) {
1478
+ if (deviceUnreachState) {
1329
1479
  deviceState = 'Offline'; //set online state to offline
1330
1480
  linkQuality = '0%'; // set linkQuality to nothing
1331
1481
  }
1332
- break;
1333
- case 'hmiP':
1334
- case 'maxcube':
1335
- if (this.configMaxMinutes[adapterID] <= 0) {
1336
- if (deviceUnreachState) {
1337
- deviceState = 'Offline'; //set online state to offline
1338
- linkQuality = '0%'; // set linkQuality to nothing
1339
- }
1340
- } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState) {
1482
+ } else if (lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID] && deviceUnreachState) {
1483
+ deviceState = 'Offline'; //set online state to offline
1484
+ linkQuality = '0%'; // set linkQuality to nothing
1485
+ }
1486
+ break;
1487
+ case 'apcups':
1488
+ case 'hue':
1489
+ case 'hueExt':
1490
+ case 'ping':
1491
+ case 'deconz':
1492
+ case 'shelly':
1493
+ case 'sonoff':
1494
+ case 'unifi':
1495
+ case 'zigbee':
1496
+ case 'zigbee2MQTT':
1497
+ if (this.configMaxMinutes[adapterID] <= 0) {
1498
+ if (!deviceUnreachState) {
1341
1499
  deviceState = 'Offline'; //set online state to offline
1342
1500
  linkQuality = '0%'; // set linkQuality to nothing
1343
1501
  }
1344
- break;
1345
- case 'apcups':
1346
- case 'hue':
1347
- case 'hueExt':
1348
- case 'ping':
1349
- case 'deconz':
1350
- case 'shelly':
1351
- case 'sonoff':
1352
- case 'unifi':
1353
- case 'zigbee':
1354
- case 'zigbee2MQTT':
1355
- if (this.configMaxMinutes[adapterID] <= 0) {
1356
- if (!deviceUnreachState) {
1357
- deviceState = 'Offline'; //set online state to offline
1358
- linkQuality = '0%'; // set linkQuality to nothing
1359
- }
1360
- } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1502
+ } else if (!deviceUnreachState && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1503
+ deviceState = 'Offline'; //set online state to offline
1504
+ linkQuality = '0%'; // set linkQuality to nothing
1505
+ }
1506
+ break;
1507
+ case 'mqttClientZigbee2Mqtt':
1508
+ if (this.configMaxMinutes[adapterID] <= 0) {
1509
+ if (deviceUnreachState !== 'online') {
1361
1510
  deviceState = 'Offline'; //set online state to offline
1362
1511
  linkQuality = '0%'; // set linkQuality to nothing
1363
1512
  }
1364
- break;
1365
- case 'mqttClientZigbee2Mqtt':
1513
+ } else if (deviceUnreachState !== 'online' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1514
+ deviceState = 'Offline'; //set online state to offline
1515
+ linkQuality = '0%'; // set linkQuality to nothing
1516
+ }
1517
+ break;
1518
+ case 'mihome':
1519
+ if (deviceUnreachState !== undefined) {
1366
1520
  if (this.configMaxMinutes[adapterID] <= 0) {
1367
- if (deviceUnreachState !== 'online') {
1521
+ if (!deviceUnreachState) {
1368
1522
  deviceState = 'Offline'; //set online state to offline
1369
1523
  linkQuality = '0%'; // set linkQuality to nothing
1370
1524
  }
1371
- } else if (deviceUnreachState !== 'online' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1525
+ } else if (lastContact && lastContact > this.configMaxMinutes[adapterID]) {
1372
1526
  deviceState = 'Offline'; //set online state to offline
1373
1527
  linkQuality = '0%'; // set linkQuality to nothing
1374
1528
  }
1375
- break;
1376
- case 'mihome':
1377
- if (deviceUnreachState !== undefined) {
1529
+ } else {
1530
+ if (this.config.mihomeMaxMinutes <= 0) {
1378
1531
  if (this.configMaxMinutes[adapterID] <= 0) {
1379
- if (!deviceUnreachState) {
1380
- deviceState = 'Offline'; //set online state to offline
1381
- linkQuality = '0%'; // set linkQuality to nothing
1382
- }
1383
- } else if (lastContact > this.configMaxMinutes[adapterID]) {
1384
1532
  deviceState = 'Offline'; //set online state to offline
1385
1533
  linkQuality = '0%'; // set linkQuality to nothing
1386
1534
  }
1387
- } else {
1388
- if (this.config.mihomeMaxMinutes <= 0) {
1389
- if (this.configMaxMinutes[adapterID] <= 0) {
1390
- deviceState = 'Offline'; //set online state to offline
1391
- linkQuality = '0%'; // set linkQuality to nothing
1392
- }
1393
- } else if (lastContact > this.configMaxMinutes[adapterID]) {
1394
- deviceState = 'Offline'; //set online state to offline
1395
- linkQuality = '0%'; // set linkQuality to nothing
1396
- }
1397
- }
1398
- break;
1399
- case 'smartgarden':
1400
- if (this.configMaxMinutes[adapterID] <= 0) {
1401
- if (deviceUnreachState === 'OFFLINE') {
1402
- deviceState = 'Offline'; //set online state to offline
1403
- linkQuality = '0%'; // set linkQuality to nothing
1404
- }
1405
- } else if (deviceUnreachState === 'OFFLINE' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1535
+ } else if (lastContact && lastContact > this.configMaxMinutes[adapterID]) {
1406
1536
  deviceState = 'Offline'; //set online state to offline
1407
1537
  linkQuality = '0%'; // set linkQuality to nothing
1408
1538
  }
1409
- break;
1410
- default:
1411
- if (this.configMaxMinutes[adapterID] <= 0) {
1412
- if (!deviceUnreachState) {
1413
- deviceState = 'Offline'; //set online state to offline
1414
- linkQuality = '0%'; // set linkQuality to nothing
1415
- }
1416
- } else if (lastContact > this.configMaxMinutes[adapterID]) {
1539
+ }
1540
+ break;
1541
+ case 'smartgarden':
1542
+ if (this.configMaxMinutes[adapterID] <= 0) {
1543
+ if (deviceUnreachState === 'OFFLINE') {
1417
1544
  deviceState = 'Offline'; //set online state to offline
1418
1545
  linkQuality = '0%'; // set linkQuality to nothing
1419
1546
  }
1420
- break;
1421
- }
1547
+ } else if (deviceUnreachState === 'OFFLINE' && lastDeviceUnreachStateChange > this.configMaxMinutes[adapterID]) {
1548
+ deviceState = 'Offline'; //set online state to offline
1549
+ linkQuality = '0%'; // set linkQuality to nothing
1550
+ }
1551
+ break;
1552
+ default:
1553
+ if (this.configMaxMinutes[adapterID] <= 0) {
1554
+ if (!deviceUnreachState) {
1555
+ deviceState = 'Offline'; //set online state to offline
1556
+ linkQuality = '0%'; // set linkQuality to nothing
1557
+ }
1558
+ } else if (lastContact && lastContact > this.configMaxMinutes[adapterID]) {
1559
+ deviceState = 'Offline'; //set online state to offline
1560
+ linkQuality = '0%'; // set linkQuality to nothing
1561
+ }
1562
+ break;
1422
1563
  }
1423
1564
  }
1424
1565
  return [lastContactString, deviceState, linkQuality];
@@ -1463,6 +1604,7 @@ class DeviceWatcher extends utils.Adapter {
1463
1604
  this.linkQualityDevices = [];
1464
1605
  this.batteryPowered = [];
1465
1606
  this.batteryLowPowered = [];
1607
+ this.listAllDevicesUserRaw = [];
1466
1608
  this.listAllDevices = [];
1467
1609
  this.offlineDevices = [];
1468
1610
  this.batteryLowPoweredRaw = [];
@@ -1496,7 +1638,7 @@ class DeviceWatcher extends utils.Adapter {
1496
1638
  }
1497
1639
 
1498
1640
  // upgradable raw list
1499
- if (deviceData.Upgradable) {
1641
+ if (deviceData.Upgradable === true) {
1500
1642
  this.upgradableDevicesRaw.push({
1501
1643
  Path: deviceData.Path,
1502
1644
  Device: deviceData.Device,
@@ -1523,6 +1665,24 @@ class DeviceWatcher extends utils.Adapter {
1523
1665
  * @param {object} device
1524
1666
  */
1525
1667
  async theLists(device) {
1668
+ // Raw List with all devices for user
1669
+ this.listAllDevicesUserRaw.push({
1670
+ Device: device.Device,
1671
+ Adapter: device.Adapter,
1672
+ Instance: device.instance,
1673
+ 'Instance connected': device.instancedeviceConnected,
1674
+ isBatteryDevice: device.isBatteryDevice,
1675
+ Battery: device.Battery,
1676
+ BatteryRaw: device.BatteryRaw,
1677
+ BatteryUnitRaw: device.BatteryUnitRaw,
1678
+ isLowBat: device.LowBat,
1679
+ 'Signal strength': device.SignalStrength,
1680
+ 'Signal strength Raw': device.SignalStrengthRaw,
1681
+ 'Last contact': device.LastContact,
1682
+ 'Update Available': device.Upgradable,
1683
+ Status: device.Status,
1684
+ });
1685
+
1526
1686
  // List with all devices
1527
1687
  this.listAllDevices.push({
1528
1688
  Device: device.Device,
@@ -1571,7 +1731,7 @@ class DeviceWatcher extends utils.Adapter {
1571
1731
  }
1572
1732
 
1573
1733
  // Device update List
1574
- if (device.Upgradable) {
1734
+ if (device.Upgradable === true || device.Upgradable === 1) {
1575
1735
  this.upgradableList.push({
1576
1736
  Device: device.Device,
1577
1737
  Adapter: device.Adapter,
@@ -1620,26 +1780,58 @@ class DeviceWatcher extends utils.Adapter {
1620
1780
  }
1621
1781
 
1622
1782
  // Write Datapoints for counts
1623
- await this.setStateAsync(`devices.${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1624
- await this.setStateAsync(`devices.${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1625
- await this.setStateAsync(`devices.${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1626
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1627
- await this.setStateAsync(`devices.${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1783
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
1784
+ await this.setStateChangedAsync(`devices.${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
1785
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
1786
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
1787
+ await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
1628
1788
 
1629
1789
  // List all devices
1630
1790
  if (this.deviceCounter === 0) {
1631
1791
  // if no device is count, write the JSON List with default value
1632
- this.listAllDevices = [{ Device: '--none--', Adapter: '', Battery: '', 'Last contact': '', 'Signal strength': '' }];
1792
+ this.listAllDevices = [
1793
+ {
1794
+ Device: '--none--',
1795
+ Adapter: '',
1796
+ Battery: '',
1797
+ 'Signal strength': '',
1798
+ 'Last contact': '',
1799
+ Status: '',
1800
+ },
1801
+ ];
1802
+ this.listAllDevicesUserRaw = [
1803
+ {
1804
+ Device: '--none--',
1805
+ Adapter: '',
1806
+ Instance: '',
1807
+ 'Instance connected': '',
1808
+ isBatteryDevice: '',
1809
+ Battery: '',
1810
+ BatteryRaw: '',
1811
+ isLowBat: '',
1812
+ 'Signal strength': '',
1813
+ 'Last contact': '',
1814
+ UpdateAvailable: '',
1815
+ Status: '',
1816
+ },
1817
+ ];
1633
1818
  }
1634
- await this.setStateAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1819
+ await this.setStateChangedAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
1820
+ await this.setStateChangedAsync(`devices.${dpSubFolder}listAllRawJSON`, { val: JSON.stringify(this.listAllDevicesUserRaw), ack: true });
1635
1821
 
1636
1822
  // List link quality
1637
1823
  if (this.linkQualityCount === 0) {
1638
1824
  // if no device is count, write the JSON List with default value
1639
- this.linkQualityDevices = [{ Device: '--none--', Adapter: '', 'Signal strength': '' }];
1825
+ this.linkQualityDevices = [
1826
+ {
1827
+ Device: '--none--',
1828
+ Adapter: '',
1829
+ 'Signal strength': '',
1830
+ },
1831
+ ];
1640
1832
  }
1641
1833
  //write JSON list
1642
- await this.setStateAsync(`devices.${dpSubFolder}linkQualityList`, {
1834
+ await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityList`, {
1643
1835
  val: JSON.stringify(this.linkQualityDevices),
1644
1836
  ack: true,
1645
1837
  });
@@ -1647,10 +1839,16 @@ class DeviceWatcher extends utils.Adapter {
1647
1839
  // List offline devices
1648
1840
  if (this.offlineDevicesCount === 0) {
1649
1841
  // if no device is count, write the JSON List with default value
1650
- this.offlineDevices = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1842
+ this.offlineDevices = [
1843
+ {
1844
+ Device: '--none--',
1845
+ Adapter: '',
1846
+ 'Last contact': '',
1847
+ },
1848
+ ];
1651
1849
  }
1652
1850
  //write JSON list
1653
- await this.setStateAsync(`devices.${dpSubFolder}offlineList`, {
1851
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineList`, {
1654
1852
  val: JSON.stringify(this.offlineDevices),
1655
1853
  ack: true,
1656
1854
  });
@@ -1658,10 +1856,16 @@ class DeviceWatcher extends utils.Adapter {
1658
1856
  // List updatable
1659
1857
  if (this.upgradableDevicesCount === 0) {
1660
1858
  // if no device is count, write the JSON List with default value
1661
- this.upgradableList = [{ Device: '--none--', Adapter: '', 'Last contact': '' }];
1859
+ this.upgradableList = [
1860
+ {
1861
+ Device: '--none--',
1862
+ Adapter: '',
1863
+ 'Last contact': '',
1864
+ },
1865
+ ];
1662
1866
  }
1663
1867
  //write JSON list
1664
- await this.setStateAsync(`devices.${dpSubFolder}upgradableList`, {
1868
+ await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableList`, {
1665
1869
  val: JSON.stringify(this.upgradableList),
1666
1870
  ack: true,
1667
1871
  });
@@ -1672,7 +1876,7 @@ class DeviceWatcher extends utils.Adapter {
1672
1876
  this.batteryPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1673
1877
  }
1674
1878
  //write JSON list
1675
- await this.setStateAsync(`devices.${dpSubFolder}batteryList`, {
1879
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryList`, {
1676
1880
  val: JSON.stringify(this.batteryPowered),
1677
1881
  ack: true,
1678
1882
  });
@@ -1683,71 +1887,93 @@ class DeviceWatcher extends utils.Adapter {
1683
1887
  this.batteryLowPowered = [{ Device: '--none--', Adapter: '', Battery: '' }];
1684
1888
  }
1685
1889
  //write JSON list
1686
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryList`, {
1890
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryList`, {
1687
1891
  val: JSON.stringify(this.batteryLowPowered),
1688
1892
  ack: true,
1689
1893
  });
1690
1894
 
1691
1895
  // set booleans datapoints
1692
1896
  if (this.offlineDevicesCount === 0) {
1693
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1897
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1694
1898
  val: false,
1695
1899
  ack: true,
1696
1900
  });
1697
1901
  } else {
1698
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1902
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
1699
1903
  val: true,
1700
1904
  ack: true,
1701
1905
  });
1702
1906
  }
1703
1907
 
1704
1908
  if (this.lowBatteryPoweredCount === 0) {
1705
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1909
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1706
1910
  val: false,
1707
1911
  ack: true,
1708
1912
  });
1709
1913
  } else {
1710
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1914
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
1711
1915
  val: true,
1712
1916
  ack: true,
1713
1917
  });
1714
1918
  }
1715
1919
 
1716
1920
  if (this.upgradableDevicesCount === 0) {
1717
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1921
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1718
1922
  val: false,
1719
1923
  ack: true,
1720
1924
  });
1721
1925
  } else {
1722
- await this.setStateAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1926
+ await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
1723
1927
  val: true,
1724
1928
  ack: true,
1725
1929
  });
1726
1930
  }
1727
1931
 
1728
1932
  //write HTML list
1729
- if (this.createHtmlList) {
1730
- await this.setStateAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1933
+ if (this.configCreateHtmlList) {
1934
+ await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
1731
1935
  val: await this.createListHTML('linkQualityList', this.linkQualityDevices, this.linkQualityCount, null),
1732
1936
  ack: true,
1733
1937
  });
1734
- await this.setStateAsync(`devices.${dpSubFolder}offlineListHTML`, {
1938
+ await this.setStateChangedAsync(`devices.${dpSubFolder}offlineListHTML`, {
1735
1939
  val: await this.createListHTML('offlineList', this.offlineDevices, this.offlineDevicesCount, null),
1736
1940
  ack: true,
1737
1941
  });
1738
- await this.setStateAsync(`devices.${dpSubFolder}batteryListHTML`, {
1942
+ await this.setStateChangedAsync(`devices.${dpSubFolder}batteryListHTML`, {
1739
1943
  val: await this.createListHTML('batteryList', this.batteryPowered, this.batteryPoweredCount, false),
1740
1944
  ack: true,
1741
1945
  });
1742
- await this.setStateAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1946
+ await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
1743
1947
  val: await this.createListHTML('batteryList', this.batteryLowPowered, this.lowBatteryPoweredCount, true),
1744
1948
  ack: true,
1745
1949
  });
1950
+ if (this.config.checkAdapterInstances) {
1951
+ await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
1952
+ val: await this.createListHTMLInstances('allInstancesList', this.listAllInstances, this.countAllInstances),
1953
+ ack: true,
1954
+ });
1955
+ await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
1956
+ val: await this.createListHTMLInstances('allActiveInstancesList', this.listAllActiveInstances, this.countAllActiveInstances),
1957
+ ack: true,
1958
+ });
1959
+ await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
1960
+ val: await this.createListHTMLInstances('errorInstanceList', this.listErrorInstance, this.countErrorInstance),
1961
+ ack: true,
1962
+ });
1963
+ await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
1964
+ val: await this.createListHTMLInstances('deactivatedInstanceList', this.listDeactivatedInstances, this.countDeactivatedInstances),
1965
+ ack: true,
1966
+ });
1967
+ await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
1968
+ val: await this.createListHTMLInstances('updateAdapterList', this.listAdapterUpdates, this.countAdapterUpdates),
1969
+ ack: true,
1970
+ });
1971
+ }
1746
1972
  }
1747
1973
 
1748
1974
  // create timestamp of last run
1749
1975
  const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
1750
- await this.setStateAsync('lastCheck', lastCheck, true);
1976
+ await this.setStateChangedAsync('lastCheck', lastCheck, true);
1751
1977
  } catch (error) {
1752
1978
  this.errorReporting('[writeDatapoints]', error);
1753
1979
  }
@@ -1771,77 +1997,93 @@ class DeviceWatcher extends utils.Adapter {
1771
1997
  *@param {string} instanceObject
1772
1998
  */
1773
1999
  async getInstanceData(instanceObject) {
1774
- const instanceAliveDP = await this.getForeignStatesAsync(`${instanceObject}.alive`);
2000
+ try {
2001
+ const instanceAliveDP = await this.getForeignStatesAsync(`${instanceObject}.alive`);
1775
2002
 
1776
- for (const [id] of Object.entries(instanceAliveDP)) {
1777
- if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
2003
+ for (const [id] of Object.entries(instanceAliveDP)) {
2004
+ if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
1778
2005
 
1779
- // get instance name
1780
- const instanceName = await this.getInstanceName(id);
2006
+ // get instance name
2007
+ const instanceName = await this.getInstanceName(id);
1781
2008
 
1782
- // get instance connected to host data
1783
- const instanceConnectedHostDP = `system.adapter.${instanceName}.connected`;
1784
- const instanceConnectedHostVal = await this.getInitValue(instanceConnectedHostDP);
2009
+ // get instance connected to host data
2010
+ const instanceConnectedHostDP = `system.adapter.${instanceName}.connected`;
2011
+ const instanceConnectedHostVal = await this.getInitValue(instanceConnectedHostDP);
1785
2012
 
1786
- // get instance connected to device data
1787
- const instanceConnectedDeviceDP = `${instanceName}.info.connection`;
1788
- let instanceConnectedDeviceVal;
1789
- if (instanceConnectedDeviceDP !== undefined && typeof instanceConnectedDeviceDP === 'boolean') {
1790
- instanceConnectedDeviceVal = await this.getInitValue(instanceConnectedDeviceDP);
1791
- } else {
1792
- instanceConnectedDeviceVal = 'N/A';
1793
- }
2013
+ // get instance connected to device data
2014
+ const instanceConnectedDeviceDP = `${instanceName}.info.connection`;
2015
+ let instanceConnectedDeviceVal;
2016
+ if (instanceConnectedDeviceDP !== undefined && typeof instanceConnectedDeviceDP === 'boolean') {
2017
+ instanceConnectedDeviceVal = await this.getInitValue(instanceConnectedDeviceDP);
2018
+ } else {
2019
+ instanceConnectedDeviceVal = 'N/A';
2020
+ }
1794
2021
 
1795
- // get adapter version
1796
- const instanceObjectPath = `system.adapter.${instanceName}`;
1797
- let adapterName;
1798
- let adapterVersion;
1799
- let instanceMode;
1800
- let scheduleTime = 'N/A';
1801
- const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
1802
- if (instanceObjectData) {
1803
- // @ts-ignore
1804
- adapterName = this.capitalize(instanceObjectData.common.name);
1805
- adapterVersion = instanceObjectData.common.version;
1806
- instanceMode = instanceObjectData.common.mode;
1807
-
1808
- if (instanceMode === 'schedule') {
1809
- scheduleTime = instanceObjectData.common.schedule;
2022
+ // get adapter version
2023
+ const instanceObjectPath = `system.adapter.${instanceName}`;
2024
+ let adapterName;
2025
+ let adapterVersion;
2026
+ let adapterAvailableUpdate = '';
2027
+ let instanceMode;
2028
+ let scheduleTime = 'N/A';
2029
+ const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
2030
+ if (instanceObjectData) {
2031
+ // @ts-ignore
2032
+ adapterName = this.capitalize(instanceObjectData.common.name);
2033
+ adapterVersion = instanceObjectData.common.version;
2034
+ instanceMode = instanceObjectData.common.mode;
2035
+
2036
+ if (instanceMode === 'schedule') {
2037
+ scheduleTime = instanceObjectData.common.schedule;
2038
+ }
1810
2039
  }
1811
- }
1812
2040
 
1813
- //const adapterVersionVal = await this.getInitValue(adapterVersionDP);
1814
- const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceConnectedHostDP, instanceConnectedDeviceDP);
1815
- const isAlive = instanceStatusRaw[1];
1816
- const instanceStatus = instanceStatusRaw[0];
1817
- const isHealthy = instanceStatusRaw[2];
1818
-
1819
- //subscribe to statechanges
1820
- this.subscribeForeignStatesAsync(id);
1821
- this.subscribeForeignStatesAsync(instanceConnectedHostDP);
1822
- this.subscribeForeignStatesAsync(instanceConnectedDeviceDP);
1823
- this.subscribeForeignObjectsAsync(instanceObjectPath);
1824
-
1825
- // create raw list
1826
- this.listInstanceRaw.set(instanceObjectPath, {
1827
- Adapter: adapterName,
1828
- InstanceName: instanceName,
1829
- instanceObjectPath: instanceObjectPath,
1830
- instanceAlivePath: id,
1831
- instanceMode: instanceMode,
1832
- schedule: scheduleTime,
1833
- adapterVersion: adapterVersion,
1834
- isAlive: isAlive,
1835
- isHealthy: isHealthy,
1836
- connectedHostPath: instanceConnectedHostDP,
1837
- isConnectedHost: instanceConnectedHostVal,
1838
- connectedDevicePath: instanceConnectedDeviceDP,
1839
- isConnectedDevice: instanceConnectedDeviceVal,
1840
- status: instanceStatus,
1841
- });
2041
+ await this.getAdapterUpdateData(`admin.*.info.updatesJson`);
2042
+
2043
+ if (this.adapterUpdatesJsonRaw.has(adapterName)) {
2044
+ for (const adapter of this.adapterUpdatesJsonRaw.values()) {
2045
+ adapterAvailableUpdate = adapter.newVersion;
2046
+ }
2047
+ } else {
2048
+ adapterAvailableUpdate = ' - ';
2049
+ }
2050
+
2051
+ //const adapterVersionVal = await this.getInitValue(adapterVersionDP);
2052
+ const instanceStatusRaw = await this.setInstanceStatus(instanceMode, scheduleTime, id, instanceConnectedHostDP, instanceConnectedDeviceDP);
2053
+ const isAlive = instanceStatusRaw[1];
2054
+ const instanceStatus = instanceStatusRaw[0];
2055
+ const isHealthy = instanceStatusRaw[2];
2056
+
2057
+ //subscribe to statechanges
2058
+ this.subscribeForeignStates(id);
2059
+ this.subscribeForeignStates(instanceConnectedHostDP);
2060
+ this.subscribeForeignStates(instanceConnectedDeviceDP);
2061
+ this.subscribeForeignObjects(`system.adapter.*`);
2062
+
2063
+ // create raw list
2064
+ this.listInstanceRaw.set(instanceObjectPath, {
2065
+ Adapter: adapterName,
2066
+ InstanceName: instanceName,
2067
+ instanceObjectPath: instanceObjectPath,
2068
+ instanceAlivePath: id,
2069
+ instanceMode: instanceMode,
2070
+ schedule: scheduleTime,
2071
+ adapterVersion: adapterVersion,
2072
+ updateAvailable: adapterAvailableUpdate,
2073
+ isAlive: isAlive,
2074
+ isHealthy: isHealthy,
2075
+ connectedHostPath: instanceConnectedHostDP,
2076
+ isConnectedHost: instanceConnectedHostVal,
2077
+ connectedDevicePath: instanceConnectedDeviceDP,
2078
+ isConnectedDevice: instanceConnectedDeviceVal,
2079
+ status: instanceStatus,
2080
+ });
2081
+ }
2082
+ await this.createInstanceList();
2083
+ await this.writeInstanceDPs();
2084
+ } catch (error) {
2085
+ this.errorReporting('[getInstanceData]', error);
1842
2086
  }
1843
- await this.createInstanceList();
1844
- await this.writeInstanceDPs();
1845
2087
  }
1846
2088
 
1847
2089
  /**
@@ -1874,6 +2116,7 @@ class DeviceWatcher extends utils.Adapter {
1874
2116
  let diff;
1875
2117
  let previousCronRun = null;
1876
2118
  let isHealthy = false;
2119
+ let instanceErrorTime = 20000 / 2;
1877
2120
 
1878
2121
  switch (instanceMode) {
1879
2122
  case 'schedule':
@@ -1895,14 +2138,20 @@ class DeviceWatcher extends utils.Adapter {
1895
2138
  case 'daemon':
1896
2139
  if (!isAlive) return ['Instanz deaktiviert', false, null]; // if instance is turned off
1897
2140
  if (isDeviceConnected === undefined) isDeviceConnected = true;
1898
- // In case of (re)start, connection may take some time. We take 3 attempts.
1899
- // Attempt 1/3 - immediately
2141
+
2142
+ if (this.userTimeInstancesList.has(instanceAlivePath)) {
2143
+ instanceErrorTime = this.userTimeInstancesList.get(instanceAlivePath).errorTime;
2144
+ instanceErrorTime = (instanceErrorTime * 1000) / 2; // calculate sec to ms and divide into two
2145
+ }
2146
+
1900
2147
  if (isHostConnected && isDeviceConnected) {
2148
+ // In case of (re)start, connection may take some time. We take 3 attempts.
2149
+ // Attempt 1/3 - immediately
1901
2150
  isHealthy = true;
1902
2151
  instanceStatusString = 'Instanz okay';
1903
2152
  } else {
1904
- // Attempt 2/3 - after 10 seconds
1905
- await this.wait(10000);
2153
+ // 2/3 - after 15 seconds
2154
+ await this.wait(instanceErrorTime);
1906
2155
  isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
1907
2156
  isHostConnected = await this.getInitValue(hostConnectedPath);
1908
2157
 
@@ -1910,8 +2159,8 @@ class DeviceWatcher extends utils.Adapter {
1910
2159
  isHealthy = true;
1911
2160
  instanceStatusString = 'Instanz okay';
1912
2161
  } else {
1913
- // Attempt 3/3 - after 20 seconds in total
1914
- await this.wait(10000);
2162
+ // 3/3 - after 30 seconds in total or user time setting
2163
+ await this.wait(instanceErrorTime);
1915
2164
  isDeviceConnected = await this.getInitValue(isDeviceConnctedPath);
1916
2165
  isHostConnected = await this.getInitValue(hostConnectedPath);
1917
2166
 
@@ -1954,7 +2203,7 @@ class DeviceWatcher extends utils.Adapter {
1954
2203
  * @param {string} adapterUpdateListDP
1955
2204
  */
1956
2205
  async getAdapterUpdateData(adapterUpdateListDP) {
1957
- this.adapterUpdatesJsonRaw = [];
2206
+ this.adapterUpdatesJsonRaw.clear();
1958
2207
  const adapterUpdatesListVal = await this.getForeignStatesAsync(adapterUpdateListDP);
1959
2208
 
1960
2209
  let adapterJsonList;
@@ -1966,9 +2215,8 @@ class DeviceWatcher extends utils.Adapter {
1966
2215
  }
1967
2216
 
1968
2217
  for (const [id] of Object.entries(adapterJsonList)) {
1969
- this.adapterUpdatesJsonRaw.push({
2218
+ this.adapterUpdatesJsonRaw.set(this.capitalize(id), {
1970
2219
  Path: adapterUpdatesJsonPath,
1971
- Adapter: this.capitalize(id),
1972
2220
  newVersion: adapterJsonList[id].availableVersion,
1973
2221
  oldVersion: adapterJsonList[id].installedVersion,
1974
2222
  });
@@ -1983,11 +2231,11 @@ class DeviceWatcher extends utils.Adapter {
1983
2231
  this.listAdapterUpdates = [];
1984
2232
  this.countAdapterUpdates = 0;
1985
2233
 
1986
- for (const adapter of this.adapterUpdatesJsonRaw) {
2234
+ for (const [adapter, updateData] of this.adapterUpdatesJsonRaw) {
1987
2235
  this.listAdapterUpdates.push({
1988
- Adapter: adapter.Adapter,
1989
- 'Available Version': adapter.newVersion,
1990
- 'Installed Version': adapter.oldVersion,
2236
+ Adapter: adapter,
2237
+ 'Available Version': updateData.newVersion,
2238
+ 'Installed Version': updateData.oldVersion,
1991
2239
  });
1992
2240
  }
1993
2241
  this.countAdapterUpdates = this.listAdapterUpdates.length;
@@ -1999,13 +2247,13 @@ class DeviceWatcher extends utils.Adapter {
1999
2247
  */
2000
2248
  async writeAdapterUpdatesDPs() {
2001
2249
  // Write Datapoints for counts
2002
- await this.setStateAsync(`adapterAndInstances.countAdapterUpdates`, { val: this.countAdapterUpdates, ack: true });
2250
+ await this.setStateChangedAsync(`adapterAndInstances.countAdapterUpdates`, { val: this.countAdapterUpdates, ack: true });
2003
2251
 
2004
2252
  // list deactivated instances
2005
2253
  if (this.countAdapterUpdates === 0) {
2006
2254
  this.listAdapterUpdates = [{ Adapter: '--none--', 'Available Version': '', 'Installed Version': '' }];
2007
2255
  }
2008
- await this.setStateAsync(`adapterAndInstances.listAdapterUpdates`, { val: JSON.stringify(this.listAdapterUpdates), ack: true });
2256
+ await this.setStateChangedAsync(`adapterAndInstances.listAdapterUpdates`, { val: JSON.stringify(this.listAdapterUpdates), ack: true });
2009
2257
  }
2010
2258
 
2011
2259
  /**
@@ -2013,6 +2261,7 @@ class DeviceWatcher extends utils.Adapter {
2013
2261
  */
2014
2262
  async createInstanceList() {
2015
2263
  this.listAllInstances = [];
2264
+ this.listAllActiveInstances = [];
2016
2265
  this.listDeactivatedInstances = [];
2017
2266
  this.listErrorInstanceRaw = [];
2018
2267
  this.listErrorInstance = [];
@@ -2029,23 +2278,36 @@ class DeviceWatcher extends utils.Adapter {
2029
2278
  }
2030
2279
 
2031
2280
  if (this.blacklistInstancesLists.includes(instance.instanceAlivePath)) continue;
2281
+ // all instances
2032
2282
  this.listAllInstances.push({
2033
2283
  Adapter: instance.Adapter,
2034
2284
  Instance: instance.InstanceName,
2035
2285
  Mode: instance.instanceMode,
2036
2286
  Schedule: instance.schedule,
2037
2287
  Version: instance.adapterVersion,
2288
+ Updateable: instance.updateAvailable,
2038
2289
  Status: instance.status,
2039
2290
  });
2291
+
2040
2292
  if (!instance.isAlive) {
2293
+ // list with deactivated instances
2041
2294
  this.listDeactivatedInstances.push({
2042
2295
  Adapter: instance.Adapter,
2043
2296
  Instance: instance.InstanceName,
2044
2297
  Status: instance.status,
2045
2298
  });
2299
+ } else {
2300
+ // list with active instances
2301
+ this.listAllActiveInstances.push({
2302
+ Adapter: instance.Adapter,
2303
+ Instance: instance.InstanceName,
2304
+ Mode: instance.instanceMode,
2305
+ Schedule: instance.schedule,
2306
+ Status: instance.status,
2307
+ });
2046
2308
  }
2047
2309
 
2048
- // fill List for User
2310
+ // list with error instances
2049
2311
  if (instance.isAlive && !instance.isHealthy) {
2050
2312
  this.listErrorInstance.push({
2051
2313
  Adapter: instance.Adapter,
@@ -2063,10 +2325,12 @@ class DeviceWatcher extends utils.Adapter {
2063
2325
  */
2064
2326
  async countInstances() {
2065
2327
  this.countAllInstances = 0;
2328
+ this.countAllActiveInstances = 0;
2066
2329
  this.countDeactivatedInstances = 0;
2067
2330
  this.countErrorInstance = 0;
2068
2331
 
2069
2332
  this.countAllInstances = this.listAllInstances.length;
2333
+ this.countAllActiveInstances = this.listAllActiveInstances.length;
2070
2334
  this.countDeactivatedInstances = this.listDeactivatedInstances.length;
2071
2335
  this.countErrorInstance = this.listErrorInstance.length;
2072
2336
  }
@@ -2075,26 +2339,27 @@ class DeviceWatcher extends utils.Adapter {
2075
2339
  * write datapoints for instances list and counts
2076
2340
  */
2077
2341
  async writeInstanceDPs() {
2078
- // Write Datapoints for counts
2079
- await this.setStateAsync(`adapterAndInstances.countAllInstances`, { val: this.countAllInstances, ack: true });
2080
- await this.setStateAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2081
-
2082
2342
  // List all instances
2083
- await this.setStateAsync(`adapterAndInstances.listAllInstances`, { val: JSON.stringify(this.listAllInstances), ack: true });
2343
+ await this.setStateChangedAsync(`adapterAndInstances.listAllInstances`, { val: JSON.stringify(this.listAllInstances), ack: true });
2344
+ await this.setStateChangedAsync(`adapterAndInstances.countAllInstances`, { val: this.countAllInstances, ack: true });
2345
+
2346
+ // List all active instances
2347
+ await this.setStateChangedAsync(`adapterAndInstances.listAllActiveInstances`, { val: JSON.stringify(this.listAllActiveInstances), ack: true });
2348
+ await this.setStateChangedAsync(`adapterAndInstances.countAllActiveInstances`, { val: this.countAllActiveInstances, ack: true });
2084
2349
 
2085
2350
  // list deactivated instances
2086
2351
  if (this.countDeactivatedInstances === 0) {
2087
- this.listDeactivatedInstances = [{ Instance: '--none--', Version: '', Status: '' }];
2352
+ this.listDeactivatedInstances = [{ Adapter: '--none--', Instance: '', Version: '', Status: '' }];
2088
2353
  }
2089
- await this.setStateAsync(`adapterAndInstances.listDeactivatedInstances`, { val: JSON.stringify(this.listDeactivatedInstances), ack: true });
2090
- await this.setStateAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2354
+ await this.setStateChangedAsync(`adapterAndInstances.listDeactivatedInstances`, { val: JSON.stringify(this.listDeactivatedInstances), ack: true });
2355
+ await this.setStateChangedAsync(`adapterAndInstances.countDeactivatedInstances`, { val: this.countDeactivatedInstances, ack: true });
2091
2356
 
2092
2357
  // list error instances
2093
2358
  if (this.countErrorInstance === 0) {
2094
- this.listErrorInstance = [{ Instance: '--none--', Mode: '', Status: '' }];
2359
+ this.listErrorInstance = [{ Adapter: '--none--', Instance: '', Mode: '', Status: '' }];
2095
2360
  }
2096
- await this.setStateAsync(`adapterAndInstances.listInstancesError`, { val: JSON.stringify(this.listErrorInstance), ack: true });
2097
- await this.setStateAsync(`adapterAndInstances.countInstancesError`, { val: this.countErrorInstance, ack: true });
2361
+ await this.setStateChangedAsync(`adapterAndInstances.listInstancesError`, { val: JSON.stringify(this.listErrorInstance), ack: true });
2362
+ await this.setStateChangedAsync(`adapterAndInstances.countInstancesError`, { val: this.countErrorInstance, ack: true });
2098
2363
  }
2099
2364
 
2100
2365
  /**
@@ -2168,6 +2433,53 @@ class DeviceWatcher extends utils.Adapter {
2168
2433
  },
2169
2434
  native: {},
2170
2435
  });
2436
+ // Instances
2437
+ await this.setObjectNotExistsAsync(`adapterAndInstances.listAllActiveInstances`, {
2438
+ type: 'state',
2439
+ common: {
2440
+ name: {
2441
+ en: 'JSON List of all active instances',
2442
+ de: 'JSON Liste aller aktiven Instanzen',
2443
+ ru: 'ДЖСОН Список всех активных инстанций',
2444
+ pt: 'J. Lista de todas as instâncias ativas',
2445
+ nl: 'JSON List van alle actieve instanties',
2446
+ fr: 'JSON Liste de tous les cas actifs',
2447
+ it: 'JSON Elenco di tutte le istanze attive',
2448
+ es: 'JSON Lista de todos los casos activos',
2449
+ pl: 'JSON Lista wszystkich aktywnych instancji',
2450
+ uk: 'Сонце Список всіх активних екземплярів',
2451
+ 'zh-cn': '附 件 所有积极事件清单',
2452
+ },
2453
+ type: 'array',
2454
+ role: 'json',
2455
+ read: true,
2456
+ write: false,
2457
+ },
2458
+ native: {},
2459
+ });
2460
+ await this.setObjectNotExistsAsync(`adapterAndInstances.countAllActiveInstances`, {
2461
+ type: 'state',
2462
+ common: {
2463
+ name: {
2464
+ en: 'Number of all active instances',
2465
+ de: 'Anzahl aller aktiven Instanzen',
2466
+ ru: 'Количество всех активных инстанций',
2467
+ pt: 'Número de todas as instâncias ativas',
2468
+ nl: 'Nummer van alle actieve instanties',
2469
+ fr: 'Nombre de toutes les instances actives',
2470
+ it: 'Numero di tutte le istanze attive',
2471
+ es: 'Número de casos activos',
2472
+ pl: 'Liczba wszystkich czynnych przypadków',
2473
+ uk: 'Кількість всіх активних екземплярів',
2474
+ 'zh-cn': '所有积极事件的数目',
2475
+ },
2476
+ type: 'number',
2477
+ role: 'value',
2478
+ read: true,
2479
+ write: false,
2480
+ },
2481
+ native: {},
2482
+ });
2171
2483
  await this.setObjectNotExistsAsync(`adapterAndInstances.listDeactivatedInstances`, {
2172
2484
  type: 'state',
2173
2485
  common: {
@@ -2317,6 +2629,8 @@ class DeviceWatcher extends utils.Adapter {
2317
2629
  await this.delObjectAsync(`adapterAndInstances`);
2318
2630
  await this.delObjectAsync(`adapterAndInstances.listAllInstances`);
2319
2631
  await this.delObjectAsync(`adapterAndInstances.countAllInstances`);
2632
+ await this.delObjectAsync(`adapterAndInstances.listAllActiveInstances`);
2633
+ await this.delObjectAsync(`adapterAndInstances.countAllActiveInstances`);
2320
2634
  await this.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
2321
2635
  await this.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
2322
2636
  await this.delObjectAsync(`adapterAndInstances.listInstancesError`);
@@ -2394,6 +2708,44 @@ class DeviceWatcher extends utils.Adapter {
2394
2708
  this.errorReporting('[sendNotification Whatsapp]', error);
2395
2709
  }
2396
2710
 
2711
+ // Matrix
2712
+ try {
2713
+ if (this.config.instanceMatrix) {
2714
+ //first check if instance is living
2715
+ const matrixAliveState = await this.getInitValue('system.adapter.' + this.config.instanceMatrix + '.alive');
2716
+
2717
+ if (!matrixAliveState) {
2718
+ this.log.warn('Matrix instance is not running. Message could not be sent. Please check your instance configuration.');
2719
+ } else {
2720
+ await this.sendToAsync(this.config.instanceMatrix, 'send', {
2721
+ html: `<h1>${this.config.titleMatrix}</h1>`,
2722
+ text: text,
2723
+ });
2724
+ }
2725
+ }
2726
+ } catch (error) {
2727
+ this.errorReporting('[sendNotification Matrix]', error);
2728
+ }
2729
+
2730
+ // Signal
2731
+ try {
2732
+ if (this.config.instanceSignal) {
2733
+ //first check if instance is living
2734
+ const signalAliveState = await this.getInitValue('system.adapter.' + this.config.instanceSignal + '.alive');
2735
+
2736
+ if (!signalAliveState) {
2737
+ this.log.warn('Signal instance is not running. Message could not be sent. Please check your instance configuration.');
2738
+ } else {
2739
+ await this.sendToAsync(this.config.instanceSignal, 'send', {
2740
+ text: text,
2741
+ phone: this.config.phoneSignal,
2742
+ });
2743
+ }
2744
+ }
2745
+ } catch (error) {
2746
+ this.errorReporting('[sendNotification Signal]', error);
2747
+ }
2748
+
2397
2749
  // Email
2398
2750
  try {
2399
2751
  if (this.config.instanceEmail) {
@@ -2532,13 +2884,12 @@ class DeviceWatcher extends utils.Adapter {
2532
2884
  setMessage(message);
2533
2885
  break;
2534
2886
  case 'updateAdapter':
2887
+ if (this.countAdapterUpdates === 0) return;
2535
2888
  objectData = this.listAdapterUpdates;
2536
2889
  list = '';
2537
-
2538
2890
  for (const id of objectData) {
2539
2891
  list = `${list}\n${id.Adapter}: v${id['Available Version']}`;
2540
2892
  }
2541
- if (list.length === 0) return;
2542
2893
  message = `Neue Adapter Updates vorhanden: ${list}`;
2543
2894
  setMessage(message);
2544
2895
  break;
@@ -2851,6 +3202,172 @@ class DeviceWatcher extends utils.Adapter {
2851
3202
  return html;
2852
3203
  }
2853
3204
 
3205
+ /**
3206
+ * @param {string} type - type of list
3207
+ * @param {object} instances - Instance
3208
+ * @param {number} instancesCount - Counted devices
3209
+ */
3210
+ async createListHTMLInstances(type, instances, instancesCount) {
3211
+ let html;
3212
+ switch (type) {
3213
+ case 'allInstancesList':
3214
+ instances = instances.sort((a, b) => {
3215
+ a = a.Instance || '';
3216
+ b = b.Instance || '';
3217
+ return a.localeCompare(b);
3218
+ });
3219
+ html = `<center>
3220
+ <b>All Instances:<font> ${instancesCount}</b><small></small></font>
3221
+ <p></p>
3222
+ </center>
3223
+ <table width=100%>
3224
+ <tr>
3225
+ <th align=left>Adapter</th>
3226
+ <th align=center>Instance</th>
3227
+ <th align=center width=180>Status</th>
3228
+ </tr>
3229
+ <tr>
3230
+ <td colspan="5"><hr></td>
3231
+ </tr>`;
3232
+
3233
+ for (const instance of instances) {
3234
+ html += `<tr>
3235
+ <td><font>${instance.Adapter}</font></td>
3236
+ <td align=center><font>${instance.Instance}</font></td>
3237
+ <td align=center><font>${instance.Status}</font></td>
3238
+ </tr>`;
3239
+ }
3240
+
3241
+ html += '</table>';
3242
+ break;
3243
+
3244
+ case 'allActiveInstancesList':
3245
+ instances = instances.sort((a, b) => {
3246
+ a = a.Instance || '';
3247
+ b = b.Instances || '';
3248
+ return a.localeCompare(b);
3249
+ });
3250
+ html = `<center>
3251
+ <b>Active Devices: <font> ${instancesCount}</b><small></small></font>
3252
+ <p></p>
3253
+ </center>
3254
+ <table width=100%>
3255
+ <tr>
3256
+ <th align=left>Adapter</th>
3257
+ <th align=center>Instance</th>
3258
+ <th align=center width=180>Status</th>
3259
+ </tr>
3260
+ <tr>
3261
+ <td colspan="5"><hr></td>
3262
+ </tr>`;
3263
+
3264
+ for (const instance of instances) {
3265
+ html += `<tr>
3266
+ <td><font>${instance.Adapter}</font></td>
3267
+ <td align=center><font>${instance.Instance}</font></td>
3268
+ <td align=center><font color=orange>${instance.Status}</font></td>
3269
+ </tr>`;
3270
+ }
3271
+
3272
+ html += '</table>';
3273
+ break;
3274
+
3275
+ case 'errorInstanceList':
3276
+ instances = instances.sort((a, b) => {
3277
+ a = a.Instance || '';
3278
+ b = b.Instances || '';
3279
+ return a.localeCompare(b);
3280
+ });
3281
+ html = `<center>
3282
+ <b>Error Instances: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
3283
+ <p></p>
3284
+ </center>
3285
+ <table width=100%>
3286
+ <tr>
3287
+ <th align=left>Adapter</th>
3288
+ <th align=center width=120>Instance</th>
3289
+ <th align=center>Status</th>
3290
+ </tr>
3291
+ <tr>
3292
+ <td colspan="5"><hr></td>
3293
+ </tr>`;
3294
+
3295
+ for (const instance of instances) {
3296
+ html += `<tr>
3297
+ <td><font>${instance.Adapter}</font></td>
3298
+ <td align=center><font>${instance.Instance}</font></td>
3299
+ <td align=center><font color=orange>${instance.Status}</font></td>
3300
+ </tr>`;
3301
+ }
3302
+
3303
+ html += '</table>';
3304
+ break;
3305
+
3306
+ case 'deactivatedInstanceList':
3307
+ instances = instances.sort((a, b) => {
3308
+ a = a.Instance || '';
3309
+ b = b.Instances || '';
3310
+ return a.localeCompare(b);
3311
+ });
3312
+ html = `<center>
3313
+ <b>Deactivated Instances: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
3314
+ <p></p>
3315
+ </center>
3316
+ <table width=100%>
3317
+ <tr>
3318
+ <th align=left>Adapter</th>
3319
+ <th align=center width=120>Instance</th>
3320
+ <th align=center>Status</th>
3321
+ </tr>
3322
+ <tr>
3323
+ <td colspan="5"><hr></td>
3324
+ </tr>`;
3325
+
3326
+ for (const instance of instances) {
3327
+ html += `<tr>
3328
+ <td><font>${instance.Adapter}</font></td>
3329
+ <td align=center><font>${instance.Instance}</font></td>
3330
+ <td align=center><font color=orange>${instance.Status}</font></td>
3331
+ </tr>`;
3332
+ }
3333
+
3334
+ html += '</table>';
3335
+ break;
3336
+
3337
+ case 'updateAdapterList':
3338
+ instances = instances.sort((a, b) => {
3339
+ a = a.Instance || '';
3340
+ b = b.Instances || '';
3341
+ return a.localeCompare(b);
3342
+ });
3343
+ html = `<center>
3344
+ <b>Updatable Adapter: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
3345
+ <p></p>
3346
+ </center>
3347
+ <table width=100%>
3348
+ <tr>
3349
+ <th align=left>Adapter</th>
3350
+ <th align=center>Installed Version</th>
3351
+ <th align=center>Available Version</th>
3352
+ </tr>
3353
+ <tr>
3354
+ <td colspan="5"><hr></td>
3355
+ </tr>`;
3356
+
3357
+ for (const instance of instances) {
3358
+ html += `<tr>
3359
+ <td><font>${instance.Adapter}</font></td>
3360
+ <td align=center><font>${instance['Installed Version']}</font></td>
3361
+ <td align=center><font color=orange>${instance['Available Version']}</font></td>
3362
+ </tr>`;
3363
+ }
3364
+
3365
+ html += '</table>';
3366
+ break;
3367
+ }
3368
+ return html;
3369
+ }
3370
+
2854
3371
  /*=============================================
2855
3372
  = create datapoints for each adapter =
2856
3373
  =============================================*/
@@ -2938,6 +3455,30 @@ class DeviceWatcher extends utils.Adapter {
2938
3455
  native: {},
2939
3456
  });
2940
3457
 
3458
+ await this.setObjectNotExistsAsync(`devices.${adptName}.listAllRawJSON`, {
3459
+ type: 'state',
3460
+ common: {
3461
+ name: {
3462
+ en: 'JSON RAW List of all devices',
3463
+ de: 'JSON RAW Liste aller Geräte',
3464
+ ru: 'ДЖСОН РАВ Список всех устройств',
3465
+ pt: 'JSON RAW Lista de todos os dispositivos',
3466
+ nl: 'JSON RAW List van alle apparaten',
3467
+ fr: 'JSON RAW Liste de tous les dispositifs',
3468
+ it: 'JSON RAW Elenco di tutti i dispositivi',
3469
+ es: 'JSON RAW Lista de todos los dispositivos',
3470
+ pl: 'JSON RAW Lista wszystkich urządzeń',
3471
+ uk: 'ДЖСОН РАВ Список всіх пристроїв',
3472
+ 'zh-cn': 'JSONRAW 所有装置清单',
3473
+ },
3474
+ type: 'array',
3475
+ role: 'json',
3476
+ read: true,
3477
+ write: false,
3478
+ },
3479
+ native: {},
3480
+ });
3481
+
2941
3482
  await this.setObjectNotExistsAsync(`devices.${adptName}.listAll`, {
2942
3483
  type: 'state',
2943
3484
  common: {
@@ -3207,6 +3748,7 @@ class DeviceWatcher extends utils.Adapter {
3207
3748
  await this.delObjectAsync(`devices.${adptName}.offlineCount`);
3208
3749
  await this.delObjectAsync(`devices.${adptName}.offlineList`);
3209
3750
  await this.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
3751
+ await this.delObjectAsync(`devices.${adptName}.listAllRawJSON`);
3210
3752
  await this.delObjectAsync(`devices.${adptName}.listAll`);
3211
3753
  await this.delObjectAsync(`devices.${adptName}.linkQualityList`);
3212
3754
  await this.delObjectAsync(`devices.${adptName}.countAll`);
@@ -3345,6 +3887,161 @@ class DeviceWatcher extends utils.Adapter {
3345
3887
  await this.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
3346
3888
  }
3347
3889
 
3890
+ /**
3891
+ * create HTML list datapoints for instances
3892
+ **/
3893
+ async createHtmlListDatapointsInstances() {
3894
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists`, {
3895
+ type: 'channel',
3896
+ common: {
3897
+ name: {
3898
+ en: 'HTML lists for adapter and instances',
3899
+ de: 'HTML-Listen für Adapter und Instanzen',
3900
+ ru: 'HTML-списки для адаптеров и инстанций',
3901
+ pt: 'Listas HTML para adaptador e instâncias',
3902
+ nl: 'HTML lijsten voor adapter en instituut',
3903
+ fr: "Listes HTML pour l'adaptateur et les instances",
3904
+ it: 'Elenchi HTML per adattatore e istanze',
3905
+ es: 'Listas HTML para adaptador y casos',
3906
+ pl: 'Listy HTML dla adaptera i instancji',
3907
+ uk: 'Списки HTML для адаптерів та екземплярів',
3908
+ 'zh-cn': 'HTML名单',
3909
+ },
3910
+ },
3911
+ native: {},
3912
+ });
3913
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
3914
+ type: 'state',
3915
+ common: {
3916
+ name: {
3917
+ en: 'HTML List of all instances',
3918
+ de: 'HTML Liste aller Instanzen',
3919
+ ru: 'HTML Список всех инстанций',
3920
+ pt: 'HTML Lista de todas as instâncias',
3921
+ nl: 'HTM List van alle instanties',
3922
+ fr: 'HTML Liste de tous les cas',
3923
+ it: 'HTML Elenco di tutte le istanze',
3924
+ es: 'HTML Lista de todos los casos',
3925
+ pl: 'HTML Lista wszystkich instancji',
3926
+ uk: 'Українська Список всіх екземплярів',
3927
+ 'zh-cn': 'HTML 所有事例一览表',
3928
+ },
3929
+ type: 'string',
3930
+ role: 'html',
3931
+ read: true,
3932
+ write: false,
3933
+ },
3934
+ native: {},
3935
+ });
3936
+
3937
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
3938
+ type: 'state',
3939
+ common: {
3940
+ name: {
3941
+ en: 'HTML List of all active instances',
3942
+ de: 'HTML Liste aller aktiven Instanzen',
3943
+ ru: 'HTML Список всех активных инстанций',
3944
+ pt: 'HTML Lista de todas as instâncias ativas',
3945
+ nl: 'HTM List van alle actieve instanties',
3946
+ fr: 'HTML Liste de tous les cas actifs',
3947
+ it: 'HTML Elenco di tutte le istanze attive',
3948
+ es: 'HTML Lista de todos los casos activos',
3949
+ pl: 'HTML Lista wszystkich aktywnych instancji',
3950
+ uk: 'Українська Список всіх активних екземплярів',
3951
+ 'zh-cn': 'HTML 所有积极事件清单',
3952
+ },
3953
+ type: 'string',
3954
+ role: 'value',
3955
+ read: true,
3956
+ write: false,
3957
+ },
3958
+ native: {},
3959
+ });
3960
+
3961
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
3962
+ type: 'state',
3963
+ common: {
3964
+ name: {
3965
+ en: 'HTML List of all deactivated instances',
3966
+ de: 'HTML Liste aller deaktivierten Instanzen',
3967
+ ru: 'HTML Список всех деактивированных инстанций',
3968
+ pt: 'HTML Lista de todas as instâncias desativadas',
3969
+ nl: 'HTM List van alle gedeactiveerde instanties',
3970
+ fr: 'HTML Liste de tous les cas désactivés',
3971
+ it: 'HTML Elenco di tutte le istanze disattivate',
3972
+ es: 'HTML Lista de todos los casos desactivados',
3973
+ pl: 'HTML Lista wszystkich przypadków deaktywowanych',
3974
+ uk: 'Українська Список всіх деактивованих екземплярів',
3975
+ 'zh-cn': 'HTML 所有违犯事件清单',
3976
+ },
3977
+ type: 'string',
3978
+ role: 'html',
3979
+ read: true,
3980
+ write: false,
3981
+ },
3982
+ native: {},
3983
+ });
3984
+
3985
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
3986
+ type: 'state',
3987
+ common: {
3988
+ name: {
3989
+ en: 'HTML List of instances with error',
3990
+ de: 'HTML Liste der Fälle mit Fehler',
3991
+ ru: 'HTML Список инстанций с ошибкой',
3992
+ pt: 'HTML Lista de casos com erro',
3993
+ nl: 'HTM List van instoringen met fouten',
3994
+ fr: 'HTML Liste des instances avec erreur',
3995
+ it: 'HTML Elenco delle istanze con errore',
3996
+ es: 'HTML Lista de casos con error',
3997
+ pl: 'HTML Lista przykładów z błądem',
3998
+ uk: 'Українська Список екземплярів з помилкою',
3999
+ 'zh-cn': 'HTML 出现错误的情况清单',
4000
+ },
4001
+ type: 'string',
4002
+ role: 'html',
4003
+ read: true,
4004
+ write: false,
4005
+ },
4006
+ native: {},
4007
+ });
4008
+ await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
4009
+ type: 'state',
4010
+ common: {
4011
+ name: {
4012
+ en: 'HTML list of adapters with available updates',
4013
+ de: 'HTML-Liste der Adapter mit verfügbaren Updates',
4014
+ ru: 'HTML список адаптеров с доступными обновлениями',
4015
+ pt: 'Lista HTML de adaptadores com atualizações disponíveis',
4016
+ nl: 'HTML lijst met beschikbare updates',
4017
+ fr: 'Liste HTML des adaptateurs avec mises à jour disponibles',
4018
+ it: 'Elenco HTML degli adattatori con aggiornamenti disponibili',
4019
+ es: 'Lista HTML de adaptadores con actualizaciones disponibles',
4020
+ pl: 'Lista adapterów HTML z dostępnymi aktualizacjami',
4021
+ uk: 'HTML список адаптерів з доступними оновленнями',
4022
+ 'zh-cn': 'HTML 可供更新的适应者名单',
4023
+ },
4024
+ type: 'string',
4025
+ role: 'html',
4026
+ read: true,
4027
+ write: false,
4028
+ },
4029
+ native: {},
4030
+ });
4031
+ }
4032
+
4033
+ /**
4034
+ * delete html datapoints for instances
4035
+ **/
4036
+ async deleteHtmlListDatapointsInstances() {
4037
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`);
4038
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`);
4039
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`);
4040
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`);
4041
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`);
4042
+ await this.delObjectAsync(`adapterAndInstances.HTML_Lists`);
4043
+ }
4044
+
3348
4045
  /*=============================================
3349
4046
  = help functions =
3350
4047
  =============================================*/
@@ -3413,12 +4110,11 @@ class DeviceWatcher extends utils.Adapter {
3413
4110
  }
3414
4111
 
3415
4112
  /**
3416
- * @param {number} time
4113
+ * @param {number} ms
3417
4114
  */
3418
- wait(time) {
3419
- return new Promise(function (resolve) {
3420
- setTimeout(resolve, time);
3421
- });
4115
+ async wait(ms) {
4116
+ if (isUnloaded) return;
4117
+ return new Promise((resolve) => setTimeout(resolve, ms));
3422
4118
  }
3423
4119
 
3424
4120
  /**
@@ -3462,11 +4158,14 @@ class DeviceWatcher extends utils.Adapter {
3462
4158
  */
3463
4159
  onUnload(callback) {
3464
4160
  try {
4161
+ this.log.debug('clearing timeouts');
4162
+
4163
+ isUnloaded = true;
4164
+
3465
4165
  if (this.refreshDataTimeout) {
3466
- this.log.debug('clearing refresh timeout');
3467
4166
  this.clearTimeout(this.refreshDataTimeout);
4167
+ this.refreshDataTimeout = null;
3468
4168
  }
3469
- isUnloaded = true;
3470
4169
 
3471
4170
  this.log.info('cleaned everything up...');
3472
4171