iobroker.device-watcher 2.12.3 → 2.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/admin/jsonConfig.json5 +1 -1
- package/io-package.json +14 -14
- package/lib/arrApart.js +2 -0
- package/lib/crud.js +1942 -0
- package/lib/tools.js +153 -0
- package/main.js +217 -2243
- package/package.json +1 -1
package/main.js
CHANGED
|
@@ -5,10 +5,12 @@ const adapterName = require('./package.json').name.split('.').pop();
|
|
|
5
5
|
const schedule = require('node-schedule');
|
|
6
6
|
const arrApart = require('./lib/arrApart.js'); // list of supported adapters
|
|
7
7
|
const translations = require('./lib/translations.js');
|
|
8
|
-
const
|
|
8
|
+
const tools = require('./lib/tools.js');
|
|
9
|
+
const crud = require('./lib/crud.js');
|
|
9
10
|
|
|
10
11
|
// indicator if the adapter is running (for intervall/shedule)
|
|
11
12
|
let isUnloaded = false;
|
|
13
|
+
const adapterUpdateListDP = 'admin.*.info.updatesJson';
|
|
12
14
|
|
|
13
15
|
class DeviceWatcher extends utils.Adapter {
|
|
14
16
|
constructor(options) {
|
|
@@ -21,7 +23,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
21
23
|
// instances and adapters
|
|
22
24
|
// raw arrays
|
|
23
25
|
this.listInstanceRaw = new Map();
|
|
24
|
-
this.adapterUpdatesJsonRaw =
|
|
26
|
+
this.adapterUpdatesJsonRaw = [];
|
|
25
27
|
this.listErrorInstanceRaw = [];
|
|
26
28
|
|
|
27
29
|
// user arrays
|
|
@@ -88,6 +90,9 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
88
90
|
this.on('objectChange', this.onObjectChange.bind(this));
|
|
89
91
|
this.on('message', this.onMessage.bind(this));
|
|
90
92
|
this.on('unload', this.onUnload.bind(this));
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
/**
|
|
@@ -242,7 +247,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
242
247
|
for (const [id] of Object.entries(arrApart)) {
|
|
243
248
|
if (this.configSetAdapter[id]) {
|
|
244
249
|
this.selAdapter.push(arrApart[id]);
|
|
245
|
-
this.adapterSelected.push(
|
|
250
|
+
this.adapterSelected.push(tools.capitalize(id));
|
|
246
251
|
}
|
|
247
252
|
}
|
|
248
253
|
|
|
@@ -257,27 +262,27 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
257
262
|
}
|
|
258
263
|
|
|
259
264
|
// create Blacklist
|
|
260
|
-
await
|
|
265
|
+
await crud.createBlacklist(this);
|
|
261
266
|
|
|
262
267
|
// create user defined list with time of error for instances
|
|
263
|
-
await
|
|
268
|
+
await crud.createTimeListInstances(this);
|
|
264
269
|
|
|
265
270
|
//create datapoints for each adapter if selected
|
|
266
271
|
for (const [id] of Object.entries(arrApart)) {
|
|
267
272
|
try {
|
|
268
273
|
if (!this.configCreateOwnFolder) {
|
|
269
|
-
await
|
|
270
|
-
await
|
|
274
|
+
await crud.deleteDPsForEachAdapter(this, id);
|
|
275
|
+
await crud.deleteHtmlListDatapoints(this, id);
|
|
271
276
|
} else {
|
|
272
277
|
if (this.configSetAdapter && this.configSetAdapter[id]) {
|
|
273
|
-
await
|
|
278
|
+
await crud.createDPsForEachAdapter(this, id);
|
|
274
279
|
// create HTML list datapoints
|
|
275
280
|
if (!this.configCreateHtmlList) {
|
|
276
|
-
await
|
|
281
|
+
await crud.deleteHtmlListDatapoints(this, id);
|
|
277
282
|
} else {
|
|
278
|
-
await
|
|
283
|
+
await crud.createHtmlListDatapoints(this, id);
|
|
279
284
|
}
|
|
280
|
-
this.log.debug(`Created datapoints for ${
|
|
285
|
+
this.log.debug(`Created datapoints for ${tools.capitalize(id)}`);
|
|
281
286
|
}
|
|
282
287
|
}
|
|
283
288
|
} catch (error) {
|
|
@@ -287,29 +292,28 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
287
292
|
|
|
288
293
|
// create HTML list datapoints
|
|
289
294
|
if (!this.configCreateHtmlList) {
|
|
290
|
-
await
|
|
291
|
-
await
|
|
295
|
+
await crud.deleteHtmlListDatapoints(this);
|
|
296
|
+
await crud.deleteHtmlListDatapointsInstances(this);
|
|
292
297
|
} else {
|
|
293
|
-
await
|
|
294
|
-
if (this.config.checkAdapterInstances) await
|
|
298
|
+
await crud.createHtmlListDatapoints(this);
|
|
299
|
+
if (this.config.checkAdapterInstances) await crud.createHtmlListDatapointsInstances(this);
|
|
295
300
|
}
|
|
296
|
-
if (!this.config.checkAdapterInstances) await
|
|
301
|
+
if (!this.config.checkAdapterInstances) await crud.deleteHtmlListDatapointsInstances(this);
|
|
297
302
|
|
|
298
|
-
// read data first at start
|
|
299
|
-
// devices
|
|
300
|
-
await this.main();
|
|
301
303
|
|
|
302
304
|
// instances and adapters
|
|
303
305
|
if (this.configCreateInstanceList) {
|
|
304
306
|
// instances
|
|
305
|
-
await
|
|
307
|
+
await crud.createDPsForInstances(this);
|
|
306
308
|
await this.getAllInstanceData();
|
|
307
309
|
// adapter updates
|
|
308
|
-
await
|
|
310
|
+
await crud.createAdapterUpdateData(this, adapterUpdateListDP);
|
|
309
311
|
} else {
|
|
310
|
-
await
|
|
312
|
+
await crud.deleteDPsForInstances(this);
|
|
311
313
|
}
|
|
312
314
|
|
|
315
|
+
await this.main();
|
|
316
|
+
|
|
313
317
|
// update last contact data in interval
|
|
314
318
|
await this.refreshData();
|
|
315
319
|
|
|
@@ -330,12 +334,57 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
330
334
|
|
|
331
335
|
// send overview of instances with error
|
|
332
336
|
if (this.config.checkSendInstanceFailedDaily) await this.sendScheduleNotifications('errorInstance');
|
|
333
|
-
|
|
337
|
+
|
|
338
|
+
} catch (error) {
|
|
334
339
|
this.log.error(`[onReady] - ${error}`);
|
|
335
340
|
this.terminate ? this.terminate(15) : process.exit(15);
|
|
336
341
|
}
|
|
337
342
|
} // <-- onReady end
|
|
338
343
|
|
|
344
|
+
/**
|
|
345
|
+
* main function
|
|
346
|
+
*/
|
|
347
|
+
async main() {
|
|
348
|
+
this.log.debug(`Function started main`);
|
|
349
|
+
this.mainRunning = true;
|
|
350
|
+
|
|
351
|
+
// cancel run if no adapter is selected
|
|
352
|
+
if (this.adapterSelected.length === 0) return;
|
|
353
|
+
|
|
354
|
+
// fill counts and lists of all selected adapter
|
|
355
|
+
try {
|
|
356
|
+
for (let i = 0; i < this.selAdapter.length; i++) {
|
|
357
|
+
await crud.createData(this, i);
|
|
358
|
+
await crud.createLists(this);
|
|
359
|
+
}
|
|
360
|
+
await crud.writeDatapoints(this); // fill the datapoints
|
|
361
|
+
this.log.debug(`Created and filled data for all adapters`);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
this.log.error(`[main - create data of all adapter] - ${error}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// fill datapoints for each adapter if selected
|
|
367
|
+
if (this.configCreateOwnFolder) {
|
|
368
|
+
try {
|
|
369
|
+
for (const [id] of Object.entries(arrApart)) {
|
|
370
|
+
if (this.configSetAdapter && this.configSetAdapter[id]) {
|
|
371
|
+
for (const deviceData of this.listAllDevicesRaw.values()) {
|
|
372
|
+
// list device only if selected adapter matched with device
|
|
373
|
+
if (!deviceData.adapterID.includes(id)) continue;
|
|
374
|
+
await crud.createLists(this, id);
|
|
375
|
+
}
|
|
376
|
+
await crud.writeDatapoints(this, id); // fill the datapoints
|
|
377
|
+
this.log.debug(`Created and filled data for ${tools.capitalize(id)}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
} catch (error) {
|
|
381
|
+
this.log.error(`[main - create and fill datapoints for each adapter] - ${error}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
this.mainRunning = false;
|
|
385
|
+
this.log.debug(`Function finished: ${this.main.name}`);
|
|
386
|
+
} //<--End of main function
|
|
387
|
+
|
|
339
388
|
// If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.
|
|
340
389
|
// You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.
|
|
341
390
|
//
|
|
@@ -517,50 +566,6 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
517
566
|
}
|
|
518
567
|
}
|
|
519
568
|
|
|
520
|
-
/**
|
|
521
|
-
* main function
|
|
522
|
-
*/
|
|
523
|
-
async main() {
|
|
524
|
-
this.log.debug(`Function started: ${this.main.name}`);
|
|
525
|
-
this.mainRunning = true;
|
|
526
|
-
|
|
527
|
-
// cancel run if no adapter is selected
|
|
528
|
-
if (this.adapterSelected.length === 0) return;
|
|
529
|
-
|
|
530
|
-
// fill counts and lists of all selected adapter
|
|
531
|
-
try {
|
|
532
|
-
for (let i = 0; i < this.selAdapter.length; i++) {
|
|
533
|
-
await this.createData(i);
|
|
534
|
-
await this.createLists();
|
|
535
|
-
}
|
|
536
|
-
await this.writeDatapoints(); // fill the datapoints
|
|
537
|
-
this.log.debug(`Created and filled data for all adapters`);
|
|
538
|
-
} catch (error) {
|
|
539
|
-
this.log.error(`[main - create data of all adapter] - ${error}`);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// fill datapoints for each adapter if selected
|
|
543
|
-
if (this.configCreateOwnFolder) {
|
|
544
|
-
try {
|
|
545
|
-
for (const [id] of Object.entries(arrApart)) {
|
|
546
|
-
if (this.configSetAdapter && this.configSetAdapter[id]) {
|
|
547
|
-
for (const deviceData of this.listAllDevicesRaw.values()) {
|
|
548
|
-
// list device only if selected adapter matched with device
|
|
549
|
-
if (!deviceData.adapterID.includes(id)) continue;
|
|
550
|
-
await this.createLists(id);
|
|
551
|
-
}
|
|
552
|
-
await this.writeDatapoints(id); // fill the datapoints
|
|
553
|
-
this.log.debug(`Created and filled data for ${this.capitalize(id)}`);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
} catch (error) {
|
|
557
|
-
this.log.error(`[main - create and fill datapoints for each adapter] - ${error}`);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
this.mainRunning = false;
|
|
561
|
-
this.log.debug(`Function finished: ${this.main.name}`);
|
|
562
|
-
} //<--End of main function
|
|
563
|
-
|
|
564
569
|
/**
|
|
565
570
|
* refresh data with interval
|
|
566
571
|
* is neccessary to refresh lastContact data, especially of devices without state changes
|
|
@@ -570,17 +575,17 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
570
575
|
const nextTimeout = this.config.updateinterval * 1000;
|
|
571
576
|
|
|
572
577
|
// devices data
|
|
573
|
-
await
|
|
574
|
-
await
|
|
575
|
-
await
|
|
578
|
+
await tools.checkLastContact(this);
|
|
579
|
+
await crud.createLists(this);
|
|
580
|
+
await crud.writeDatapoints(this);
|
|
576
581
|
|
|
577
582
|
// devices data in own adapter folder
|
|
578
583
|
if (this.configCreateOwnFolder) {
|
|
579
584
|
for (const [id] of Object.entries(arrApart)) {
|
|
580
585
|
if (this.configSetAdapter && this.configSetAdapter[id]) {
|
|
581
|
-
await
|
|
582
|
-
await
|
|
583
|
-
this.log.debug(`Created and filled data for ${
|
|
586
|
+
await crud.createLists(this, id);
|
|
587
|
+
await crud.writeDatapoints(this, id);
|
|
588
|
+
this.log.debug(`Created and filled data for ${tools.capitalize(id)}`);
|
|
584
589
|
}
|
|
585
590
|
}
|
|
586
591
|
}
|
|
@@ -603,366 +608,6 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
603
608
|
}, nextTimeout);
|
|
604
609
|
} // <-- refreshData end
|
|
605
610
|
|
|
606
|
-
/**
|
|
607
|
-
* create blacklist
|
|
608
|
-
*/
|
|
609
|
-
async createBlacklist() {
|
|
610
|
-
this.log.debug(`Function started: ${this.createBlacklist.name}`);
|
|
611
|
-
|
|
612
|
-
// DEVICES
|
|
613
|
-
const myBlacklist = this.config.tableBlacklist;
|
|
614
|
-
if (myBlacklist.length >= 1) {
|
|
615
|
-
for (const i in myBlacklist) {
|
|
616
|
-
try {
|
|
617
|
-
const blacklistParse = this.parseData(myBlacklist[i].devices);
|
|
618
|
-
// push devices in list to ignor device in lists
|
|
619
|
-
if (myBlacklist[i].checkIgnorLists) {
|
|
620
|
-
this.blacklistLists.push(blacklistParse.path);
|
|
621
|
-
}
|
|
622
|
-
if (myBlacklist[i].checkIgnorAdapterLists) {
|
|
623
|
-
this.blacklistAdapterLists.push(blacklistParse.path);
|
|
624
|
-
}
|
|
625
|
-
// push devices in list to ignor device in notifications
|
|
626
|
-
if (myBlacklist[i].checkIgnorNotify) {
|
|
627
|
-
this.blacklistNotify.push(blacklistParse.path);
|
|
628
|
-
}
|
|
629
|
-
} catch (error) {
|
|
630
|
-
this.log.error(`[createBlacklist] - ${error}`);
|
|
631
|
-
}
|
|
632
|
-
if (this.blacklistLists.length >= 1) this.log.info(`Found devices/services on blacklist for lists: ${this.blacklistLists}`);
|
|
633
|
-
if (this.blacklistAdapterLists.length >= 1) this.log.info(`Found devices/services on blacklist for own adapter lists: ${this.blacklistAdapterLists}`);
|
|
634
|
-
if (this.blacklistNotify.length >= 1) this.log.info(`Found devices/services on blacklist for notifications: ${this.blacklistNotify}`);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// INSTANCES
|
|
639
|
-
const myBlacklistInstances = this.config.tableBlacklistInstances;
|
|
640
|
-
if (myBlacklistInstances.length >= 1) {
|
|
641
|
-
for (const i in myBlacklistInstances) {
|
|
642
|
-
try {
|
|
643
|
-
const blacklistParse = this.parseData(myBlacklistInstances[i].instances);
|
|
644
|
-
// push devices in list to ignor device in lists
|
|
645
|
-
if (myBlacklistInstances[i].checkIgnorLists) {
|
|
646
|
-
this.blacklistInstancesLists.push(blacklistParse.instanceID);
|
|
647
|
-
}
|
|
648
|
-
// push devices in list to ignor device in notifications
|
|
649
|
-
if (myBlacklistInstances[i].checkIgnorNotify) {
|
|
650
|
-
this.blacklistInstancesNotify.push(blacklistParse.instanceID);
|
|
651
|
-
}
|
|
652
|
-
} catch (error) {
|
|
653
|
-
this.log.error(`[createBlacklist] - ${error}`);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
if (this.blacklistInstancesLists.length >= 1) this.log.info(`Found instances items on blacklist for lists: ${this.blacklistInstancesLists}`);
|
|
657
|
-
if (this.blacklistInstancesNotify.length >= 1) this.log.info(`Found instances items on blacklist for notifications: ${this.blacklistInstancesNotify}`);
|
|
658
|
-
}
|
|
659
|
-
this.log.debug(`Function finished: ${this.createBlacklist.name}`);
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
/**
|
|
663
|
-
* create list with time for instances
|
|
664
|
-
*/
|
|
665
|
-
async createTimeListInstances() {
|
|
666
|
-
// INSTANCES
|
|
667
|
-
const userTimeListInstances = this.config.tableTimeInstance;
|
|
668
|
-
if (userTimeListInstances.length >= 1) {
|
|
669
|
-
for (const i in userTimeListInstances) {
|
|
670
|
-
try {
|
|
671
|
-
const userTimeListparse = this.parseData(userTimeListInstances[i].instancesTime);
|
|
672
|
-
// push devices in list to ignor device in lists
|
|
673
|
-
this.userTimeInstancesList.set(userTimeListparse.instanceName, {
|
|
674
|
-
deactivationTime: userTimeListInstances[i].deactivationTime,
|
|
675
|
-
errorTime: userTimeListInstances[i].errorTime,
|
|
676
|
-
});
|
|
677
|
-
} catch (error) {
|
|
678
|
-
this.log.error(`[createTimeListInstances] - ${error}`);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (this.userTimeInstancesList.size >= 1) this.log.info(`Found instances items on lists for timesettings: ${Array.from(this.userTimeInstancesList.keys())}`);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
* @param {object} i - Device Object
|
|
687
|
-
*/
|
|
688
|
-
async createData(i) {
|
|
689
|
-
try {
|
|
690
|
-
const devices = await this.getForeignStatesAsync(this.selAdapter[i].Selektor);
|
|
691
|
-
const adapterID = this.selAdapter[i].adapterID;
|
|
692
|
-
|
|
693
|
-
/*---------- Start of loop ----------*/
|
|
694
|
-
for (const [id] of Object.entries(devices)) {
|
|
695
|
-
if (id.endsWith('.')) continue;
|
|
696
|
-
const mainSelector = id;
|
|
697
|
-
|
|
698
|
-
/*=============================================
|
|
699
|
-
= get Instanz =
|
|
700
|
-
=============================================*/
|
|
701
|
-
const instance = id.slice(0, id.indexOf('.') + 2);
|
|
702
|
-
|
|
703
|
-
const instanceDeviceConnectionDP = `${instance}.info.connection`;
|
|
704
|
-
const instancedeviceConnected = await this.getInitValue(instanceDeviceConnectionDP);
|
|
705
|
-
this.subscribeForeignStates(instanceDeviceConnectionDP);
|
|
706
|
-
this.subscribeForeignObjects(`${this.selAdapter[i].Selektor}`);
|
|
707
|
-
// this.subscribeForeignObjects('*');
|
|
708
|
-
//this.subscribeForeignStates('*');
|
|
709
|
-
/*=============================================
|
|
710
|
-
= Get device name =
|
|
711
|
-
=============================================*/
|
|
712
|
-
const deviceName = await this.getDeviceName(id, i);
|
|
713
|
-
|
|
714
|
-
/*=============================================
|
|
715
|
-
= Get adapter name =
|
|
716
|
-
=============================================*/
|
|
717
|
-
const adapter = this.selAdapter[i].adapter;
|
|
718
|
-
|
|
719
|
-
/*=============================================
|
|
720
|
-
= Get path to datapoints =
|
|
721
|
-
=============================================*/
|
|
722
|
-
const currDeviceString = id.slice(0, id.lastIndexOf('.') + 1 - 1);
|
|
723
|
-
const shortCurrDeviceString = currDeviceString.slice(0, currDeviceString.lastIndexOf('.') + 1 - 1);
|
|
724
|
-
|
|
725
|
-
// subscribe to object device path
|
|
726
|
-
this.subscribeForeignStates(currDeviceString);
|
|
727
|
-
|
|
728
|
-
/*=============================================
|
|
729
|
-
= Get signal strength =
|
|
730
|
-
=============================================*/
|
|
731
|
-
let deviceQualityDP = currDeviceString + this.selAdapter[i].rssiState;
|
|
732
|
-
let deviceQualityState;
|
|
733
|
-
|
|
734
|
-
switch (adapterID) {
|
|
735
|
-
case 'mihomeVacuum':
|
|
736
|
-
deviceQualityDP = shortCurrDeviceString + this.selAdapter[i].rssiState;
|
|
737
|
-
deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
|
|
738
|
-
break;
|
|
739
|
-
|
|
740
|
-
case 'netatmo':
|
|
741
|
-
deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
|
|
742
|
-
if (!deviceQualityState) {
|
|
743
|
-
deviceQualityDP = currDeviceString + this.selAdapter[i].rfState;
|
|
744
|
-
deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
|
|
745
|
-
}
|
|
746
|
-
break;
|
|
747
|
-
|
|
748
|
-
default:
|
|
749
|
-
deviceQualityState = await this.getForeignStateAsync(deviceQualityDP);
|
|
750
|
-
break;
|
|
751
|
-
}
|
|
752
|
-
//subscribe to states
|
|
753
|
-
this.subscribeForeignStates(deviceQualityDP);
|
|
754
|
-
|
|
755
|
-
const signalData = await this.calculateSignalStrength(deviceQualityState, adapterID);
|
|
756
|
-
let linkQuality = signalData[0];
|
|
757
|
-
const linkQualityRaw = signalData[1];
|
|
758
|
-
|
|
759
|
-
/*=============================================
|
|
760
|
-
= Get battery data =
|
|
761
|
-
=============================================*/
|
|
762
|
-
let deviceBatteryStateDP;
|
|
763
|
-
let deviceBatteryState;
|
|
764
|
-
let batteryHealth;
|
|
765
|
-
let batteryHealthRaw;
|
|
766
|
-
let batteryUnitRaw;
|
|
767
|
-
let lowBatIndicator;
|
|
768
|
-
let isBatteryDevice;
|
|
769
|
-
let isLowBatDP;
|
|
770
|
-
let faultReportingDP;
|
|
771
|
-
let faultReportingState;
|
|
772
|
-
|
|
773
|
-
const deviceChargerStateDP = currDeviceString + this.selAdapter[i].charger;
|
|
774
|
-
const deviceChargerState = await this.getInitValue(deviceChargerStateDP);
|
|
775
|
-
|
|
776
|
-
if (deviceChargerState === undefined || deviceChargerState === false) {
|
|
777
|
-
// Get battery states
|
|
778
|
-
switch (adapterID) {
|
|
779
|
-
case 'hmrpc':
|
|
780
|
-
deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
|
|
781
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
782
|
-
|
|
783
|
-
if (deviceBatteryState === undefined) {
|
|
784
|
-
deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].hmDNBattery;
|
|
785
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
786
|
-
}
|
|
787
|
-
break;
|
|
788
|
-
case 'hueExt':
|
|
789
|
-
case 'mihomeVacuum':
|
|
790
|
-
case 'mqttNuki':
|
|
791
|
-
case 'loqedSmartLock':
|
|
792
|
-
deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery;
|
|
793
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
794
|
-
|
|
795
|
-
if (deviceBatteryState === undefined) {
|
|
796
|
-
deviceBatteryStateDP = shortCurrDeviceString + this.selAdapter[i].battery2;
|
|
797
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
798
|
-
}
|
|
799
|
-
break;
|
|
800
|
-
default:
|
|
801
|
-
deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery;
|
|
802
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
803
|
-
|
|
804
|
-
if (deviceBatteryState === undefined) {
|
|
805
|
-
deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery2;
|
|
806
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
807
|
-
|
|
808
|
-
if (deviceBatteryState === undefined) {
|
|
809
|
-
deviceBatteryStateDP = currDeviceString + this.selAdapter[i].battery3;
|
|
810
|
-
deviceBatteryState = await this.getInitValue(deviceBatteryStateDP);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
break;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// Get low bat states
|
|
817
|
-
isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat;
|
|
818
|
-
let deviceLowBatState = await this.getInitValue(isLowBatDP);
|
|
819
|
-
|
|
820
|
-
if (deviceLowBatState === undefined) {
|
|
821
|
-
isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat2;
|
|
822
|
-
deviceLowBatState = await this.getInitValue(isLowBatDP);
|
|
823
|
-
|
|
824
|
-
if (deviceLowBatState === undefined) {
|
|
825
|
-
isLowBatDP = currDeviceString + this.selAdapter[i].isLowBat3;
|
|
826
|
-
deviceLowBatState = await this.getInitValue(isLowBatDP);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
if (deviceLowBatState === undefined) isLowBatDP = 'none';
|
|
830
|
-
|
|
831
|
-
faultReportingDP = shortCurrDeviceString + this.selAdapter[i].faultReporting;
|
|
832
|
-
faultReportingState = await this.getInitValue(faultReportingDP);
|
|
833
|
-
|
|
834
|
-
//subscribe to states
|
|
835
|
-
this.subscribeForeignStates(deviceBatteryStateDP);
|
|
836
|
-
this.subscribeForeignStates(isLowBatDP);
|
|
837
|
-
this.subscribeForeignStates(faultReportingDP);
|
|
838
|
-
|
|
839
|
-
const batteryData = await this.getBatteryData(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
|
|
840
|
-
batteryHealth = batteryData[0];
|
|
841
|
-
batteryHealthRaw = batteryData[2];
|
|
842
|
-
batteryUnitRaw = batteryData[3];
|
|
843
|
-
isBatteryDevice = batteryData[1];
|
|
844
|
-
|
|
845
|
-
if (isBatteryDevice) {
|
|
846
|
-
lowBatIndicator = await this.setLowbatIndicator(deviceBatteryState, deviceLowBatState, faultReportingState, adapterID);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/*=============================================
|
|
851
|
-
= Get last contact of device =
|
|
852
|
-
=============================================*/
|
|
853
|
-
let unreachDP = currDeviceString + this.selAdapter[i].reach;
|
|
854
|
-
const deviceStateSelectorDP = shortCurrDeviceString + this.selAdapter[i].stateValue;
|
|
855
|
-
const rssiPeerSelectorDP = currDeviceString + this.selAdapter[i].rssiPeerState;
|
|
856
|
-
let timeSelector = currDeviceString + this.selAdapter[i].timeSelector;
|
|
857
|
-
|
|
858
|
-
const timeSelectorState = await this.getInitValue(timeSelector);
|
|
859
|
-
if (timeSelectorState === undefined) {
|
|
860
|
-
timeSelector = shortCurrDeviceString + this.selAdapter[i].timeSelector;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
let deviceUnreachState = await this.getInitValue(unreachDP);
|
|
864
|
-
if (deviceUnreachState === undefined) {
|
|
865
|
-
unreachDP = shortCurrDeviceString + this.selAdapter[i].reach;
|
|
866
|
-
deviceUnreachState = await this.getInitValue(shortCurrDeviceString + this.selAdapter[i].reach);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// subscribe to states
|
|
870
|
-
this.subscribeForeignStates(timeSelector);
|
|
871
|
-
this.subscribeForeignStates(unreachDP);
|
|
872
|
-
this.subscribeForeignStates(deviceStateSelectorDP);
|
|
873
|
-
this.subscribeForeignStates(rssiPeerSelectorDP);
|
|
874
|
-
|
|
875
|
-
const onlineState = await this.getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorDP, rssiPeerSelectorDP);
|
|
876
|
-
let deviceState;
|
|
877
|
-
let lastContactString;
|
|
878
|
-
|
|
879
|
-
if (onlineState) {
|
|
880
|
-
lastContactString = onlineState[0];
|
|
881
|
-
deviceState = onlineState[1];
|
|
882
|
-
linkQuality = onlineState[2];
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
/*=============================================
|
|
886
|
-
= Get update data =
|
|
887
|
-
=============================================*/
|
|
888
|
-
let isUpgradable;
|
|
889
|
-
let deviceUpdateDP;
|
|
890
|
-
|
|
891
|
-
if (this.config.checkSendDeviceUpgrade) {
|
|
892
|
-
deviceUpdateDP = currDeviceString + this.selAdapter[i].upgrade;
|
|
893
|
-
let deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
|
|
894
|
-
if (deviceUpdateSelector === undefined) {
|
|
895
|
-
deviceUpdateDP = shortCurrDeviceString + this.selAdapter[i].upgrade;
|
|
896
|
-
deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
|
|
897
|
-
if (deviceUpdateSelector === undefined) {
|
|
898
|
-
const shortShortCurrDeviceString = shortCurrDeviceString.slice(0, shortCurrDeviceString.lastIndexOf('.') + 1 - 1);
|
|
899
|
-
deviceUpdateDP = shortShortCurrDeviceString + this.selAdapter[i].upgrade;
|
|
900
|
-
deviceUpdateSelector = await this.getInitValue(deviceUpdateDP);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
if (deviceUpdateSelector !== undefined) {
|
|
905
|
-
isUpgradable = await this.checkDeviceUpdate(adapterID, deviceUpdateSelector);
|
|
906
|
-
} else {
|
|
907
|
-
isUpgradable = ' - ';
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
// subscribe to states
|
|
911
|
-
this.subscribeForeignStates(deviceUpdateDP);
|
|
912
|
-
// this.subscribeForeignStates('*');
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
/*=============================================
|
|
916
|
-
= Fill Raw Lists =
|
|
917
|
-
=============================================*/
|
|
918
|
-
const setupList = () => {
|
|
919
|
-
this.listAllDevicesRaw.set(currDeviceString, {
|
|
920
|
-
Path: id,
|
|
921
|
-
mainSelector: mainSelector,
|
|
922
|
-
instanceDeviceConnectionDP: instanceDeviceConnectionDP,
|
|
923
|
-
instancedeviceConnected: instancedeviceConnected,
|
|
924
|
-
instance: instance,
|
|
925
|
-
Device: deviceName,
|
|
926
|
-
adapterID: adapterID,
|
|
927
|
-
Adapter: adapter,
|
|
928
|
-
timeSelector: timeSelector,
|
|
929
|
-
isBatteryDevice: isBatteryDevice,
|
|
930
|
-
Battery: batteryHealth,
|
|
931
|
-
BatteryRaw: batteryHealthRaw,
|
|
932
|
-
BatteryUnitRaw: batteryUnitRaw,
|
|
933
|
-
batteryDP: deviceBatteryStateDP,
|
|
934
|
-
LowBat: lowBatIndicator,
|
|
935
|
-
LowBatDP: isLowBatDP,
|
|
936
|
-
faultReport: faultReportingState,
|
|
937
|
-
faultReportDP: faultReportingDP,
|
|
938
|
-
SignalStrengthDP: deviceQualityDP,
|
|
939
|
-
SignalStrength: linkQuality,
|
|
940
|
-
SignalStrengthRaw: linkQualityRaw,
|
|
941
|
-
UnreachState: deviceUnreachState,
|
|
942
|
-
UnreachDP: unreachDP,
|
|
943
|
-
DeviceStateSelectorDP: deviceStateSelectorDP,
|
|
944
|
-
rssiPeerSelectorDP: rssiPeerSelectorDP,
|
|
945
|
-
LastContact: lastContactString,
|
|
946
|
-
Status: deviceState,
|
|
947
|
-
UpdateDP: deviceUpdateDP,
|
|
948
|
-
Upgradable: isUpgradable,
|
|
949
|
-
});
|
|
950
|
-
};
|
|
951
|
-
|
|
952
|
-
if (!this.configListOnlyBattery) {
|
|
953
|
-
// Add all devices
|
|
954
|
-
setupList();
|
|
955
|
-
} else {
|
|
956
|
-
// Add only devices with battery in the rawlist
|
|
957
|
-
if (!isBatteryDevice) continue;
|
|
958
|
-
setupList();
|
|
959
|
-
}
|
|
960
|
-
} // <-- end of loop
|
|
961
|
-
} catch (error) {
|
|
962
|
-
this.log.error(`[createData - create data of devices] - ${error}`);
|
|
963
|
-
}
|
|
964
|
-
} // <-- end of createData
|
|
965
|
-
|
|
966
611
|
/*=============================================
|
|
967
612
|
= functions to get data =
|
|
968
613
|
=============================================*/
|
|
@@ -989,7 +634,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
989
634
|
|
|
990
635
|
switch (this.selAdapter[i].adapterID) {
|
|
991
636
|
case 'fullybrowser':
|
|
992
|
-
deviceName = (await
|
|
637
|
+
deviceName = (await tools.getInitValue(this,currDeviceString + this.selAdapter[i].id)) + ' ' + (await tools.getInitValue(this,currDeviceString + this.selAdapter[i].id2));
|
|
993
638
|
break;
|
|
994
639
|
|
|
995
640
|
// Get ID with short currDeviceString from objectjson
|
|
@@ -1018,7 +663,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1018
663
|
case 'mihomeVacuum':
|
|
1019
664
|
case 'roomba':
|
|
1020
665
|
folderName = shortCurrDeviceString.slice(shortCurrDeviceString.lastIndexOf('.') + 1);
|
|
1021
|
-
deviceID = await
|
|
666
|
+
deviceID = await tools.getInitValue(this,shortCurrDeviceString + this.selAdapter[i].id);
|
|
1022
667
|
deviceName = `I${folderName} ${deviceID}`;
|
|
1023
668
|
break;
|
|
1024
669
|
|
|
@@ -1026,7 +671,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1026
671
|
case 'tado':
|
|
1027
672
|
case 'wifilight':
|
|
1028
673
|
case 'fullybrowserV3':
|
|
1029
|
-
|
|
674
|
+
case 'sonoff':
|
|
1030
675
|
deviceName = currDeviceString.slice(currDeviceString.lastIndexOf('.') + 1);
|
|
1031
676
|
break;
|
|
1032
677
|
|
|
@@ -1050,7 +695,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1050
695
|
|
|
1051
696
|
// Get ID with main selektor from objectjson
|
|
1052
697
|
default:
|
|
1053
|
-
if (this.selAdapter[i].id !== 'none' || this.selAdapter[i].id !== undefined) deviceName = await
|
|
698
|
+
if (this.selAdapter[i].id !== 'none' || this.selAdapter[i].id !== undefined) deviceName = await tools.getInitValue(this,currDeviceString + this.selAdapter[i].id);
|
|
1054
699
|
if (deviceName === null || deviceName === undefined) {
|
|
1055
700
|
if (deviceObject && typeof deviceObject === 'object' && deviceObject.common) {
|
|
1056
701
|
deviceName = deviceObject.common.name;
|
|
@@ -1263,7 +908,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1263
908
|
* @param {object} selector - Selector
|
|
1264
909
|
*/
|
|
1265
910
|
async getLastContact(selector) {
|
|
1266
|
-
const lastContact =
|
|
911
|
+
const lastContact = tools.getTimestamp(selector);
|
|
1267
912
|
let lastContactString;
|
|
1268
913
|
|
|
1269
914
|
lastContactString = `${this.formatDate(new Date(selector), 'hh:mm')}`;
|
|
@@ -1283,19 +928,29 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1283
928
|
* @param {string} unreachDP - Datapoint of Unreach
|
|
1284
929
|
* @param {object} linkQuality - Linkquality Value
|
|
1285
930
|
* @param {object} deviceUnreachState - State of deviceUnreach datapoint
|
|
1286
|
-
* @param {string}
|
|
1287
|
-
* @param {string}
|
|
931
|
+
* @param {string} deviceStateSelectorHMRPC - Selector of device state (like .state)
|
|
932
|
+
* @param {string} rssiPeerSelectorHMRPC - HM RSSI Peer Datapoint
|
|
1288
933
|
*/
|
|
1289
|
-
async getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState,
|
|
934
|
+
async getOnlineState(timeSelector, adapterID, unreachDP, linkQuality, deviceUnreachState, deviceStateSelectorHMRPC, rssiPeerSelectorHMRPC) {
|
|
1290
935
|
let lastContactString;
|
|
1291
936
|
let deviceState = 'Online';
|
|
1292
937
|
|
|
1293
938
|
try {
|
|
1294
939
|
const deviceTimeSelector = await this.getForeignStateAsync(timeSelector);
|
|
1295
940
|
const deviceUnreachSelector = await this.getForeignStateAsync(unreachDP);
|
|
1296
|
-
const deviceStateSelector = await this.getForeignStateAsync(
|
|
1297
|
-
const rssiPeerSelector = await this.getForeignStateAsync(
|
|
1298
|
-
const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ?
|
|
941
|
+
const deviceStateSelector = await this.getForeignStateAsync(deviceStateSelectorHMRPC); // for hmrpc devices
|
|
942
|
+
const rssiPeerSelector = await this.getForeignStateAsync(rssiPeerSelectorHMRPC);
|
|
943
|
+
const lastDeviceUnreachStateChange = deviceUnreachSelector != undefined ? tools.getTimestamp(deviceUnreachSelector.lc) : tools.getTimestamp(timeSelector.ts);
|
|
944
|
+
|
|
945
|
+
// ignore disabled device from zigbee2MQTT
|
|
946
|
+
if (adapterID === 'zigbee2MQTT') {
|
|
947
|
+
const is_device_disabled = await tools.isDisabledDevice(this, unreachDP.substring(0, unreachDP.lastIndexOf('.')));
|
|
948
|
+
|
|
949
|
+
if (is_device_disabled) {
|
|
950
|
+
return [null, 'disabled', '0%'];
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
1299
954
|
// If there is no contact since user sets minutes add device in offline list
|
|
1300
955
|
// calculate to days after 48 hours
|
|
1301
956
|
switch (unreachDP) {
|
|
@@ -1335,7 +990,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1335
990
|
= Set Online Status =
|
|
1336
991
|
=============================================*/
|
|
1337
992
|
let lastContact;
|
|
1338
|
-
if (deviceTimeSelector) lastContact =
|
|
993
|
+
if (deviceTimeSelector) lastContact = tools.getTimestamp(deviceTimeSelector.ts);
|
|
1339
994
|
|
|
1340
995
|
if (this.configMaxMinutes !== undefined) {
|
|
1341
996
|
switch (adapterID) {
|
|
@@ -1458,38 +1113,6 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1458
1113
|
}
|
|
1459
1114
|
}
|
|
1460
1115
|
|
|
1461
|
-
/**
|
|
1462
|
-
* when was last contact of device
|
|
1463
|
-
*/
|
|
1464
|
-
async checkLastContact() {
|
|
1465
|
-
for (const [deviceID, deviceData] of this.listAllDevicesRaw.entries()) {
|
|
1466
|
-
if (deviceData.instancedeviceConnected !== false) {
|
|
1467
|
-
const oldContactState = deviceData.Status;
|
|
1468
|
-
deviceData.UnreachState = await this.getInitValue(deviceData.UnreachDP);
|
|
1469
|
-
const contactData = await this.getOnlineState(
|
|
1470
|
-
deviceData.timeSelector,
|
|
1471
|
-
deviceData.adapterID,
|
|
1472
|
-
deviceData.UnreachDP,
|
|
1473
|
-
deviceData.SignalStrength,
|
|
1474
|
-
deviceData.UnreachState,
|
|
1475
|
-
deviceData.DeviceStateSelectorDP,
|
|
1476
|
-
deviceData.rssiPeerSelectorDP,
|
|
1477
|
-
);
|
|
1478
|
-
if (contactData !== undefined) {
|
|
1479
|
-
deviceData.LastContact = contactData[0];
|
|
1480
|
-
deviceData.Status = contactData[1];
|
|
1481
|
-
deviceData.linkQuality = contactData[2];
|
|
1482
|
-
}
|
|
1483
|
-
if (this.config.checkSendOfflineMsg && oldContactState !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
|
|
1484
|
-
// check if the generally deviceData connected state is for a while true
|
|
1485
|
-
if (await this.getTimestampConnectionDP(deviceData.instanceDeviceConnectionDP, 50000)) {
|
|
1486
|
-
await this.sendStateNotifications('Devices', 'onlineStateDevice', deviceID);
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
1116
|
/**
|
|
1494
1117
|
* @param {any} adapterID
|
|
1495
1118
|
* @param {string | number | boolean | null} deviceUpdateSelector
|
|
@@ -1526,402 +1149,91 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1526
1149
|
}
|
|
1527
1150
|
|
|
1528
1151
|
/**
|
|
1529
|
-
*
|
|
1530
|
-
* @param {
|
|
1152
|
+
* fill the lists for user
|
|
1153
|
+
* @param {object} device
|
|
1531
1154
|
*/
|
|
1532
|
-
async
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1155
|
+
async theLists(device) {
|
|
1156
|
+
// Raw List with all devices for user
|
|
1157
|
+
if (device.Status !== 'disabled') {
|
|
1158
|
+
|
|
1159
|
+
this.listAllDevicesUserRaw.push({
|
|
1160
|
+
Device: device.Device,
|
|
1161
|
+
Adapter: device.Adapter,
|
|
1162
|
+
Instance: device.instance,
|
|
1163
|
+
'Instance connected': device.instancedeviceConnected,
|
|
1164
|
+
isBatteryDevice: device.isBatteryDevice,
|
|
1165
|
+
Battery: device.Battery,
|
|
1166
|
+
BatteryRaw: device.BatteryRaw,
|
|
1167
|
+
BatteryUnitRaw: device.BatteryUnitRaw,
|
|
1168
|
+
isLowBat: device.LowBat,
|
|
1169
|
+
'Signal strength': device.SignalStrength,
|
|
1170
|
+
'Signal strength Raw': device.SignalStrengthRaw,
|
|
1171
|
+
'Last contact': device.LastContact,
|
|
1172
|
+
'Update Available': device.Upgradable,
|
|
1173
|
+
Status: device.Status,
|
|
1174
|
+
});
|
|
1543
1175
|
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1176
|
+
// List with all devices
|
|
1177
|
+
this.listAllDevices.push({
|
|
1178
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1179
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1180
|
+
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1181
|
+
[translations.Signal_strength[this.config.userSelectedLanguage]]: device.SignalStrength,
|
|
1182
|
+
[translations.Last_Contact[this.config.userSelectedLanguage]]: device.LastContact,
|
|
1183
|
+
[translations.Status[this.config.userSelectedLanguage]]: device.Status,
|
|
1184
|
+
});
|
|
1547
1185
|
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
Device: deviceData.Device,
|
|
1555
|
-
Adapter: deviceData.Adapter,
|
|
1556
|
-
Battery: deviceData.Battery,
|
|
1186
|
+
// LinkQuality lists
|
|
1187
|
+
if (device.SignalStrength != ' - ') {
|
|
1188
|
+
this.linkQualityDevices.push({
|
|
1189
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1190
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1191
|
+
[translations.Signal_strength[this.config.userSelectedLanguage]]: device.SignalStrength,
|
|
1557
1192
|
});
|
|
1558
1193
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
Device:
|
|
1564
|
-
Adapter:
|
|
1565
|
-
|
|
1194
|
+
|
|
1195
|
+
// Battery lists
|
|
1196
|
+
if (device.isBatteryDevice) {
|
|
1197
|
+
this.batteryPowered.push({
|
|
1198
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1199
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1200
|
+
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1201
|
+
[translations.Status[this.config.userSelectedLanguage]]: device.Status,
|
|
1566
1202
|
});
|
|
1567
1203
|
}
|
|
1568
1204
|
|
|
1569
|
-
//
|
|
1570
|
-
if (
|
|
1571
|
-
this.
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1205
|
+
// Low Bat lists
|
|
1206
|
+
if (device.LowBat && device.Status !== 'Offline') {
|
|
1207
|
+
this.batteryLowPowered.push({
|
|
1208
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1209
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1210
|
+
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1575
1211
|
});
|
|
1576
1212
|
}
|
|
1577
1213
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1214
|
+
// Offline List
|
|
1215
|
+
if (device.Status === 'Offline') {
|
|
1216
|
+
this.offlineDevices.push({
|
|
1217
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1218
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1219
|
+
[translations.Last_Contact[this.config.userSelectedLanguage]]: device.LastContact,
|
|
1220
|
+
});
|
|
1580
1221
|
}
|
|
1581
1222
|
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1223
|
+
// Device update List
|
|
1224
|
+
if (device.Upgradable === true || device.Upgradable === 1) {
|
|
1225
|
+
this.upgradableList.push({
|
|
1226
|
+
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1227
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1228
|
+
});
|
|
1587
1229
|
}
|
|
1588
1230
|
}
|
|
1589
|
-
await this.countDevices();
|
|
1590
1231
|
}
|
|
1591
1232
|
|
|
1233
|
+
|
|
1592
1234
|
/**
|
|
1593
|
-
*
|
|
1594
|
-
* @param {
|
|
1595
|
-
*/
|
|
1596
|
-
async theLists(device) {
|
|
1597
|
-
// Raw List with all devices for user
|
|
1598
|
-
this.listAllDevicesUserRaw.push({
|
|
1599
|
-
Device: device.Device,
|
|
1600
|
-
Adapter: device.Adapter,
|
|
1601
|
-
Instance: device.instance,
|
|
1602
|
-
'Instance connected': device.instancedeviceConnected,
|
|
1603
|
-
isBatteryDevice: device.isBatteryDevice,
|
|
1604
|
-
Battery: device.Battery,
|
|
1605
|
-
BatteryRaw: device.BatteryRaw,
|
|
1606
|
-
BatteryUnitRaw: device.BatteryUnitRaw,
|
|
1607
|
-
isLowBat: device.LowBat,
|
|
1608
|
-
'Signal strength': device.SignalStrength,
|
|
1609
|
-
'Signal strength Raw': device.SignalStrengthRaw,
|
|
1610
|
-
'Last contact': device.LastContact,
|
|
1611
|
-
'Update Available': device.Upgradable,
|
|
1612
|
-
Status: device.Status,
|
|
1613
|
-
});
|
|
1614
|
-
|
|
1615
|
-
// List with all devices
|
|
1616
|
-
this.listAllDevices.push({
|
|
1617
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1618
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1619
|
-
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1620
|
-
[translations.Signal_strength[this.config.userSelectedLanguage]]: device.SignalStrength,
|
|
1621
|
-
[translations.Last_Contact[this.config.userSelectedLanguage]]: device.LastContact,
|
|
1622
|
-
[translations.Status[this.config.userSelectedLanguage]]: device.Status,
|
|
1623
|
-
});
|
|
1624
|
-
|
|
1625
|
-
// LinkQuality lists
|
|
1626
|
-
if (device.SignalStrength != ' - ') {
|
|
1627
|
-
this.linkQualityDevices.push({
|
|
1628
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1629
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1630
|
-
[translations.Signal_strength[this.config.userSelectedLanguage]]: device.SignalStrength,
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
// Battery lists
|
|
1635
|
-
if (device.isBatteryDevice) {
|
|
1636
|
-
this.batteryPowered.push({
|
|
1637
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1638
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1639
|
-
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1640
|
-
[translations.Status[this.config.userSelectedLanguage]]: device.Status,
|
|
1641
|
-
});
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
// Low Bat lists
|
|
1645
|
-
if (device.LowBat && device.Status !== 'Offline') {
|
|
1646
|
-
this.batteryLowPowered.push({
|
|
1647
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1648
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1649
|
-
[translations.Battery[this.config.userSelectedLanguage]]: device.Battery,
|
|
1650
|
-
});
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
// Offline List
|
|
1654
|
-
if (device.Status === 'Offline') {
|
|
1655
|
-
this.offlineDevices.push({
|
|
1656
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1657
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1658
|
-
[translations.Last_Contact[this.config.userSelectedLanguage]]: device.LastContact,
|
|
1659
|
-
});
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
// Device update List
|
|
1663
|
-
if (device.Upgradable === true || device.Upgradable === 1) {
|
|
1664
|
-
this.upgradableList.push({
|
|
1665
|
-
[translations.Device[this.config.userSelectedLanguage]]: device.Device,
|
|
1666
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: device.Adapter,
|
|
1667
|
-
});
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
/**
|
|
1672
|
-
* Count devices for each type
|
|
1673
|
-
*/
|
|
1674
|
-
async countDevices() {
|
|
1675
|
-
// Count how many devices with link Quality
|
|
1676
|
-
this.linkQualityCount = this.linkQualityDevices.length;
|
|
1677
|
-
|
|
1678
|
-
// Count how many devcies are offline
|
|
1679
|
-
this.offlineDevicesCount = this.offlineDevices.length;
|
|
1680
|
-
|
|
1681
|
-
// Count how many devices are with battery
|
|
1682
|
-
this.batteryPoweredCount = this.batteryPowered.length;
|
|
1683
|
-
|
|
1684
|
-
// 3d. Count how many devices are with low battery
|
|
1685
|
-
this.lowBatteryPoweredCount = this.batteryLowPowered.length;
|
|
1686
|
-
|
|
1687
|
-
// Count how many devices are exists
|
|
1688
|
-
this.deviceCounter = this.listAllDevices.length;
|
|
1689
|
-
|
|
1690
|
-
// Count how many devices has update available
|
|
1691
|
-
this.upgradableDevicesCount = this.upgradableList.length;
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
/**
|
|
1695
|
-
* @param {string} [adptName] - Adaptername
|
|
1696
|
-
*/
|
|
1697
|
-
async writeDatapoints(adptName) {
|
|
1698
|
-
// fill the datapoints
|
|
1699
|
-
this.log.debug(`Start the function: ${this.writeDatapoints.name}`);
|
|
1700
|
-
|
|
1701
|
-
try {
|
|
1702
|
-
let dpSubFolder;
|
|
1703
|
-
//write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
|
|
1704
|
-
if (adptName) {
|
|
1705
|
-
dpSubFolder = adptName + '.';
|
|
1706
|
-
} else {
|
|
1707
|
-
dpSubFolder = '';
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
// Write Datapoints for counts
|
|
1711
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}offlineCount`, { val: this.offlineDevicesCount, ack: true });
|
|
1712
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}countAll`, { val: this.deviceCounter, ack: true });
|
|
1713
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}batteryCount`, { val: this.batteryPoweredCount, ack: true });
|
|
1714
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryCount`, { val: this.lowBatteryPoweredCount, ack: true });
|
|
1715
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableCount`, { val: this.upgradableDevicesCount, ack: true });
|
|
1716
|
-
// List all devices
|
|
1717
|
-
if (this.deviceCounter === 0) {
|
|
1718
|
-
// if no device is count, write the JSON List with default value
|
|
1719
|
-
this.listAllDevices = [
|
|
1720
|
-
{
|
|
1721
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1722
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1723
|
-
[translations.Battery[this.config.userSelectedLanguage]]: '',
|
|
1724
|
-
[translations.Signal_strength[this.config.userSelectedLanguage]]: '',
|
|
1725
|
-
[translations.Last_Contact[this.config.userSelectedLanguage]]: '',
|
|
1726
|
-
[translations.Status[this.config.userSelectedLanguage]]: '',
|
|
1727
|
-
},
|
|
1728
|
-
];
|
|
1729
|
-
this.listAllDevicesUserRaw = [
|
|
1730
|
-
{
|
|
1731
|
-
Device: '--none--',
|
|
1732
|
-
Adapter: '',
|
|
1733
|
-
Instance: '',
|
|
1734
|
-
'Instance connected': '',
|
|
1735
|
-
isBatteryDevice: '',
|
|
1736
|
-
Battery: '',
|
|
1737
|
-
BatteryRaw: '',
|
|
1738
|
-
isLowBat: '',
|
|
1739
|
-
'Signal strength': '',
|
|
1740
|
-
'Last contact': '',
|
|
1741
|
-
UpdateAvailable: '',
|
|
1742
|
-
Status: '',
|
|
1743
|
-
},
|
|
1744
|
-
];
|
|
1745
|
-
}
|
|
1746
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}listAll`, { val: JSON.stringify(this.listAllDevices), ack: true });
|
|
1747
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}listAllRawJSON`, { val: JSON.stringify(this.listAllDevicesUserRaw), ack: true });
|
|
1748
|
-
|
|
1749
|
-
// List link quality
|
|
1750
|
-
if (this.linkQualityCount === 0) {
|
|
1751
|
-
// if no device is count, write the JSON List with default value
|
|
1752
|
-
this.linkQualityDevices = [
|
|
1753
|
-
{
|
|
1754
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1755
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1756
|
-
[translations.Signal_strength[this.config.userSelectedLanguage]]: '',
|
|
1757
|
-
},
|
|
1758
|
-
];
|
|
1759
|
-
}
|
|
1760
|
-
//write JSON list
|
|
1761
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityList`, {
|
|
1762
|
-
val: JSON.stringify(this.linkQualityDevices),
|
|
1763
|
-
ack: true,
|
|
1764
|
-
});
|
|
1765
|
-
|
|
1766
|
-
// List offline devices
|
|
1767
|
-
if (this.offlineDevicesCount === 0) {
|
|
1768
|
-
// if no device is count, write the JSON List with default value
|
|
1769
|
-
this.offlineDevices = [
|
|
1770
|
-
{
|
|
1771
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1772
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1773
|
-
[translations.Last_Contact[this.config.userSelectedLanguage]]: '',
|
|
1774
|
-
},
|
|
1775
|
-
];
|
|
1776
|
-
}
|
|
1777
|
-
//write JSON list
|
|
1778
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}offlineList`, {
|
|
1779
|
-
val: JSON.stringify(this.offlineDevices),
|
|
1780
|
-
ack: true,
|
|
1781
|
-
});
|
|
1782
|
-
|
|
1783
|
-
// List updatable
|
|
1784
|
-
if (this.upgradableDevicesCount === 0) {
|
|
1785
|
-
// if no device is count, write the JSON List with default value
|
|
1786
|
-
this.upgradableList = [
|
|
1787
|
-
{
|
|
1788
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1789
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1790
|
-
[translations.Last_Contact[this.config.userSelectedLanguage]]: '',
|
|
1791
|
-
},
|
|
1792
|
-
];
|
|
1793
|
-
}
|
|
1794
|
-
//write JSON list
|
|
1795
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}upgradableList`, {
|
|
1796
|
-
val: JSON.stringify(this.upgradableList),
|
|
1797
|
-
ack: true,
|
|
1798
|
-
});
|
|
1799
|
-
|
|
1800
|
-
// List battery powered
|
|
1801
|
-
if (this.batteryPoweredCount === 0) {
|
|
1802
|
-
// if no device is count, write the JSON List with default value
|
|
1803
|
-
this.batteryPowered = [
|
|
1804
|
-
{
|
|
1805
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1806
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1807
|
-
[translations.Battery[this.config.userSelectedLanguage]]: '',
|
|
1808
|
-
},
|
|
1809
|
-
];
|
|
1810
|
-
}
|
|
1811
|
-
//write JSON list
|
|
1812
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}batteryList`, {
|
|
1813
|
-
val: JSON.stringify(this.batteryPowered),
|
|
1814
|
-
ack: true,
|
|
1815
|
-
});
|
|
1816
|
-
|
|
1817
|
-
// list battery low powered
|
|
1818
|
-
if (this.lowBatteryPoweredCount === 0) {
|
|
1819
|
-
// if no device is count, write the JSON List with default value
|
|
1820
|
-
this.batteryLowPowered = [
|
|
1821
|
-
{
|
|
1822
|
-
[translations.Device[this.config.userSelectedLanguage]]: '--none--',
|
|
1823
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '',
|
|
1824
|
-
[translations.Battery[this.config.userSelectedLanguage]]: '',
|
|
1825
|
-
},
|
|
1826
|
-
];
|
|
1827
|
-
}
|
|
1828
|
-
//write JSON list
|
|
1829
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryList`, {
|
|
1830
|
-
val: JSON.stringify(this.batteryLowPowered),
|
|
1831
|
-
ack: true,
|
|
1832
|
-
});
|
|
1833
|
-
|
|
1834
|
-
// set booleans datapoints
|
|
1835
|
-
if (this.offlineDevicesCount === 0) {
|
|
1836
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
|
|
1837
|
-
val: false,
|
|
1838
|
-
ack: true,
|
|
1839
|
-
});
|
|
1840
|
-
} else {
|
|
1841
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceOffline`, {
|
|
1842
|
-
val: true,
|
|
1843
|
-
ack: true,
|
|
1844
|
-
});
|
|
1845
|
-
}
|
|
1846
|
-
|
|
1847
|
-
if (this.lowBatteryPoweredCount === 0) {
|
|
1848
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
|
|
1849
|
-
val: false,
|
|
1850
|
-
ack: true,
|
|
1851
|
-
});
|
|
1852
|
-
} else {
|
|
1853
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceLowBat`, {
|
|
1854
|
-
val: true,
|
|
1855
|
-
ack: true,
|
|
1856
|
-
});
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
if (this.upgradableDevicesCount === 0) {
|
|
1860
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
|
|
1861
|
-
val: false,
|
|
1862
|
-
ack: true,
|
|
1863
|
-
});
|
|
1864
|
-
} else {
|
|
1865
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}oneDeviceUpdatable`, {
|
|
1866
|
-
val: true,
|
|
1867
|
-
ack: true,
|
|
1868
|
-
});
|
|
1869
|
-
}
|
|
1870
|
-
|
|
1871
|
-
//write HTML list
|
|
1872
|
-
if (this.configCreateHtmlList) {
|
|
1873
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
|
|
1874
|
-
val: await this.createListHTML('linkQualityList', this.linkQualityDevices, this.linkQualityCount, null),
|
|
1875
|
-
ack: true,
|
|
1876
|
-
});
|
|
1877
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}offlineListHTML`, {
|
|
1878
|
-
val: await this.createListHTML('offlineList', this.offlineDevices, this.offlineDevicesCount, null),
|
|
1879
|
-
ack: true,
|
|
1880
|
-
});
|
|
1881
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}batteryListHTML`, {
|
|
1882
|
-
val: await this.createListHTML('batteryList', this.batteryPowered, this.batteryPoweredCount, false),
|
|
1883
|
-
ack: true,
|
|
1884
|
-
});
|
|
1885
|
-
await this.setStateChangedAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
|
|
1886
|
-
val: await this.createListHTML('batteryList', this.batteryLowPowered, this.lowBatteryPoweredCount, true),
|
|
1887
|
-
ack: true,
|
|
1888
|
-
});
|
|
1889
|
-
if (this.config.checkAdapterInstances) {
|
|
1890
|
-
await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
|
|
1891
|
-
val: await this.createListHTMLInstances('allInstancesList', this.listAllInstances, this.countAllInstances),
|
|
1892
|
-
ack: true,
|
|
1893
|
-
});
|
|
1894
|
-
await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
|
|
1895
|
-
val: await this.createListHTMLInstances('allActiveInstancesList', this.listAllActiveInstances, this.countAllActiveInstances),
|
|
1896
|
-
ack: true,
|
|
1897
|
-
});
|
|
1898
|
-
await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
|
|
1899
|
-
val: await this.createListHTMLInstances('errorInstanceList', this.listErrorInstance, this.countErrorInstance),
|
|
1900
|
-
ack: true,
|
|
1901
|
-
});
|
|
1902
|
-
await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
|
|
1903
|
-
val: await this.createListHTMLInstances('deactivatedInstanceList', this.listDeactivatedInstances, this.countDeactivatedInstances),
|
|
1904
|
-
ack: true,
|
|
1905
|
-
});
|
|
1906
|
-
await this.setStateChangedAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
|
|
1907
|
-
val: await this.createListHTMLInstances('updateAdapterList', this.listAdapterUpdates, this.countAdapterUpdates),
|
|
1908
|
-
ack: true,
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
|
|
1913
|
-
// create timestamp of last run
|
|
1914
|
-
const lastCheck = this.formatDate(new Date(), 'DD.MM.YYYY') + ' - ' + this.formatDate(new Date(), 'hh:mm:ss');
|
|
1915
|
-
await this.setStateChangedAsync('lastCheck', lastCheck, true);
|
|
1916
|
-
} catch (error) {
|
|
1917
|
-
this.log.error(`[writeDatapoints] - ${error}`);
|
|
1918
|
-
}
|
|
1919
|
-
this.log.debug(`Function finished: ${this.writeDatapoints.name}`);
|
|
1920
|
-
} //<--End of writing Datapoints
|
|
1921
|
-
|
|
1922
|
-
/**
|
|
1923
|
-
* @param {string | string[]} id
|
|
1924
|
-
* @param {ioBroker.State} state
|
|
1235
|
+
* @param {string | string[]} id
|
|
1236
|
+
* @param {ioBroker.State} state
|
|
1925
1237
|
*/
|
|
1926
1238
|
async renewDeviceData(id, state) {
|
|
1927
1239
|
let batteryData;
|
|
@@ -1974,7 +1286,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
1974
1286
|
deviceData.BatteryRaw = batteryData[2];
|
|
1975
1287
|
deviceData.BatteryUnitRaw = batteryData[3];
|
|
1976
1288
|
if (deviceData.LowBatDP !== 'none') {
|
|
1977
|
-
isLowBatValue = await
|
|
1289
|
+
isLowBatValue = await tools.getInitValue(this,deviceData.LowBatDP);
|
|
1978
1290
|
} else {
|
|
1979
1291
|
isLowBatValue = undefined;
|
|
1980
1292
|
}
|
|
@@ -2037,17 +1349,17 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2037
1349
|
deviceData.UnreachDP,
|
|
2038
1350
|
deviceData.SignalStrength,
|
|
2039
1351
|
deviceData.UnreachState,
|
|
2040
|
-
deviceData.
|
|
2041
|
-
deviceData.
|
|
1352
|
+
deviceData.deviceStateSelectorHMRPC,
|
|
1353
|
+
deviceData.rssiPeerSelectorHMRPC,
|
|
2042
1354
|
);
|
|
2043
|
-
if (contactData !== undefined) {
|
|
1355
|
+
if (contactData !== undefined && contactData !== null) {
|
|
2044
1356
|
deviceData.LastContact = contactData[0];
|
|
2045
1357
|
deviceData.Status = contactData[1];
|
|
2046
1358
|
deviceData.SignalStrength = contactData[2];
|
|
2047
1359
|
}
|
|
2048
1360
|
if (this.config.checkSendOfflineMsg && oldStatus !== deviceData.Status && !this.blacklistNotify.includes(deviceData.Path)) {
|
|
2049
1361
|
// check if the generally deviceData connected state is for a while true
|
|
2050
|
-
if (await
|
|
1362
|
+
if (await tools.getTimestampConnectionDP(this, deviceData.instanceDeviceConnectionDP, 50000)) {
|
|
2051
1363
|
await this.sendStateNotifications('Devices', 'onlineStateDevice', deviceID);
|
|
2052
1364
|
}
|
|
2053
1365
|
}
|
|
@@ -2078,6 +1390,9 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2078
1390
|
try {
|
|
2079
1391
|
const instanceAliveDP = await this.getForeignStatesAsync(`${instanceObject}.alive`);
|
|
2080
1392
|
|
|
1393
|
+
this.adapterUpdatesJsonRaw = await this.getAdapterUpdateData(adapterUpdateListDP);
|
|
1394
|
+
|
|
1395
|
+
|
|
2081
1396
|
for (const [id] of Object.entries(instanceAliveDP)) {
|
|
2082
1397
|
if (!(typeof id === 'string' && id.startsWith(`system.adapter.`))) continue;
|
|
2083
1398
|
|
|
@@ -2086,13 +1401,13 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2086
1401
|
|
|
2087
1402
|
// get instance connected to host data
|
|
2088
1403
|
const instanceConnectedHostDP = `system.adapter.${instanceID}.connected`;
|
|
2089
|
-
const instanceConnectedHostVal = await
|
|
1404
|
+
const instanceConnectedHostVal = await tools.getInitValue(this,instanceConnectedHostDP);
|
|
2090
1405
|
|
|
2091
1406
|
// get instance connected to device data
|
|
2092
1407
|
const instanceConnectedDeviceDP = `${instanceID}.info.connection`;
|
|
2093
1408
|
let instanceConnectedDeviceVal;
|
|
2094
1409
|
if (instanceConnectedDeviceDP !== undefined && typeof instanceConnectedDeviceDP === 'boolean') {
|
|
2095
|
-
instanceConnectedDeviceVal = await
|
|
1410
|
+
instanceConnectedDeviceVal = await tools.getInitValue(this,instanceConnectedDeviceDP);
|
|
2096
1411
|
} else {
|
|
2097
1412
|
instanceConnectedDeviceVal = 'N/A';
|
|
2098
1413
|
}
|
|
@@ -2107,7 +1422,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2107
1422
|
const instanceObjectData = await this.getForeignObjectAsync(instanceObjectPath);
|
|
2108
1423
|
if (instanceObjectData) {
|
|
2109
1424
|
// @ts-ignore
|
|
2110
|
-
adapterName =
|
|
1425
|
+
adapterName = tools.capitalize(instanceObjectData.common.name);
|
|
2111
1426
|
adapterVersion = instanceObjectData.common.version;
|
|
2112
1427
|
instanceMode = instanceObjectData.common.mode;
|
|
2113
1428
|
|
|
@@ -2116,12 +1431,13 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2116
1431
|
}
|
|
2117
1432
|
}
|
|
2118
1433
|
|
|
2119
|
-
await this.getAdapterUpdateData(`admin.*.info.updatesJson`);
|
|
2120
1434
|
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
1435
|
+
const updateEntry = this.adapterUpdatesJsonRaw.find(
|
|
1436
|
+
entry => entry.adapter.toLowerCase() === adapterName.toLowerCase()
|
|
1437
|
+
);
|
|
1438
|
+
|
|
1439
|
+
if (updateEntry) {
|
|
1440
|
+
adapterAvailableUpdate = updateEntry.newVersion;
|
|
2125
1441
|
} else {
|
|
2126
1442
|
adapterAvailableUpdate = ' - ';
|
|
2127
1443
|
}
|
|
@@ -2190,9 +1506,9 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2190
1506
|
* @param {string} instanceID
|
|
2191
1507
|
*/
|
|
2192
1508
|
async checkDaemonIsHealthy(instanceID) {
|
|
2193
|
-
const connectedHostState = await
|
|
2194
|
-
const isAlive = await
|
|
2195
|
-
let connectedDeviceState = await
|
|
1509
|
+
const connectedHostState = await tools.getInitValue(this,`system.adapter.${instanceID}.connected`);
|
|
1510
|
+
const isAlive = await tools.getInitValue(this,`system.adapter.${instanceID}.alive`);
|
|
1511
|
+
let connectedDeviceState = await tools.getInitValue(this,`${instanceID}.info.connection`);
|
|
2196
1512
|
if (connectedDeviceState === undefined) {
|
|
2197
1513
|
connectedDeviceState = true;
|
|
2198
1514
|
}
|
|
@@ -2220,7 +1536,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2220
1536
|
* @param {number} instanceDeactivationTime
|
|
2221
1537
|
*/
|
|
2222
1538
|
async checkDaemonIsAlive(instanceID, instanceDeactivationTime) {
|
|
2223
|
-
let isAlive = await
|
|
1539
|
+
let isAlive = await tools.getInitValue(this,`system.adapter.${instanceID}.alive`);
|
|
2224
1540
|
let daemonIsAlive;
|
|
2225
1541
|
let isHealthy = false;
|
|
2226
1542
|
let instanceStatusString = isAlive ? translations.instance_activated[this.config.userSelectedLanguage] : translations.instance_deactivated[this.config.userSelectedLanguage];
|
|
@@ -2257,7 +1573,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2257
1573
|
|
|
2258
1574
|
if (isAliveSchedule) {
|
|
2259
1575
|
lastUpdate = Math.round((Date.now() - isAliveSchedule.lc) / 1000); // Last state change in seconds
|
|
2260
|
-
previousCronRun =
|
|
1576
|
+
previousCronRun = tools.getPreviousCronRun(this, scheduleTime); // When was the last cron run
|
|
2261
1577
|
if (previousCronRun) {
|
|
2262
1578
|
lastCronRun = Math.round(previousCronRun / 1000); // change distance to last run in seconds
|
|
2263
1579
|
diff = lastCronRun - lastUpdate;
|
|
@@ -2337,26 +1653,13 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2337
1653
|
return [isAlive, isHealthy, instanceStatusString, connectedToHost, connectedToDevice];
|
|
2338
1654
|
}
|
|
2339
1655
|
|
|
2340
|
-
/**
|
|
2341
|
-
* create adapter update data
|
|
2342
|
-
*/
|
|
2343
|
-
async createAdapterUpdateData() {
|
|
2344
|
-
const adapterUpdateListDP = 'admin.*.info.updatesJson';
|
|
2345
|
-
// subscribe to datapoint
|
|
2346
|
-
this.subscribeForeignStates(adapterUpdateListDP);
|
|
2347
|
-
|
|
2348
|
-
await this.getAdapterUpdateData(adapterUpdateListDP);
|
|
2349
|
-
|
|
2350
|
-
await this.createAdapterUpdateList();
|
|
2351
|
-
}
|
|
2352
|
-
|
|
2353
1656
|
/**
|
|
2354
1657
|
* create adapter update raw lists
|
|
2355
1658
|
* @param {string} adapterUpdateListDP
|
|
2356
1659
|
*/
|
|
2357
1660
|
async getAdapterUpdateData(adapterUpdateListDP) {
|
|
2358
1661
|
// Clear the existing adapter updates data
|
|
2359
|
-
|
|
1662
|
+
let adapterUpdatesJsonRaw = [];
|
|
2360
1663
|
|
|
2361
1664
|
// Fetch the adapter updates list
|
|
2362
1665
|
const adapterUpdatesListVal = await this.getForeignStatesAsync(adapterUpdateListDP);
|
|
@@ -2366,20 +1669,22 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2366
1669
|
|
|
2367
1670
|
// Extract adapter data from the list
|
|
2368
1671
|
for (const [id, value] of Object.entries(adapterUpdatesListVal)) {
|
|
2369
|
-
adapterJsonList =
|
|
1672
|
+
adapterJsonList = tools.parseData(value.val);
|
|
2370
1673
|
adapterUpdatesJsonPath = id;
|
|
2371
1674
|
}
|
|
2372
1675
|
|
|
2373
1676
|
// Populate the adapter updates data
|
|
2374
1677
|
for (const [id, adapterData] of Object.entries(adapterJsonList)) {
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
1678
|
+
adapterUpdatesJsonRaw.push(
|
|
1679
|
+
{
|
|
1680
|
+
adapter: tools.capitalize(id),
|
|
1681
|
+
newVersion: adapterData.availableVersion,
|
|
1682
|
+
oldVersion: adapterData.installedVersion,
|
|
1683
|
+
}
|
|
1684
|
+
);
|
|
2380
1685
|
}
|
|
2381
1686
|
|
|
2382
|
-
return
|
|
1687
|
+
return adapterUpdatesJsonRaw;
|
|
2383
1688
|
}
|
|
2384
1689
|
|
|
2385
1690
|
/**
|
|
@@ -2389,13 +1694,14 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2389
1694
|
this.listAdapterUpdates = [];
|
|
2390
1695
|
this.countAdapterUpdates = 0;
|
|
2391
1696
|
|
|
2392
|
-
for (const
|
|
1697
|
+
for (const updateData of this.adapterUpdatesJsonRaw) {
|
|
2393
1698
|
this.listAdapterUpdates.push({
|
|
2394
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: adapter,
|
|
1699
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: updateData.adapter,
|
|
2395
1700
|
[translations.Available_Version[this.config.userSelectedLanguage]]: updateData.newVersion,
|
|
2396
1701
|
[translations.Installed_Version[this.config.userSelectedLanguage]]: updateData.oldVersion,
|
|
2397
1702
|
});
|
|
2398
1703
|
}
|
|
1704
|
+
|
|
2399
1705
|
this.countAdapterUpdates = this.listAdapterUpdates.length;
|
|
2400
1706
|
await this.writeAdapterUpdatesDPs();
|
|
2401
1707
|
}
|
|
@@ -2410,7 +1716,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2410
1716
|
if (this.countAdapterUpdates === 0) {
|
|
2411
1717
|
this.listAdapterUpdates = [
|
|
2412
1718
|
{
|
|
2413
|
-
[translations.Adapter[this.config.userSelectedLanguage]]: '--
|
|
1719
|
+
[translations.Adapter[this.config.userSelectedLanguage]]: '--no updates--',
|
|
2414
1720
|
[translations.Available_Version[this.config.userSelectedLanguage]]: '',
|
|
2415
1721
|
[translations.Installed_Version[this.config.userSelectedLanguage]]: '',
|
|
2416
1722
|
},
|
|
@@ -2556,8 +1862,11 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2556
1862
|
|
|
2557
1863
|
// Update instances with available adapter updates
|
|
2558
1864
|
for (const instance of this.listInstanceRaw.values()) {
|
|
2559
|
-
|
|
2560
|
-
|
|
1865
|
+
const adapterUpdate = this.adapterUpdatesJsonRaw.find(
|
|
1866
|
+
entry => entry.adapter.toLowerCase() === instance.Adapter.toLowerCase()
|
|
1867
|
+
);
|
|
1868
|
+
|
|
1869
|
+
if (adapterUpdate) {
|
|
2561
1870
|
instance.updateAvailable = adapterUpdate.newVersion;
|
|
2562
1871
|
} else {
|
|
2563
1872
|
instance.updateAvailable = ' - ';
|
|
@@ -2622,294 +1931,6 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2622
1931
|
}
|
|
2623
1932
|
}
|
|
2624
1933
|
|
|
2625
|
-
/**
|
|
2626
|
-
* create Datapoints for Instances
|
|
2627
|
-
*/
|
|
2628
|
-
async createDPsForInstances() {
|
|
2629
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances`, {
|
|
2630
|
-
type: 'channel',
|
|
2631
|
-
common: {
|
|
2632
|
-
name: {
|
|
2633
|
-
en: 'Adapter and Instances',
|
|
2634
|
-
de: 'Adapter und Instanzen',
|
|
2635
|
-
ru: 'Адаптер и Instances',
|
|
2636
|
-
pt: 'Adaptador e instâncias',
|
|
2637
|
-
nl: 'Adapter en Instance',
|
|
2638
|
-
fr: 'Adaptateur et instances',
|
|
2639
|
-
it: 'Adattatore e istanze',
|
|
2640
|
-
es: 'Adaptador e instalaciones',
|
|
2641
|
-
pl: 'Adapter and Instances',
|
|
2642
|
-
// @ts-ignore
|
|
2643
|
-
uk: 'Адаптер та інстанції',
|
|
2644
|
-
'zh-cn': '道歉和案',
|
|
2645
|
-
},
|
|
2646
|
-
},
|
|
2647
|
-
native: {},
|
|
2648
|
-
});
|
|
2649
|
-
|
|
2650
|
-
// Instances
|
|
2651
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.listAllInstances`, {
|
|
2652
|
-
type: 'state',
|
|
2653
|
-
common: {
|
|
2654
|
-
name: {
|
|
2655
|
-
en: 'JSON List of all instances',
|
|
2656
|
-
de: 'JSON Liste aller Instanzen',
|
|
2657
|
-
ru: 'ДЖСОН Список всех инстанций',
|
|
2658
|
-
pt: 'J. Lista de todas as instâncias',
|
|
2659
|
-
nl: 'JSON List van alle instanties',
|
|
2660
|
-
fr: 'JSON Liste de tous les cas',
|
|
2661
|
-
it: 'JSON Elenco di tutte le istanze',
|
|
2662
|
-
es: 'JSON Lista de todos los casos',
|
|
2663
|
-
pl: 'JSON Lista wszystkich instancji',
|
|
2664
|
-
// @ts-ignore
|
|
2665
|
-
uk: 'Сонце Список всіх екземплярів',
|
|
2666
|
-
'zh-cn': '附 件 所有事例一览表',
|
|
2667
|
-
},
|
|
2668
|
-
type: 'array',
|
|
2669
|
-
role: 'json',
|
|
2670
|
-
read: true,
|
|
2671
|
-
write: false,
|
|
2672
|
-
},
|
|
2673
|
-
native: {},
|
|
2674
|
-
});
|
|
2675
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.countAllInstances`, {
|
|
2676
|
-
type: 'state',
|
|
2677
|
-
common: {
|
|
2678
|
-
name: {
|
|
2679
|
-
en: 'Number of all instances',
|
|
2680
|
-
de: 'Anzahl aller Instanzen',
|
|
2681
|
-
ru: 'Количество всех инстанций',
|
|
2682
|
-
pt: 'Número de todas as instâncias',
|
|
2683
|
-
nl: 'Nummer van alle gevallen',
|
|
2684
|
-
fr: 'Nombre de cas',
|
|
2685
|
-
it: 'Numero di tutte le istanze',
|
|
2686
|
-
es: 'Número de casos',
|
|
2687
|
-
pl: 'Liczba wszystkich instancji',
|
|
2688
|
-
// @ts-ignore
|
|
2689
|
-
uk: 'Кількість всіх екземплярів',
|
|
2690
|
-
'zh-cn': '各类案件数目',
|
|
2691
|
-
},
|
|
2692
|
-
type: 'number',
|
|
2693
|
-
role: 'value',
|
|
2694
|
-
read: true,
|
|
2695
|
-
write: false,
|
|
2696
|
-
},
|
|
2697
|
-
native: {},
|
|
2698
|
-
});
|
|
2699
|
-
// Instances
|
|
2700
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.listAllActiveInstances`, {
|
|
2701
|
-
type: 'state',
|
|
2702
|
-
common: {
|
|
2703
|
-
name: {
|
|
2704
|
-
en: 'JSON List of all active instances',
|
|
2705
|
-
de: 'JSON Liste aller aktiven Instanzen',
|
|
2706
|
-
ru: 'ДЖСОН Список всех активных инстанций',
|
|
2707
|
-
pt: 'J. Lista de todas as instâncias ativas',
|
|
2708
|
-
nl: 'JSON List van alle actieve instanties',
|
|
2709
|
-
fr: 'JSON Liste de tous les cas actifs',
|
|
2710
|
-
it: 'JSON Elenco di tutte le istanze attive',
|
|
2711
|
-
es: 'JSON Lista de todos los casos activos',
|
|
2712
|
-
pl: 'JSON Lista wszystkich aktywnych instancji',
|
|
2713
|
-
// @ts-ignore
|
|
2714
|
-
uk: 'Сонце Список всіх активних екземплярів',
|
|
2715
|
-
'zh-cn': '附 件 所有积极事件清单',
|
|
2716
|
-
},
|
|
2717
|
-
type: 'array',
|
|
2718
|
-
role: 'json',
|
|
2719
|
-
read: true,
|
|
2720
|
-
write: false,
|
|
2721
|
-
},
|
|
2722
|
-
native: {},
|
|
2723
|
-
});
|
|
2724
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.countAllActiveInstances`, {
|
|
2725
|
-
type: 'state',
|
|
2726
|
-
common: {
|
|
2727
|
-
name: {
|
|
2728
|
-
en: 'Number of all active instances',
|
|
2729
|
-
de: 'Anzahl aller aktiven Instanzen',
|
|
2730
|
-
ru: 'Количество всех активных инстанций',
|
|
2731
|
-
pt: 'Número de todas as instâncias ativas',
|
|
2732
|
-
nl: 'Nummer van alle actieve instanties',
|
|
2733
|
-
fr: 'Nombre de toutes les instances actives',
|
|
2734
|
-
it: 'Numero di tutte le istanze attive',
|
|
2735
|
-
es: 'Número de casos activos',
|
|
2736
|
-
pl: 'Liczba wszystkich czynnych przypadków',
|
|
2737
|
-
// @ts-ignore
|
|
2738
|
-
uk: 'Кількість всіх активних екземплярів',
|
|
2739
|
-
'zh-cn': '所有积极事件的数目',
|
|
2740
|
-
},
|
|
2741
|
-
type: 'number',
|
|
2742
|
-
role: 'value',
|
|
2743
|
-
read: true,
|
|
2744
|
-
write: false,
|
|
2745
|
-
},
|
|
2746
|
-
native: {},
|
|
2747
|
-
});
|
|
2748
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.listDeactivatedInstances`, {
|
|
2749
|
-
type: 'state',
|
|
2750
|
-
common: {
|
|
2751
|
-
name: {
|
|
2752
|
-
en: 'JSON List of deactivated instances',
|
|
2753
|
-
de: 'JSON Liste der deaktivierten Instanzen',
|
|
2754
|
-
ru: 'ДЖСОН Список деактивированных инстанций',
|
|
2755
|
-
pt: 'J. Lista de instâncias desativadas',
|
|
2756
|
-
nl: 'JSON List van gedeactiveerde instanties',
|
|
2757
|
-
fr: 'JSON Liste des cas désactivés',
|
|
2758
|
-
it: 'JSON Elenco delle istanze disattivate',
|
|
2759
|
-
es: 'JSON Lista de casos desactivados',
|
|
2760
|
-
pl: 'JSON Lista przypadków deaktywowanych',
|
|
2761
|
-
// @ts-ignore
|
|
2762
|
-
uk: 'Сонце Перелік деактивованих екземплярів',
|
|
2763
|
-
'zh-cn': '附 件 被动事例清单',
|
|
2764
|
-
},
|
|
2765
|
-
type: 'array',
|
|
2766
|
-
role: 'json',
|
|
2767
|
-
read: true,
|
|
2768
|
-
write: false,
|
|
2769
|
-
},
|
|
2770
|
-
native: {},
|
|
2771
|
-
});
|
|
2772
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.countDeactivatedInstances`, {
|
|
2773
|
-
type: 'state',
|
|
2774
|
-
common: {
|
|
2775
|
-
name: {
|
|
2776
|
-
en: 'Number of deactivated instances',
|
|
2777
|
-
de: 'Anzahl deaktivierter Instanzen',
|
|
2778
|
-
ru: 'Количество деактивированных инстанций',
|
|
2779
|
-
pt: 'Número de instâncias desativadas',
|
|
2780
|
-
nl: 'Nummer van gedeactiveerde instanties',
|
|
2781
|
-
fr: 'Nombre de cas désactivés',
|
|
2782
|
-
it: 'Numero di istanze disattivate',
|
|
2783
|
-
es: 'Número de casos desactivados',
|
|
2784
|
-
pl: 'Liczba deaktywowanych instancji',
|
|
2785
|
-
// @ts-ignore
|
|
2786
|
-
uk: 'Кількість деактивованих екземплярів',
|
|
2787
|
-
'zh-cn': 'A. 递解事件的数目',
|
|
2788
|
-
},
|
|
2789
|
-
type: 'number',
|
|
2790
|
-
role: 'value',
|
|
2791
|
-
read: true,
|
|
2792
|
-
write: false,
|
|
2793
|
-
},
|
|
2794
|
-
native: {},
|
|
2795
|
-
});
|
|
2796
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.listInstancesError`, {
|
|
2797
|
-
type: 'state',
|
|
2798
|
-
common: {
|
|
2799
|
-
name: {
|
|
2800
|
-
en: 'JSON list of instances with error',
|
|
2801
|
-
de: 'JSON-Liste von Instanzen mit Fehler',
|
|
2802
|
-
ru: 'JSON список инстанций с ошибкой',
|
|
2803
|
-
pt: 'Lista de instâncias JSON com erro',
|
|
2804
|
-
nl: 'JSON lijst met fouten',
|
|
2805
|
-
fr: 'Liste des instances avec erreur',
|
|
2806
|
-
it: 'Elenco JSON delle istanze con errore',
|
|
2807
|
-
es: 'JSON lista de casos con error',
|
|
2808
|
-
pl: 'Lista błędów JSON',
|
|
2809
|
-
// @ts-ignore
|
|
2810
|
-
uk: 'JSON список екземплярів з помилкою',
|
|
2811
|
-
'zh-cn': '联合工作组办公室错误事件清单',
|
|
2812
|
-
},
|
|
2813
|
-
type: 'array',
|
|
2814
|
-
role: 'json',
|
|
2815
|
-
read: true,
|
|
2816
|
-
write: false,
|
|
2817
|
-
},
|
|
2818
|
-
native: {},
|
|
2819
|
-
});
|
|
2820
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.countInstancesError`, {
|
|
2821
|
-
type: 'state',
|
|
2822
|
-
common: {
|
|
2823
|
-
name: {
|
|
2824
|
-
en: 'Count of instances with error',
|
|
2825
|
-
de: 'Anzahl der Instanzen mit Fehler',
|
|
2826
|
-
ru: 'Количество инстанций с ошибкой',
|
|
2827
|
-
pt: 'Contagem de instâncias com erro',
|
|
2828
|
-
nl: 'Graaf van instoringen met fouten',
|
|
2829
|
-
fr: 'Nombre de cas avec erreur',
|
|
2830
|
-
it: 'Conteggio di istanze con errore',
|
|
2831
|
-
es: 'Cuenta de casos con error',
|
|
2832
|
-
pl: 'Liczba przykładów w przypadku błędów',
|
|
2833
|
-
// @ts-ignore
|
|
2834
|
-
uk: 'Кількість екземплярів з помилкою',
|
|
2835
|
-
'zh-cn': '发生错误的情况',
|
|
2836
|
-
},
|
|
2837
|
-
type: 'number',
|
|
2838
|
-
role: 'value',
|
|
2839
|
-
read: true,
|
|
2840
|
-
write: false,
|
|
2841
|
-
},
|
|
2842
|
-
native: {},
|
|
2843
|
-
});
|
|
2844
|
-
|
|
2845
|
-
// Adapter
|
|
2846
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.listAdapterUpdates`, {
|
|
2847
|
-
type: 'state',
|
|
2848
|
-
common: {
|
|
2849
|
-
name: {
|
|
2850
|
-
en: 'JSON list of adapters with available updates',
|
|
2851
|
-
de: 'JSON-Liste der Adapter mit verfügbaren Updates',
|
|
2852
|
-
ru: 'JSON список адаптеров с доступными обновлениями',
|
|
2853
|
-
pt: 'Lista de adaptadores JSON com atualizações disponíveis',
|
|
2854
|
-
nl: 'JSON lijst met beschikbare updates',
|
|
2855
|
-
fr: 'Liste JSON des adaptateurs avec mises à jour disponibles',
|
|
2856
|
-
it: 'Elenco di adattatori JSON con aggiornamenti disponibili',
|
|
2857
|
-
es: 'JSON lista de adaptadores con actualizaciones disponibles',
|
|
2858
|
-
pl: 'JSON lista adapterów z dostępnymi aktualizacjami',
|
|
2859
|
-
// @ts-ignore
|
|
2860
|
-
uk: 'JSON список адаптерів з доступними оновленнями',
|
|
2861
|
-
'zh-cn': '附录A',
|
|
2862
|
-
},
|
|
2863
|
-
type: 'array',
|
|
2864
|
-
role: 'json',
|
|
2865
|
-
read: true,
|
|
2866
|
-
write: false,
|
|
2867
|
-
},
|
|
2868
|
-
native: {},
|
|
2869
|
-
});
|
|
2870
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.countAdapterUpdates`, {
|
|
2871
|
-
type: 'state',
|
|
2872
|
-
common: {
|
|
2873
|
-
name: {
|
|
2874
|
-
en: 'Number of adapters with available updates',
|
|
2875
|
-
de: 'Anzahl der Adapter mit verfügbaren Updates',
|
|
2876
|
-
ru: 'Количество адаптеров с доступными обновлениями',
|
|
2877
|
-
pt: 'Número de adaptadores com atualizações disponíveis',
|
|
2878
|
-
nl: 'Nummer van adapters met beschikbare updates',
|
|
2879
|
-
fr: "Nombre d'adaptateurs avec mises à jour disponibles",
|
|
2880
|
-
it: 'Numero di adattatori con aggiornamenti disponibili',
|
|
2881
|
-
es: 'Número de adaptadores con actualizaciones disponibles',
|
|
2882
|
-
pl: 'Liczba adapterów z dostępną aktualizacją',
|
|
2883
|
-
// @ts-ignore
|
|
2884
|
-
uk: 'Кількість адаптерів з доступними оновленнями',
|
|
2885
|
-
'zh-cn': '更新的适应者人数',
|
|
2886
|
-
},
|
|
2887
|
-
type: 'number',
|
|
2888
|
-
role: 'value',
|
|
2889
|
-
read: true,
|
|
2890
|
-
write: false,
|
|
2891
|
-
},
|
|
2892
|
-
native: {},
|
|
2893
|
-
});
|
|
2894
|
-
}
|
|
2895
|
-
|
|
2896
|
-
/**
|
|
2897
|
-
* delete Datapoints for Instances
|
|
2898
|
-
*/
|
|
2899
|
-
async deleteDPsForInstances() {
|
|
2900
|
-
await this.delObjectAsync(`adapterAndInstances`);
|
|
2901
|
-
await this.delObjectAsync(`adapterAndInstances.listAllInstances`);
|
|
2902
|
-
await this.delObjectAsync(`adapterAndInstances.countAllInstances`);
|
|
2903
|
-
await this.delObjectAsync(`adapterAndInstances.listAllActiveInstances`);
|
|
2904
|
-
await this.delObjectAsync(`adapterAndInstances.countAllActiveInstances`);
|
|
2905
|
-
await this.delObjectAsync(`adapterAndInstances.listDeactivatedInstances`);
|
|
2906
|
-
await this.delObjectAsync(`adapterAndInstances.countDeactivatedInstances`);
|
|
2907
|
-
await this.delObjectAsync(`adapterAndInstances.listInstancesError`);
|
|
2908
|
-
await this.delObjectAsync(`adapterAndInstances.countInstancesError`);
|
|
2909
|
-
await this.delObjectAsync(`adapterAndInstances.listAdapterUpdates`);
|
|
2910
|
-
await this.delObjectAsync(`adapterAndInstances.countAdapterUpdates`);
|
|
2911
|
-
}
|
|
2912
|
-
|
|
2913
1934
|
/*=============================================
|
|
2914
1935
|
= functions to send notifications =
|
|
2915
1936
|
=============================================*/
|
|
@@ -2923,7 +1944,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2923
1944
|
if (this.config.instancePushover) {
|
|
2924
1945
|
try {
|
|
2925
1946
|
//first check if instance is living
|
|
2926
|
-
const pushoverAliveState = await
|
|
1947
|
+
const pushoverAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instancePushover + '.alive');
|
|
2927
1948
|
|
|
2928
1949
|
if (!pushoverAliveState) {
|
|
2929
1950
|
this.log.warn('Pushover instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -2945,7 +1966,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2945
1966
|
if (this.config.instanceTelegram) {
|
|
2946
1967
|
try {
|
|
2947
1968
|
//first check if instance is living
|
|
2948
|
-
const telegramAliveState = await
|
|
1969
|
+
const telegramAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceTelegram + '.alive');
|
|
2949
1970
|
|
|
2950
1971
|
if (!telegramAliveState) {
|
|
2951
1972
|
this.log.warn('Telegram instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -2965,7 +1986,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2965
1986
|
if (this.config.instanceWhatsapp) {
|
|
2966
1987
|
try {
|
|
2967
1988
|
//first check if instance is living
|
|
2968
|
-
const whatsappAliveState = await
|
|
1989
|
+
const whatsappAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceWhatsapp + '.alive');
|
|
2969
1990
|
|
|
2970
1991
|
if (!whatsappAliveState) {
|
|
2971
1992
|
this.log.warn('Whatsapp instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -2984,7 +2005,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
2984
2005
|
if (this.config.instanceMatrix) {
|
|
2985
2006
|
try {
|
|
2986
2007
|
//first check if instance is living
|
|
2987
|
-
const matrixAliveState = await
|
|
2008
|
+
const matrixAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceMatrix + '.alive');
|
|
2988
2009
|
|
|
2989
2010
|
if (!matrixAliveState) {
|
|
2990
2011
|
this.log.warn('Matrix instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3003,7 +2024,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3003
2024
|
if (this.config.instanceSignal) {
|
|
3004
2025
|
try {
|
|
3005
2026
|
//first check if instance is living
|
|
3006
|
-
const signalAliveState = await
|
|
2027
|
+
const signalAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceSignal + '.alive');
|
|
3007
2028
|
|
|
3008
2029
|
if (!signalAliveState) {
|
|
3009
2030
|
this.log.warn('Signal instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3022,7 +2043,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3022
2043
|
if (this.config.instanceEmail) {
|
|
3023
2044
|
try {
|
|
3024
2045
|
//first check if instance is living
|
|
3025
|
-
const eMailAliveState = await
|
|
2046
|
+
const eMailAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceEmail + '.alive');
|
|
3026
2047
|
|
|
3027
2048
|
if (!eMailAliveState) {
|
|
3028
2049
|
this.log.warn('eMail instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3042,7 +2063,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3042
2063
|
if (this.config.instanceJarvis) {
|
|
3043
2064
|
try {
|
|
3044
2065
|
//first check if instance is living
|
|
3045
|
-
const jarvisAliveState = await
|
|
2066
|
+
const jarvisAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceJarvis + '.alive');
|
|
3046
2067
|
|
|
3047
2068
|
if (!jarvisAliveState) {
|
|
3048
2069
|
this.log.warn('Jarvis instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3062,7 +2083,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3062
2083
|
if (this.config.instanceLovelace) {
|
|
3063
2084
|
try {
|
|
3064
2085
|
//first check if instance is living
|
|
3065
|
-
const lovelaceAliveState = await
|
|
2086
|
+
const lovelaceAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceLovelace + '.alive');
|
|
3066
2087
|
|
|
3067
2088
|
if (!lovelaceAliveState) {
|
|
3068
2089
|
this.log.warn('Lovelace instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3082,7 +2103,7 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3082
2103
|
if (this.config.instanceSynochat) {
|
|
3083
2104
|
try {
|
|
3084
2105
|
//first check if instance is living
|
|
3085
|
-
const synochatAliveState = await
|
|
2106
|
+
const synochatAliveState = await tools.getInitValue(this,'system.adapter.' + this.config.instanceSynochat + '.alive');
|
|
3086
2107
|
|
|
3087
2108
|
if (!synochatAliveState) {
|
|
3088
2109
|
this.log.warn('Synochat instance is not running. Message could not be sent. Please check your instance configuration.');
|
|
@@ -3327,1053 +2348,6 @@ class DeviceWatcher extends utils.Adapter {
|
|
|
3327
2348
|
}
|
|
3328
2349
|
}
|
|
3329
2350
|
|
|
3330
|
-
/*=============================================
|
|
3331
|
-
= functions to create html lists =
|
|
3332
|
-
=============================================*/
|
|
3333
|
-
/**
|
|
3334
|
-
* @param {string} type - type of list
|
|
3335
|
-
* @param {object} devices - Device
|
|
3336
|
-
* @param {number} deviceCount - Counted devices
|
|
3337
|
-
* @param {object} isLowBatteryList - list Low Battery Devices
|
|
3338
|
-
*/
|
|
3339
|
-
async createListHTML(type, devices, deviceCount, isLowBatteryList) {
|
|
3340
|
-
let html;
|
|
3341
|
-
switch (type) {
|
|
3342
|
-
case 'linkQualityList':
|
|
3343
|
-
devices = devices.sort((a, b) => {
|
|
3344
|
-
a = a.Device || '';
|
|
3345
|
-
b = b.Device || '';
|
|
3346
|
-
return a.localeCompare(b);
|
|
3347
|
-
});
|
|
3348
|
-
html = `<center>
|
|
3349
|
-
<b>${[translations.Link_quality_devices[this.config.userSelectedLanguage]]}:<font> ${deviceCount}</b><small></small></font>
|
|
3350
|
-
<p></p>
|
|
3351
|
-
</center>
|
|
3352
|
-
<table width=100%>
|
|
3353
|
-
<tr>
|
|
3354
|
-
<th align=left>${[translations.Device[this.config.userSelectedLanguage]]}</th>
|
|
3355
|
-
<th align=center width=120>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3356
|
-
<th align=right>${[translations.Signal_strength[this.config.userSelectedLanguage]]}</th>
|
|
3357
|
-
</tr>
|
|
3358
|
-
<tr>
|
|
3359
|
-
<td colspan="5"><hr></td>
|
|
3360
|
-
</tr>`;
|
|
3361
|
-
|
|
3362
|
-
for (const device of devices) {
|
|
3363
|
-
html += `<tr>
|
|
3364
|
-
<td><font>${device[translations.Device[this.config.userSelectedLanguage]]}</font></td>
|
|
3365
|
-
<td align=center><font>${device[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3366
|
-
<td align=right><font>${device[translations.Signal_strength[this.config.userSelectedLanguage]]}</font></td>
|
|
3367
|
-
</tr>`;
|
|
3368
|
-
}
|
|
3369
|
-
|
|
3370
|
-
html += '</table>';
|
|
3371
|
-
break;
|
|
3372
|
-
|
|
3373
|
-
case 'offlineList':
|
|
3374
|
-
devices = devices.sort((a, b) => {
|
|
3375
|
-
a = a.Device || '';
|
|
3376
|
-
b = b.Device || '';
|
|
3377
|
-
return a.localeCompare(b);
|
|
3378
|
-
});
|
|
3379
|
-
html = `<center>
|
|
3380
|
-
<b>${[translations.offline_devices[this.config.userSelectedLanguage]]}: <font color=${deviceCount === 0 ? '#3bcf0e' : 'orange'}>${deviceCount}</b><small></small></font>
|
|
3381
|
-
<p></p>
|
|
3382
|
-
</center>
|
|
3383
|
-
<table width=100%>
|
|
3384
|
-
<tr>
|
|
3385
|
-
<th align=left>${[translations.Device[this.config.userSelectedLanguage]]}</th>
|
|
3386
|
-
<th align=center width=120>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3387
|
-
<th align=center>${[translations.Last_Contact[this.config.userSelectedLanguage]]}</th>
|
|
3388
|
-
</tr>
|
|
3389
|
-
<tr>
|
|
3390
|
-
<td colspan="5"><hr></td>
|
|
3391
|
-
</tr>`;
|
|
3392
|
-
|
|
3393
|
-
for (const device of devices) {
|
|
3394
|
-
html += `<tr>
|
|
3395
|
-
<td><font>${device[translations.Device[this.config.userSelectedLanguage]]}</font></td>
|
|
3396
|
-
<td align=center><font>${device[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3397
|
-
<td align=center><font color=orange>${device[translations.Last_Contact[this.config.userSelectedLanguage]]}</font></td>
|
|
3398
|
-
</tr>`;
|
|
3399
|
-
}
|
|
3400
|
-
|
|
3401
|
-
html += '</table>';
|
|
3402
|
-
break;
|
|
3403
|
-
|
|
3404
|
-
case 'batteryList':
|
|
3405
|
-
devices = devices.sort((a, b) => {
|
|
3406
|
-
a = a.Device || '';
|
|
3407
|
-
b = b.Device || '';
|
|
3408
|
-
return a.localeCompare(b);
|
|
3409
|
-
});
|
|
3410
|
-
html = `<center>
|
|
3411
|
-
<b>${isLowBatteryList === true ? `${[translations.low[this.config.userSelectedLanguage]]} ` : ''}${[translations.battery_devices[this.config.userSelectedLanguage]]}:
|
|
3412
|
-
<font color=${isLowBatteryList === true ? (deviceCount > 0 ? 'orange' : '#3bcf0e') : ''}>${deviceCount}</b></font>
|
|
3413
|
-
<p></p>
|
|
3414
|
-
</center>
|
|
3415
|
-
<table width=100%>
|
|
3416
|
-
<tr>
|
|
3417
|
-
<th align=left>${[translations.Device[this.config.userSelectedLanguage]]}</th>
|
|
3418
|
-
<th align=center width=120>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3419
|
-
<th align=${isLowBatteryList ? 'center' : 'right'}>${[translations.Battery[this.config.userSelectedLanguage]]}</th>
|
|
3420
|
-
</tr>
|
|
3421
|
-
<tr>
|
|
3422
|
-
<td colspan="5"><hr></td>
|
|
3423
|
-
</tr>`;
|
|
3424
|
-
for (const device of devices) {
|
|
3425
|
-
html += `<tr>
|
|
3426
|
-
<td><font>${device[translations.Device[this.config.userSelectedLanguage]]}</font></td>
|
|
3427
|
-
<td align=center><font>${device[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>`;
|
|
3428
|
-
|
|
3429
|
-
if (isLowBatteryList) {
|
|
3430
|
-
html += `<td align=center><font color=orange>${device[translations.Battery[this.config.userSelectedLanguage]]}</font></td>`;
|
|
3431
|
-
} else {
|
|
3432
|
-
html += `<td align=right><font color=#3bcf0e>${device[translations.Battery[this.config.userSelectedLanguage]]}</font></td>`;
|
|
3433
|
-
}
|
|
3434
|
-
html += `</tr>`;
|
|
3435
|
-
}
|
|
3436
|
-
|
|
3437
|
-
html += '</table>';
|
|
3438
|
-
break;
|
|
3439
|
-
}
|
|
3440
|
-
return html;
|
|
3441
|
-
}
|
|
3442
|
-
|
|
3443
|
-
/**
|
|
3444
|
-
* @param {string} type - type of list
|
|
3445
|
-
* @param {object} instances - Instance
|
|
3446
|
-
* @param {number} instancesCount - Counted devices
|
|
3447
|
-
*/
|
|
3448
|
-
async createListHTMLInstances(type, instances, instancesCount) {
|
|
3449
|
-
let html;
|
|
3450
|
-
switch (type) {
|
|
3451
|
-
case 'allInstancesList':
|
|
3452
|
-
instances = instances.sort((a, b) => {
|
|
3453
|
-
a = a.Instance || '';
|
|
3454
|
-
b = b.Instance || '';
|
|
3455
|
-
return a.localeCompare(b);
|
|
3456
|
-
});
|
|
3457
|
-
html = `<center>
|
|
3458
|
-
<b>${[translations.All_Instances[this.config.userSelectedLanguage]]}:<font> ${instancesCount}</b><small></small></font>
|
|
3459
|
-
<p></p>
|
|
3460
|
-
</center>
|
|
3461
|
-
<table width=100%>
|
|
3462
|
-
<tr>
|
|
3463
|
-
<th align=left>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3464
|
-
<th align=center>${[translations.Instance[this.config.userSelectedLanguage]]}</th>
|
|
3465
|
-
<th align=center width=180>${[translations.Status[this.config.userSelectedLanguage]]}</th>
|
|
3466
|
-
</tr>
|
|
3467
|
-
<tr>
|
|
3468
|
-
<td colspan="5"><hr></td>
|
|
3469
|
-
</tr>`;
|
|
3470
|
-
|
|
3471
|
-
for (const instanceData of instances) {
|
|
3472
|
-
html += `<tr>
|
|
3473
|
-
<td><font>${instanceData[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3474
|
-
<td align=center><font>${instanceData[translations.Instance[this.config.userSelectedLanguage]]}</font></td>
|
|
3475
|
-
<td align=center><font>${instanceData[translations.Status[this.config.userSelectedLanguage]]}</font></td>
|
|
3476
|
-
</tr>`;
|
|
3477
|
-
}
|
|
3478
|
-
|
|
3479
|
-
html += '</table>';
|
|
3480
|
-
break;
|
|
3481
|
-
|
|
3482
|
-
case 'allActiveInstancesList':
|
|
3483
|
-
instances = instances.sort((a, b) => {
|
|
3484
|
-
a = a.Instance || '';
|
|
3485
|
-
b = b.Instances || '';
|
|
3486
|
-
return a.localeCompare(b);
|
|
3487
|
-
});
|
|
3488
|
-
html = `<center>
|
|
3489
|
-
<b>${[translations.Active_Instances[this.config.userSelectedLanguage]]}: <font> ${instancesCount}</b><small></small></font>
|
|
3490
|
-
<p></p>
|
|
3491
|
-
</center>
|
|
3492
|
-
<table width=100%>
|
|
3493
|
-
<tr>
|
|
3494
|
-
<th align=left>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3495
|
-
<th align=center>${[translations.Instance[this.config.userSelectedLanguage]]}</th>
|
|
3496
|
-
<th align=center width=180>${[translations.Status[this.config.userSelectedLanguage]]}</th>
|
|
3497
|
-
</tr>
|
|
3498
|
-
<tr>
|
|
3499
|
-
<td colspan="5"><hr></td>
|
|
3500
|
-
</tr>`;
|
|
3501
|
-
|
|
3502
|
-
for (const instanceData of instances) {
|
|
3503
|
-
html += `<tr>
|
|
3504
|
-
<td><font>${instanceData[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3505
|
-
<td align=center><font>${instanceData[translations.Instance[this.config.userSelectedLanguage]]}</font></td>
|
|
3506
|
-
<td align=center><font color=orange>${instanceData[translations.Status[this.config.userSelectedLanguage]]}</font></td>
|
|
3507
|
-
</tr>`;
|
|
3508
|
-
}
|
|
3509
|
-
|
|
3510
|
-
html += '</table>';
|
|
3511
|
-
break;
|
|
3512
|
-
|
|
3513
|
-
case 'errorInstanceList':
|
|
3514
|
-
instances = instances.sort((a, b) => {
|
|
3515
|
-
a = a.Instance || '';
|
|
3516
|
-
b = b.Instances || '';
|
|
3517
|
-
return a.localeCompare(b);
|
|
3518
|
-
});
|
|
3519
|
-
html = `<center>
|
|
3520
|
-
<b>${[translations.Error_Instances[this.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
|
|
3521
|
-
<p></p>
|
|
3522
|
-
</center>
|
|
3523
|
-
<table width=100%>
|
|
3524
|
-
<tr>
|
|
3525
|
-
<th align=left>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3526
|
-
<th align=center>${[translations.Instance[this.config.userSelectedLanguage]]}</th>
|
|
3527
|
-
<th align=center width=180>${[translations.Status[this.config.userSelectedLanguage]]}</th>
|
|
3528
|
-
</tr>
|
|
3529
|
-
<tr>
|
|
3530
|
-
<td colspan="5"><hr></td>
|
|
3531
|
-
</tr>`;
|
|
3532
|
-
|
|
3533
|
-
for (const instanceData of instances) {
|
|
3534
|
-
html += `<tr>
|
|
3535
|
-
<td><font>${instanceData[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3536
|
-
<td align=center><font>${instanceData[translations.Instance[this.config.userSelectedLanguage]]}</font></td>
|
|
3537
|
-
<td align=center><font color=orange>${instanceData[translations.Status[this.config.userSelectedLanguage]]}</font></td>
|
|
3538
|
-
</tr>`;
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
html += '</table>';
|
|
3542
|
-
break;
|
|
3543
|
-
|
|
3544
|
-
case 'deactivatedInstanceList':
|
|
3545
|
-
instances = instances.sort((a, b) => {
|
|
3546
|
-
a = a.Instance || '';
|
|
3547
|
-
b = b.Instances || '';
|
|
3548
|
-
return a.localeCompare(b);
|
|
3549
|
-
});
|
|
3550
|
-
html = `<center>
|
|
3551
|
-
<b>${[translations.Deactivated_Instances[this.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
|
|
3552
|
-
<p></p>
|
|
3553
|
-
</center>
|
|
3554
|
-
<table width=100%>
|
|
3555
|
-
<tr>
|
|
3556
|
-
<th align=left>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3557
|
-
<th align=center>${[translations.Instance[this.config.userSelectedLanguage]]}</th>
|
|
3558
|
-
<th align=center width=180>${[translations.Status[this.config.userSelectedLanguage]]}</th>
|
|
3559
|
-
</tr>
|
|
3560
|
-
<tr>
|
|
3561
|
-
<td colspan="5"><hr></td>
|
|
3562
|
-
</tr>`;
|
|
3563
|
-
|
|
3564
|
-
for (const instanceData of instances) {
|
|
3565
|
-
if (!instanceData.isAlive) {
|
|
3566
|
-
html += `<tr>
|
|
3567
|
-
<td><font>${instanceData[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3568
|
-
<td align=center><font>${instanceData[translations.Instance[this.config.userSelectedLanguage]]}</font></td>
|
|
3569
|
-
<td align=center><font color=orange>${instanceData[translations.Status[this.config.userSelectedLanguage]]}</font></td>
|
|
3570
|
-
</tr>`;
|
|
3571
|
-
}
|
|
3572
|
-
}
|
|
3573
|
-
|
|
3574
|
-
html += '</table>';
|
|
3575
|
-
break;
|
|
3576
|
-
|
|
3577
|
-
case 'updateAdapterList':
|
|
3578
|
-
html = `<center>
|
|
3579
|
-
<b>${[translations.Updatable_adapters[this.config.userSelectedLanguage]]}: <font color=${instancesCount === 0 ? '#3bcf0e' : 'orange'}>${instancesCount}</b><small></small></font>
|
|
3580
|
-
<p></p>
|
|
3581
|
-
</center>
|
|
3582
|
-
<table width=100%>
|
|
3583
|
-
<tr>
|
|
3584
|
-
<th align=left>${[translations.Adapter[this.config.userSelectedLanguage]]}</th>
|
|
3585
|
-
<th align=center>${[translations.Installed_Version[this.config.userSelectedLanguage]]}</th>
|
|
3586
|
-
<th align=center>${[translations.Available_Version[this.config.userSelectedLanguage]]}</th>
|
|
3587
|
-
</tr>
|
|
3588
|
-
<tr>
|
|
3589
|
-
<td colspan="5"><hr></td>
|
|
3590
|
-
</tr>`;
|
|
3591
|
-
|
|
3592
|
-
for (const instanceData of instances.values()) {
|
|
3593
|
-
if (instanceData.updateAvailable !== ' - ') {
|
|
3594
|
-
html += `<tr>
|
|
3595
|
-
<td><font>${instanceData[translations.Adapter[this.config.userSelectedLanguage]]}</font></td>
|
|
3596
|
-
<td align=center><font>${instanceData[translations.Installed_Version[this.config.userSelectedLanguage]]}</font></td>
|
|
3597
|
-
<td align=center><font color=orange>${instanceData[translations.Available_Version[this.config.userSelectedLanguage]]}</font></td>
|
|
3598
|
-
</tr>`;
|
|
3599
|
-
}
|
|
3600
|
-
}
|
|
3601
|
-
|
|
3602
|
-
html += '</table>';
|
|
3603
|
-
break;
|
|
3604
|
-
}
|
|
3605
|
-
return html;
|
|
3606
|
-
}
|
|
3607
|
-
|
|
3608
|
-
/*=============================================
|
|
3609
|
-
= create datapoints for each adapter =
|
|
3610
|
-
=============================================*/
|
|
3611
|
-
|
|
3612
|
-
/**
|
|
3613
|
-
* @param {object} adptName - Adaptername of devices
|
|
3614
|
-
*/
|
|
3615
|
-
async createDPsForEachAdapter(adptName) {
|
|
3616
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}`, {
|
|
3617
|
-
type: 'channel',
|
|
3618
|
-
common: {
|
|
3619
|
-
name: adptName,
|
|
3620
|
-
},
|
|
3621
|
-
native: {},
|
|
3622
|
-
});
|
|
3623
|
-
|
|
3624
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.offlineCount`, {
|
|
3625
|
-
type: 'state',
|
|
3626
|
-
common: {
|
|
3627
|
-
name: {
|
|
3628
|
-
en: 'Number of devices offline',
|
|
3629
|
-
de: 'Anzahl der Geräte offline',
|
|
3630
|
-
ru: 'Количество устройств offline',
|
|
3631
|
-
pt: 'Número de dispositivos offline',
|
|
3632
|
-
nl: 'Nummer van apparatuur offline',
|
|
3633
|
-
fr: 'Nombre de dispositifs hors ligne',
|
|
3634
|
-
it: 'Numero di dispositivi offline',
|
|
3635
|
-
es: 'Número de dispositivos sin conexión',
|
|
3636
|
-
pl: 'Ilość urządzeń offline',
|
|
3637
|
-
'zh-cn': '线内装置数量',
|
|
3638
|
-
},
|
|
3639
|
-
type: 'number',
|
|
3640
|
-
role: 'value',
|
|
3641
|
-
read: true,
|
|
3642
|
-
write: false,
|
|
3643
|
-
},
|
|
3644
|
-
native: {},
|
|
3645
|
-
});
|
|
3646
|
-
|
|
3647
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.offlineList`, {
|
|
3648
|
-
type: 'state',
|
|
3649
|
-
common: {
|
|
3650
|
-
name: {
|
|
3651
|
-
en: 'List of offline devices',
|
|
3652
|
-
de: 'Liste der Offline-Geräte',
|
|
3653
|
-
ru: 'Список оффлайн устройств',
|
|
3654
|
-
pt: 'Lista de dispositivos off-line',
|
|
3655
|
-
nl: 'List van offline apparatuur',
|
|
3656
|
-
fr: 'Liste des dispositifs hors ligne',
|
|
3657
|
-
it: 'Elenco dei dispositivi offline',
|
|
3658
|
-
es: 'Lista de dispositivos sin conexión',
|
|
3659
|
-
pl: 'Lista urządzeń offline',
|
|
3660
|
-
'zh-cn': '线装置清单',
|
|
3661
|
-
},
|
|
3662
|
-
type: 'array',
|
|
3663
|
-
role: 'json',
|
|
3664
|
-
read: true,
|
|
3665
|
-
write: false,
|
|
3666
|
-
},
|
|
3667
|
-
native: {},
|
|
3668
|
-
});
|
|
3669
|
-
|
|
3670
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceOffline`, {
|
|
3671
|
-
type: 'state',
|
|
3672
|
-
common: {
|
|
3673
|
-
name: {
|
|
3674
|
-
en: 'Is one device with offline',
|
|
3675
|
-
de: 'Ist ein Gerät mit Offline',
|
|
3676
|
-
ru: 'Это одно устройство с offline',
|
|
3677
|
-
pt: 'É um dispositivo com offline',
|
|
3678
|
-
nl: 'Is een apparaat met offline',
|
|
3679
|
-
fr: 'Est un appareil avec hors ligne',
|
|
3680
|
-
it: 'È un dispositivo con offline',
|
|
3681
|
-
es: 'Es un dispositivo sin conexión',
|
|
3682
|
-
pl: 'Jest to jeden urządzenie z offlinem',
|
|
3683
|
-
// @ts-ignore
|
|
3684
|
-
uk: 'Є один пристрій з автономним',
|
|
3685
|
-
'zh-cn': '一处有线装置',
|
|
3686
|
-
},
|
|
3687
|
-
type: 'boolean',
|
|
3688
|
-
role: 'state',
|
|
3689
|
-
read: true,
|
|
3690
|
-
write: false,
|
|
3691
|
-
def: false,
|
|
3692
|
-
},
|
|
3693
|
-
native: {},
|
|
3694
|
-
});
|
|
3695
|
-
|
|
3696
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.listAllRawJSON`, {
|
|
3697
|
-
type: 'state',
|
|
3698
|
-
common: {
|
|
3699
|
-
name: {
|
|
3700
|
-
en: 'JSON RAW List of all devices',
|
|
3701
|
-
de: 'JSON RAW Liste aller Geräte',
|
|
3702
|
-
ru: 'ДЖСОН РАВ Список всех устройств',
|
|
3703
|
-
pt: 'JSON RAW Lista de todos os dispositivos',
|
|
3704
|
-
nl: 'JSON RAW List van alle apparaten',
|
|
3705
|
-
fr: 'JSON RAW Liste de tous les dispositifs',
|
|
3706
|
-
it: 'JSON RAW Elenco di tutti i dispositivi',
|
|
3707
|
-
es: 'JSON RAW Lista de todos los dispositivos',
|
|
3708
|
-
pl: 'JSON RAW Lista wszystkich urządzeń',
|
|
3709
|
-
// @ts-ignore
|
|
3710
|
-
uk: 'ДЖСОН РАВ Список всіх пристроїв',
|
|
3711
|
-
'zh-cn': 'JSONRAW 所有装置清单',
|
|
3712
|
-
},
|
|
3713
|
-
type: 'array',
|
|
3714
|
-
role: 'json',
|
|
3715
|
-
read: true,
|
|
3716
|
-
write: false,
|
|
3717
|
-
},
|
|
3718
|
-
native: {},
|
|
3719
|
-
});
|
|
3720
|
-
|
|
3721
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.listAll`, {
|
|
3722
|
-
type: 'state',
|
|
3723
|
-
common: {
|
|
3724
|
-
name: {
|
|
3725
|
-
en: 'List of all devices',
|
|
3726
|
-
de: 'Liste aller Geräte',
|
|
3727
|
-
ru: 'Список всех устройств',
|
|
3728
|
-
pt: 'Lista de todos os dispositivos',
|
|
3729
|
-
nl: 'List van alle apparaten',
|
|
3730
|
-
fr: 'Liste de tous les dispositifs',
|
|
3731
|
-
it: 'Elenco di tutti i dispositivi',
|
|
3732
|
-
es: 'Lista de todos los dispositivos',
|
|
3733
|
-
pl: 'Lista wszystkich urządzeń',
|
|
3734
|
-
'zh-cn': '所有装置清单',
|
|
3735
|
-
},
|
|
3736
|
-
type: 'array',
|
|
3737
|
-
role: 'json',
|
|
3738
|
-
read: true,
|
|
3739
|
-
write: false,
|
|
3740
|
-
},
|
|
3741
|
-
native: {},
|
|
3742
|
-
});
|
|
3743
|
-
|
|
3744
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.linkQualityList`, {
|
|
3745
|
-
type: 'state',
|
|
3746
|
-
common: {
|
|
3747
|
-
name: {
|
|
3748
|
-
en: 'List of devices with signal strength',
|
|
3749
|
-
de: 'Liste der Geräte mit Signalstärke',
|
|
3750
|
-
ru: 'Список устройств с силой сигнала',
|
|
3751
|
-
pt: 'Lista de dispositivos com força de sinal',
|
|
3752
|
-
nl: 'List van apparaten met signaalkracht',
|
|
3753
|
-
fr: 'Liste des dispositifs avec force de signal',
|
|
3754
|
-
it: 'Elenco dei dispositivi con forza del segnale',
|
|
3755
|
-
es: 'Lista de dispositivos con fuerza de señal',
|
|
3756
|
-
pl: 'Lista urządzeń z siłą sygnałową',
|
|
3757
|
-
'zh-cn': '具有信号实力的装置清单',
|
|
3758
|
-
},
|
|
3759
|
-
type: 'array',
|
|
3760
|
-
role: 'json',
|
|
3761
|
-
read: true,
|
|
3762
|
-
write: false,
|
|
3763
|
-
},
|
|
3764
|
-
native: {},
|
|
3765
|
-
});
|
|
3766
|
-
|
|
3767
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.countAll`, {
|
|
3768
|
-
type: 'state',
|
|
3769
|
-
common: {
|
|
3770
|
-
name: {
|
|
3771
|
-
en: 'Number of all devices',
|
|
3772
|
-
de: 'Anzahl aller Geräte',
|
|
3773
|
-
ru: 'Количество всех устройств',
|
|
3774
|
-
pt: 'Número de todos os dispositivos',
|
|
3775
|
-
nl: 'Nummer van alle apparaten',
|
|
3776
|
-
fr: 'Nombre de tous les appareils',
|
|
3777
|
-
it: 'Numero di tutti i dispositivi',
|
|
3778
|
-
es: 'Número de todos los dispositivos',
|
|
3779
|
-
pl: 'Ilość wszystkich urządzeń',
|
|
3780
|
-
'zh-cn': '所有装置的数目',
|
|
3781
|
-
},
|
|
3782
|
-
type: 'number',
|
|
3783
|
-
role: 'value',
|
|
3784
|
-
read: true,
|
|
3785
|
-
write: false,
|
|
3786
|
-
},
|
|
3787
|
-
native: {},
|
|
3788
|
-
});
|
|
3789
|
-
|
|
3790
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.batteryList`, {
|
|
3791
|
-
type: 'state',
|
|
3792
|
-
common: {
|
|
3793
|
-
name: {
|
|
3794
|
-
en: 'List of devices with battery state',
|
|
3795
|
-
de: 'Liste der Geräte mit Batteriezustand',
|
|
3796
|
-
ru: 'Список устройств с состоянием батареи',
|
|
3797
|
-
pt: 'Lista de dispositivos com estado da bateria',
|
|
3798
|
-
nl: 'List van apparaten met batterij staat',
|
|
3799
|
-
fr: 'Liste des appareils avec état de batterie',
|
|
3800
|
-
it: 'Elenco dei dispositivi con stato della batteria',
|
|
3801
|
-
es: 'Lista de dispositivos con estado de batería',
|
|
3802
|
-
pl: 'Lista urządzeń z baterią stanową',
|
|
3803
|
-
'zh-cn': '电池国装置清单',
|
|
3804
|
-
},
|
|
3805
|
-
type: 'array',
|
|
3806
|
-
role: 'json',
|
|
3807
|
-
read: true,
|
|
3808
|
-
write: false,
|
|
3809
|
-
},
|
|
3810
|
-
native: {},
|
|
3811
|
-
});
|
|
3812
|
-
|
|
3813
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryList`, {
|
|
3814
|
-
type: 'state',
|
|
3815
|
-
common: {
|
|
3816
|
-
name: {
|
|
3817
|
-
en: 'List of devices with low battery state',
|
|
3818
|
-
de: 'Liste der Geräte mit niedrigem Batteriezustand',
|
|
3819
|
-
ru: 'Список устройств с низким состоянием батареи',
|
|
3820
|
-
pt: 'Lista de dispositivos com baixo estado da bateria',
|
|
3821
|
-
nl: 'List van apparaten met lage batterij staat',
|
|
3822
|
-
fr: 'Liste des appareils à faible état de batterie',
|
|
3823
|
-
it: 'Elenco di dispositivi con stato di batteria basso',
|
|
3824
|
-
es: 'Lista de dispositivos con estado de batería bajo',
|
|
3825
|
-
pl: 'Lista urządzeń o niskim stanie baterii',
|
|
3826
|
-
'zh-cn': '低电池国家装置清单',
|
|
3827
|
-
},
|
|
3828
|
-
type: 'array',
|
|
3829
|
-
role: 'json',
|
|
3830
|
-
read: true,
|
|
3831
|
-
write: false,
|
|
3832
|
-
},
|
|
3833
|
-
native: {},
|
|
3834
|
-
});
|
|
3835
|
-
|
|
3836
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.lowBatteryCount`, {
|
|
3837
|
-
type: 'state',
|
|
3838
|
-
common: {
|
|
3839
|
-
name: {
|
|
3840
|
-
en: 'Number of devices with low battery',
|
|
3841
|
-
de: 'Anzahl der Geräte mit niedriger Batterie',
|
|
3842
|
-
ru: 'Количество устройств c низкой батареей',
|
|
3843
|
-
pt: 'Número de dispositivos com bateria baixa',
|
|
3844
|
-
nl: 'Nummer van apparaten met lage batterij',
|
|
3845
|
-
fr: 'Nombre de dispositifs avec batterie basse',
|
|
3846
|
-
it: 'Numero di dispositivi con batteria bassa',
|
|
3847
|
-
es: 'Número de dispositivos con batería baja',
|
|
3848
|
-
pl: 'Liczba urządzeń z niską baterią',
|
|
3849
|
-
'zh-cn': '低电池的装置数量',
|
|
3850
|
-
},
|
|
3851
|
-
type: 'number',
|
|
3852
|
-
role: 'value',
|
|
3853
|
-
read: true,
|
|
3854
|
-
write: false,
|
|
3855
|
-
},
|
|
3856
|
-
native: {},
|
|
3857
|
-
});
|
|
3858
|
-
|
|
3859
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceLowBat`, {
|
|
3860
|
-
type: 'state',
|
|
3861
|
-
common: {
|
|
3862
|
-
name: {
|
|
3863
|
-
en: 'Is one device with low battery',
|
|
3864
|
-
de: 'Ist ein Gerät mit niedrigem Akku',
|
|
3865
|
-
ru: 'Один прибор с низкой батареей',
|
|
3866
|
-
pt: 'É um dispositivo com bateria baixa',
|
|
3867
|
-
nl: 'Is een apparaat met lage batterijen',
|
|
3868
|
-
fr: 'Est un appareil avec batterie basse',
|
|
3869
|
-
it: 'È un dispositivo con batteria bassa',
|
|
3870
|
-
es: 'Es un dispositivo con batería baja',
|
|
3871
|
-
pl: 'Jest to jeden urządzenie z niską baterią',
|
|
3872
|
-
// @ts-ignore
|
|
3873
|
-
uk: 'Є одним пристроєм з низьких акумуляторів',
|
|
3874
|
-
'zh-cn': '低电池的装置',
|
|
3875
|
-
},
|
|
3876
|
-
type: 'boolean',
|
|
3877
|
-
role: 'state',
|
|
3878
|
-
read: true,
|
|
3879
|
-
write: false,
|
|
3880
|
-
def: false,
|
|
3881
|
-
},
|
|
3882
|
-
native: {},
|
|
3883
|
-
});
|
|
3884
|
-
|
|
3885
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.batteryCount`, {
|
|
3886
|
-
type: 'state',
|
|
3887
|
-
common: {
|
|
3888
|
-
name: {
|
|
3889
|
-
en: 'Number of devices with battery',
|
|
3890
|
-
de: 'Anzahl der Geräte mit Batterie',
|
|
3891
|
-
ru: 'Количество устройств c батареей',
|
|
3892
|
-
pt: 'Número de dispositivos com bateria',
|
|
3893
|
-
nl: 'Nummer van apparaten met batterij',
|
|
3894
|
-
fr: 'Nombre de dispositifs avec batterie',
|
|
3895
|
-
it: 'Numero di dispositivi con batteria',
|
|
3896
|
-
es: 'Número de dispositivos con batería',
|
|
3897
|
-
pl: 'Liczba urządzeń z baterią',
|
|
3898
|
-
'zh-cn': '电池的装置数量',
|
|
3899
|
-
},
|
|
3900
|
-
type: 'number',
|
|
3901
|
-
role: 'value',
|
|
3902
|
-
read: true,
|
|
3903
|
-
write: false,
|
|
3904
|
-
},
|
|
3905
|
-
native: {},
|
|
3906
|
-
});
|
|
3907
|
-
|
|
3908
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.upgradableCount`, {
|
|
3909
|
-
type: 'state',
|
|
3910
|
-
common: {
|
|
3911
|
-
name: {
|
|
3912
|
-
en: 'Number of devices with available updates ',
|
|
3913
|
-
de: 'Anzahl der Geräte mit verfügbaren Updates',
|
|
3914
|
-
ru: 'Количество устройств с доступными обновлениями',
|
|
3915
|
-
pt: 'Número de dispositivos com atualizações disponíveis',
|
|
3916
|
-
nl: 'Nummer van apparatuur met beschikbare updates',
|
|
3917
|
-
fr: 'Nombre de dispositifs avec mises à jour disponibles',
|
|
3918
|
-
it: 'Numero di dispositivi con aggiornamenti disponibili',
|
|
3919
|
-
es: 'Número de dispositivos con actualizaciones disponibles',
|
|
3920
|
-
pl: 'Liczba urządzeń z dostępną aktualizacją',
|
|
3921
|
-
// @ts-ignore
|
|
3922
|
-
uk: 'Кількість пристроїв з доступними оновленнями',
|
|
3923
|
-
'zh-cn': '现有更新的装置数目',
|
|
3924
|
-
},
|
|
3925
|
-
type: 'number',
|
|
3926
|
-
role: 'value',
|
|
3927
|
-
read: true,
|
|
3928
|
-
write: false,
|
|
3929
|
-
},
|
|
3930
|
-
native: {},
|
|
3931
|
-
});
|
|
3932
|
-
|
|
3933
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.upgradableList`, {
|
|
3934
|
-
type: 'state',
|
|
3935
|
-
common: {
|
|
3936
|
-
name: {
|
|
3937
|
-
en: 'JSON List of devices with available updates ',
|
|
3938
|
-
de: 'JSON Liste der Geräte mit verfügbaren Updates',
|
|
3939
|
-
ru: 'ДЖСОН Список устройств с доступными обновлениями',
|
|
3940
|
-
pt: 'J. Lista de dispositivos com atualizações disponíveis',
|
|
3941
|
-
nl: 'JSON List van apparatuur met beschikbare updates',
|
|
3942
|
-
fr: 'JSON Liste des appareils avec mises à jour disponibles',
|
|
3943
|
-
it: 'JSON Elenco dei dispositivi con aggiornamenti disponibili',
|
|
3944
|
-
es: 'JSON Lista de dispositivos con actualizaciones disponibles',
|
|
3945
|
-
pl: 'JSON Lista urządzeń korzystających z aktualizacji',
|
|
3946
|
-
// @ts-ignore
|
|
3947
|
-
uk: 'Сонце Перелік пристроїв з доступними оновленнями',
|
|
3948
|
-
'zh-cn': '附 件 现有最新设备清单',
|
|
3949
|
-
},
|
|
3950
|
-
type: 'array',
|
|
3951
|
-
role: 'json',
|
|
3952
|
-
read: true,
|
|
3953
|
-
write: false,
|
|
3954
|
-
},
|
|
3955
|
-
native: {},
|
|
3956
|
-
});
|
|
3957
|
-
|
|
3958
|
-
await this.setObjectNotExistsAsync(`devices.${adptName}.oneDeviceUpdatable`, {
|
|
3959
|
-
type: 'state',
|
|
3960
|
-
common: {
|
|
3961
|
-
name: {
|
|
3962
|
-
en: 'Is one device updatable',
|
|
3963
|
-
de: 'Ist ein Gerät aufnehmbar',
|
|
3964
|
-
ru: 'Одно устройство обновляется',
|
|
3965
|
-
pt: 'É um dispositivo updatable',
|
|
3966
|
-
nl: 'Is een apparaat updat',
|
|
3967
|
-
fr: "Est-ce qu'un appareil est indéfectible",
|
|
3968
|
-
it: 'È un dispositivo updatable',
|
|
3969
|
-
es: 'Es un dispositivo actualizado',
|
|
3970
|
-
pl: 'Jest to jedno urządzenie updatable',
|
|
3971
|
-
// @ts-ignore
|
|
3972
|
-
uk: 'Є одним пристроєм',
|
|
3973
|
-
'zh-cn': '一台装置',
|
|
3974
|
-
},
|
|
3975
|
-
type: 'boolean',
|
|
3976
|
-
role: 'state',
|
|
3977
|
-
read: true,
|
|
3978
|
-
write: false,
|
|
3979
|
-
def: false,
|
|
3980
|
-
},
|
|
3981
|
-
native: {},
|
|
3982
|
-
});
|
|
3983
|
-
}
|
|
3984
|
-
|
|
3985
|
-
/**
|
|
3986
|
-
* delete datapoints for each adapter
|
|
3987
|
-
* @param {object} adptName - Adaptername of devices
|
|
3988
|
-
*/
|
|
3989
|
-
async deleteDPsForEachAdapter(adptName) {
|
|
3990
|
-
await this.delObjectAsync(`devices.${adptName}`);
|
|
3991
|
-
await this.delObjectAsync(`devices.${adptName}.offlineCount`);
|
|
3992
|
-
await this.delObjectAsync(`devices.${adptName}.offlineList`);
|
|
3993
|
-
await this.delObjectAsync(`devices.${adptName}.oneDeviceOffline`);
|
|
3994
|
-
await this.delObjectAsync(`devices.${adptName}.listAllRawJSON`);
|
|
3995
|
-
await this.delObjectAsync(`devices.${adptName}.listAll`);
|
|
3996
|
-
await this.delObjectAsync(`devices.${adptName}.linkQualityList`);
|
|
3997
|
-
await this.delObjectAsync(`devices.${adptName}.countAll`);
|
|
3998
|
-
await this.delObjectAsync(`devices.${adptName}.batteryList`);
|
|
3999
|
-
await this.delObjectAsync(`devices.${adptName}.lowBatteryList`);
|
|
4000
|
-
await this.delObjectAsync(`devices.${adptName}.lowBatteryCount`);
|
|
4001
|
-
await this.delObjectAsync(`devices.${adptName}.oneDeviceLowBat`);
|
|
4002
|
-
await this.delObjectAsync(`devices.${adptName}.batteryCount`);
|
|
4003
|
-
await this.delObjectAsync(`devices.${adptName}.upgradableCount`);
|
|
4004
|
-
await this.delObjectAsync(`devices.${adptName}.upgradableList`);
|
|
4005
|
-
await this.delObjectAsync(`devices.${adptName}.oneDeviceUpdatable`);
|
|
4006
|
-
}
|
|
4007
|
-
|
|
4008
|
-
/**
|
|
4009
|
-
* create HTML list datapoints
|
|
4010
|
-
* @param {object} [adptName] - Adaptername of devices
|
|
4011
|
-
**/
|
|
4012
|
-
async createHtmlListDatapoints(adptName) {
|
|
4013
|
-
let dpSubFolder;
|
|
4014
|
-
//write the datapoints in subfolders with the adaptername otherwise write the dP's in the root folder
|
|
4015
|
-
if (adptName) {
|
|
4016
|
-
dpSubFolder = `${adptName}.`;
|
|
4017
|
-
} else {
|
|
4018
|
-
dpSubFolder = '';
|
|
4019
|
-
}
|
|
4020
|
-
|
|
4021
|
-
await this.setObjectNotExistsAsync(`devices.${dpSubFolder}offlineListHTML`, {
|
|
4022
|
-
type: 'state',
|
|
4023
|
-
common: {
|
|
4024
|
-
name: {
|
|
4025
|
-
en: 'HTML List of offline devices',
|
|
4026
|
-
de: 'HTML Liste der Offline-Geräte',
|
|
4027
|
-
ru: 'HTML Список оффлайн устройств',
|
|
4028
|
-
pt: 'HTML Lista de dispositivos off-line',
|
|
4029
|
-
nl: 'HTML List van offline apparatuur',
|
|
4030
|
-
fr: 'HTML Liste des dispositifs hors ligne',
|
|
4031
|
-
it: 'HTML Elenco dei dispositivi offline',
|
|
4032
|
-
es: 'HTML Lista de dispositivos sin conexión',
|
|
4033
|
-
pl: 'HTML Lista urządzeń offline',
|
|
4034
|
-
'zh-cn': 'HTML 线装置清单',
|
|
4035
|
-
},
|
|
4036
|
-
type: 'string',
|
|
4037
|
-
role: 'html',
|
|
4038
|
-
read: true,
|
|
4039
|
-
write: false,
|
|
4040
|
-
},
|
|
4041
|
-
native: {},
|
|
4042
|
-
});
|
|
4043
|
-
|
|
4044
|
-
await this.setObjectNotExistsAsync(`devices.${dpSubFolder}linkQualityListHTML`, {
|
|
4045
|
-
type: 'state',
|
|
4046
|
-
common: {
|
|
4047
|
-
name: {
|
|
4048
|
-
en: 'HTML List of devices with signal strength',
|
|
4049
|
-
de: 'HTML Liste der Geräte mit Signalstärke',
|
|
4050
|
-
ru: 'HTML Список устройств с силой сигнала',
|
|
4051
|
-
pt: 'HTML Lista de dispositivos com força de sinal',
|
|
4052
|
-
nl: 'HTML List van apparaten met signaalkracht',
|
|
4053
|
-
fr: 'HTML Liste des dispositifs avec force de signal',
|
|
4054
|
-
it: 'HTML Elenco dei dispositivi con forza del segnale',
|
|
4055
|
-
es: 'HTML Lista de dispositivos con fuerza de señal',
|
|
4056
|
-
pl: 'HTML Lista urządzeń z siłą sygnałową',
|
|
4057
|
-
'zh-cn': 'HTML 具有信号实力的装置清单',
|
|
4058
|
-
},
|
|
4059
|
-
type: 'string',
|
|
4060
|
-
role: 'value',
|
|
4061
|
-
read: true,
|
|
4062
|
-
write: false,
|
|
4063
|
-
},
|
|
4064
|
-
native: {},
|
|
4065
|
-
});
|
|
4066
|
-
|
|
4067
|
-
await this.setObjectNotExistsAsync(`devices.${dpSubFolder}batteryListHTML`, {
|
|
4068
|
-
type: 'state',
|
|
4069
|
-
common: {
|
|
4070
|
-
name: {
|
|
4071
|
-
en: 'HTML List of devices with battery state',
|
|
4072
|
-
de: 'HTML Liste der Geräte mit Batteriezustand',
|
|
4073
|
-
ru: 'HTML Список устройств с состоянием батареи',
|
|
4074
|
-
pt: 'HTML Lista de dispositivos com estado da bateria',
|
|
4075
|
-
nl: 'HTML List van apparaten met batterij staat',
|
|
4076
|
-
fr: 'HTML Liste des appareils avec état de batterie',
|
|
4077
|
-
it: 'HTML Elenco dei dispositivi con stato della batteria',
|
|
4078
|
-
es: 'HTML Lista de dispositivos con estado de batería',
|
|
4079
|
-
pl: 'HTML Lista urządzeń z baterią stanową',
|
|
4080
|
-
'zh-cn': 'HTML 电池国装置清单',
|
|
4081
|
-
},
|
|
4082
|
-
type: 'string',
|
|
4083
|
-
role: 'html',
|
|
4084
|
-
read: true,
|
|
4085
|
-
write: false,
|
|
4086
|
-
},
|
|
4087
|
-
native: {},
|
|
4088
|
-
});
|
|
4089
|
-
|
|
4090
|
-
await this.setObjectNotExistsAsync(`devices.${dpSubFolder}lowBatteryListHTML`, {
|
|
4091
|
-
type: 'state',
|
|
4092
|
-
common: {
|
|
4093
|
-
name: {
|
|
4094
|
-
en: 'HTML List of devices with low battery state',
|
|
4095
|
-
de: 'HTML Liste der Geräte mit niedrigem Batteriezustand',
|
|
4096
|
-
ru: 'HTML Список устройств с низким состоянием батареи',
|
|
4097
|
-
pt: 'HTML Lista de dispositivos com baixo estado da bateria',
|
|
4098
|
-
nl: 'HTML List van apparaten met lage batterij staat',
|
|
4099
|
-
fr: 'HTML Liste des appareils à faible état de batterie',
|
|
4100
|
-
it: 'HTML Elenco di dispositivi con stato di batteria basso',
|
|
4101
|
-
es: 'HTML Lista de dispositivos con estado de batería bajo',
|
|
4102
|
-
pl: 'HTML Lista urządzeń o niskim stanie baterii',
|
|
4103
|
-
'zh-cn': 'HTML 低电池国家装置清单',
|
|
4104
|
-
},
|
|
4105
|
-
type: 'string',
|
|
4106
|
-
role: 'html',
|
|
4107
|
-
read: true,
|
|
4108
|
-
write: false,
|
|
4109
|
-
},
|
|
4110
|
-
native: {},
|
|
4111
|
-
});
|
|
4112
|
-
}
|
|
4113
|
-
|
|
4114
|
-
/**
|
|
4115
|
-
* delete html datapoints
|
|
4116
|
-
* @param {object} [adptName] - Adaptername of devices
|
|
4117
|
-
**/
|
|
4118
|
-
async deleteHtmlListDatapoints(adptName) {
|
|
4119
|
-
// delete the datapoints in subfolders with the adaptername otherwise delete the dP's in the root folder
|
|
4120
|
-
let dpSubFolder;
|
|
4121
|
-
if (adptName) {
|
|
4122
|
-
dpSubFolder = `${adptName}.`;
|
|
4123
|
-
} else {
|
|
4124
|
-
dpSubFolder = '';
|
|
4125
|
-
}
|
|
4126
|
-
|
|
4127
|
-
await this.delObjectAsync(`devices.${dpSubFolder}offlineListHTML`);
|
|
4128
|
-
await this.delObjectAsync(`devices.${dpSubFolder}linkQualityListHTML`);
|
|
4129
|
-
await this.delObjectAsync(`devices.${dpSubFolder}batteryListHTML`);
|
|
4130
|
-
await this.delObjectAsync(`devices.${dpSubFolder}lowBatteryListHTML`);
|
|
4131
|
-
}
|
|
4132
|
-
|
|
4133
|
-
/**
|
|
4134
|
-
* create HTML list datapoints for instances
|
|
4135
|
-
**/
|
|
4136
|
-
async createHtmlListDatapointsInstances() {
|
|
4137
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists`, {
|
|
4138
|
-
type: 'channel',
|
|
4139
|
-
common: {
|
|
4140
|
-
name: {
|
|
4141
|
-
en: 'HTML lists for adapter and instances',
|
|
4142
|
-
de: 'HTML-Listen für Adapter und Instanzen',
|
|
4143
|
-
ru: 'HTML-списки для адаптеров и инстанций',
|
|
4144
|
-
pt: 'Listas HTML para adaptador e instâncias',
|
|
4145
|
-
nl: 'HTML lijsten voor adapter en instituut',
|
|
4146
|
-
fr: "Listes HTML pour l'adaptateur et les instances",
|
|
4147
|
-
it: 'Elenchi HTML per adattatore e istanze',
|
|
4148
|
-
es: 'Listas HTML para adaptador y casos',
|
|
4149
|
-
pl: 'Listy HTML dla adaptera i instancji',
|
|
4150
|
-
// @ts-ignore
|
|
4151
|
-
uk: 'Списки HTML для адаптерів та екземплярів',
|
|
4152
|
-
'zh-cn': 'HTML名单',
|
|
4153
|
-
},
|
|
4154
|
-
},
|
|
4155
|
-
native: {},
|
|
4156
|
-
});
|
|
4157
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`, {
|
|
4158
|
-
type: 'state',
|
|
4159
|
-
common: {
|
|
4160
|
-
name: {
|
|
4161
|
-
en: 'HTML List of all instances',
|
|
4162
|
-
de: 'HTML Liste aller Instanzen',
|
|
4163
|
-
ru: 'HTML Список всех инстанций',
|
|
4164
|
-
pt: 'HTML Lista de todas as instâncias',
|
|
4165
|
-
nl: 'HTM List van alle instanties',
|
|
4166
|
-
fr: 'HTML Liste de tous les cas',
|
|
4167
|
-
it: 'HTML Elenco di tutte le istanze',
|
|
4168
|
-
es: 'HTML Lista de todos los casos',
|
|
4169
|
-
pl: 'HTML Lista wszystkich instancji',
|
|
4170
|
-
// @ts-ignore
|
|
4171
|
-
uk: 'Українська Список всіх екземплярів',
|
|
4172
|
-
'zh-cn': 'HTML 所有事例一览表',
|
|
4173
|
-
},
|
|
4174
|
-
type: 'string',
|
|
4175
|
-
role: 'html',
|
|
4176
|
-
read: true,
|
|
4177
|
-
write: false,
|
|
4178
|
-
},
|
|
4179
|
-
native: {},
|
|
4180
|
-
});
|
|
4181
|
-
|
|
4182
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`, {
|
|
4183
|
-
type: 'state',
|
|
4184
|
-
common: {
|
|
4185
|
-
name: {
|
|
4186
|
-
en: 'HTML List of all active instances',
|
|
4187
|
-
de: 'HTML Liste aller aktiven Instanzen',
|
|
4188
|
-
ru: 'HTML Список всех активных инстанций',
|
|
4189
|
-
pt: 'HTML Lista de todas as instâncias ativas',
|
|
4190
|
-
nl: 'HTM List van alle actieve instanties',
|
|
4191
|
-
fr: 'HTML Liste de tous les cas actifs',
|
|
4192
|
-
it: 'HTML Elenco di tutte le istanze attive',
|
|
4193
|
-
es: 'HTML Lista de todos los casos activos',
|
|
4194
|
-
pl: 'HTML Lista wszystkich aktywnych instancji',
|
|
4195
|
-
// @ts-ignore
|
|
4196
|
-
uk: 'Українська Список всіх активних екземплярів',
|
|
4197
|
-
'zh-cn': 'HTML 所有积极事件清单',
|
|
4198
|
-
},
|
|
4199
|
-
type: 'string',
|
|
4200
|
-
role: 'value',
|
|
4201
|
-
read: true,
|
|
4202
|
-
write: false,
|
|
4203
|
-
},
|
|
4204
|
-
native: {},
|
|
4205
|
-
});
|
|
4206
|
-
|
|
4207
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`, {
|
|
4208
|
-
type: 'state',
|
|
4209
|
-
common: {
|
|
4210
|
-
name: {
|
|
4211
|
-
en: 'HTML List of all deactivated instances',
|
|
4212
|
-
de: 'HTML Liste aller deaktivierten Instanzen',
|
|
4213
|
-
ru: 'HTML Список всех деактивированных инстанций',
|
|
4214
|
-
pt: 'HTML Lista de todas as instâncias desativadas',
|
|
4215
|
-
nl: 'HTM List van alle gedeactiveerde instanties',
|
|
4216
|
-
fr: 'HTML Liste de tous les cas désactivés',
|
|
4217
|
-
it: 'HTML Elenco di tutte le istanze disattivate',
|
|
4218
|
-
es: 'HTML Lista de todos los casos desactivados',
|
|
4219
|
-
pl: 'HTML Lista wszystkich przypadków deaktywowanych',
|
|
4220
|
-
// @ts-ignore
|
|
4221
|
-
uk: 'Українська Список всіх деактивованих екземплярів',
|
|
4222
|
-
'zh-cn': 'HTML 所有违犯事件清单',
|
|
4223
|
-
},
|
|
4224
|
-
type: 'string',
|
|
4225
|
-
role: 'html',
|
|
4226
|
-
read: true,
|
|
4227
|
-
write: false,
|
|
4228
|
-
},
|
|
4229
|
-
native: {},
|
|
4230
|
-
});
|
|
4231
|
-
|
|
4232
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`, {
|
|
4233
|
-
type: 'state',
|
|
4234
|
-
common: {
|
|
4235
|
-
name: {
|
|
4236
|
-
en: 'HTML List of instances with error',
|
|
4237
|
-
de: 'HTML Liste der Fälle mit Fehler',
|
|
4238
|
-
ru: 'HTML Список инстанций с ошибкой',
|
|
4239
|
-
pt: 'HTML Lista de casos com erro',
|
|
4240
|
-
nl: 'HTM List van instoringen met fouten',
|
|
4241
|
-
fr: 'HTML Liste des instances avec erreur',
|
|
4242
|
-
it: 'HTML Elenco delle istanze con errore',
|
|
4243
|
-
es: 'HTML Lista de casos con error',
|
|
4244
|
-
pl: 'HTML Lista przykładów z błądem',
|
|
4245
|
-
// @ts-ignore
|
|
4246
|
-
uk: 'Українська Список екземплярів з помилкою',
|
|
4247
|
-
'zh-cn': 'HTML 出现错误的情况清单',
|
|
4248
|
-
},
|
|
4249
|
-
type: 'string',
|
|
4250
|
-
role: 'html',
|
|
4251
|
-
read: true,
|
|
4252
|
-
write: false,
|
|
4253
|
-
},
|
|
4254
|
-
native: {},
|
|
4255
|
-
});
|
|
4256
|
-
await this.setObjectNotExistsAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`, {
|
|
4257
|
-
type: 'state',
|
|
4258
|
-
common: {
|
|
4259
|
-
name: {
|
|
4260
|
-
en: 'HTML list of adapters with available updates',
|
|
4261
|
-
de: 'HTML-Liste der Adapter mit verfügbaren Updates',
|
|
4262
|
-
ru: 'HTML список адаптеров с доступными обновлениями',
|
|
4263
|
-
pt: 'Lista HTML de adaptadores com atualizações disponíveis',
|
|
4264
|
-
nl: 'HTML lijst met beschikbare updates',
|
|
4265
|
-
fr: 'Liste HTML des adaptateurs avec mises à jour disponibles',
|
|
4266
|
-
it: 'Elenco HTML degli adattatori con aggiornamenti disponibili',
|
|
4267
|
-
es: 'Lista HTML de adaptadores con actualizaciones disponibles',
|
|
4268
|
-
pl: 'Lista adapterów HTML z dostępnymi aktualizacjami',
|
|
4269
|
-
// @ts-ignore
|
|
4270
|
-
uk: 'HTML список адаптерів з доступними оновленнями',
|
|
4271
|
-
'zh-cn': 'HTML 可供更新的适应者名单',
|
|
4272
|
-
},
|
|
4273
|
-
type: 'string',
|
|
4274
|
-
role: 'html',
|
|
4275
|
-
read: true,
|
|
4276
|
-
write: false,
|
|
4277
|
-
},
|
|
4278
|
-
native: {},
|
|
4279
|
-
});
|
|
4280
|
-
}
|
|
4281
|
-
|
|
4282
|
-
/**
|
|
4283
|
-
* delete html datapoints for instances
|
|
4284
|
-
**/
|
|
4285
|
-
async deleteHtmlListDatapointsInstances() {
|
|
4286
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllInstancesHTML`);
|
|
4287
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAllActiveInstancesHTML`);
|
|
4288
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listDeactivatedInstancesHTML`);
|
|
4289
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listInstancesErrorHTML`);
|
|
4290
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists.listAdapterUpdatesHTML`);
|
|
4291
|
-
await this.delObjectAsync(`adapterAndInstances.HTML_Lists`);
|
|
4292
|
-
}
|
|
4293
|
-
|
|
4294
|
-
/*=============================================
|
|
4295
|
-
= help functions =
|
|
4296
|
-
=============================================*/
|
|
4297
|
-
|
|
4298
|
-
/**
|
|
4299
|
-
* @param {string} id - id which should be capitalize
|
|
4300
|
-
*/
|
|
4301
|
-
capitalize(id) {
|
|
4302
|
-
//make the first letter uppercase
|
|
4303
|
-
return id && id[0].toUpperCase() + id.slice(1);
|
|
4304
|
-
}
|
|
4305
|
-
|
|
4306
|
-
/**
|
|
4307
|
-
* @param {number} dpValue - get Time of this datapoint
|
|
4308
|
-
*/
|
|
4309
|
-
getTimestamp(dpValue) {
|
|
4310
|
-
const time = new Date();
|
|
4311
|
-
return (dpValue = Math.round((time.getTime() - dpValue) / 1000 / 60));
|
|
4312
|
-
}
|
|
4313
|
-
|
|
4314
|
-
/**
|
|
4315
|
-
* @param {string} dp - get Time of this datapoint
|
|
4316
|
-
* @param {number} ms - milliseconds
|
|
4317
|
-
*/
|
|
4318
|
-
async getTimestampConnectionDP(dp, ms) {
|
|
4319
|
-
const time = new Date();
|
|
4320
|
-
const dpValue = await this.getForeignStateAsync(dp);
|
|
4321
|
-
if (dpValue) {
|
|
4322
|
-
if (!dpValue.val) return false;
|
|
4323
|
-
|
|
4324
|
-
const dpLastStateChange = Math.round(time.getTime() - dpValue.lc); // calculate in ms
|
|
4325
|
-
if (dpLastStateChange >= ms) {
|
|
4326
|
-
return true;
|
|
4327
|
-
} else {
|
|
4328
|
-
return false;
|
|
4329
|
-
}
|
|
4330
|
-
}
|
|
4331
|
-
}
|
|
4332
|
-
|
|
4333
|
-
/**
|
|
4334
|
-
* @param {object} obj - State of datapoint
|
|
4335
|
-
*/
|
|
4336
|
-
async getInitValue(obj) {
|
|
4337
|
-
//state can be null or undefinded
|
|
4338
|
-
const foreignState = await this.getForeignStateAsync(obj);
|
|
4339
|
-
if (foreignState) return foreignState.val;
|
|
4340
|
-
}
|
|
4341
|
-
|
|
4342
|
-
/**
|
|
4343
|
-
* @param {object} obj - State of own datapoint
|
|
4344
|
-
*/
|
|
4345
|
-
async getOwnInitValue(obj) {
|
|
4346
|
-
//state can be null or undefinded for own states
|
|
4347
|
-
const stateVal = await this.getStateAsync(obj);
|
|
4348
|
-
if (stateVal) return stateVal.val;
|
|
4349
|
-
}
|
|
4350
|
-
|
|
4351
|
-
/**
|
|
4352
|
-
* @param {object} data - object
|
|
4353
|
-
*/
|
|
4354
|
-
parseData(data) {
|
|
4355
|
-
if (!data) return {};
|
|
4356
|
-
if (typeof data === 'object') return data;
|
|
4357
|
-
if (typeof data === 'string') return JSON.parse(data);
|
|
4358
|
-
return {};
|
|
4359
|
-
}
|
|
4360
|
-
|
|
4361
|
-
/**
|
|
4362
|
-
* Get previous run of cron job schedule
|
|
4363
|
-
* Requires cron-parser!
|
|
4364
|
-
* Inspired by https://stackoverflow.com/questions/68134104/
|
|
4365
|
-
* @param {string} lastCronRun
|
|
4366
|
-
*/
|
|
4367
|
-
getPreviousCronRun(lastCronRun) {
|
|
4368
|
-
try {
|
|
4369
|
-
const interval = cronParser.parseExpression(lastCronRun);
|
|
4370
|
-
const previous = interval.prev();
|
|
4371
|
-
return Math.floor(Date.now() - previous.getTime()); // in ms
|
|
4372
|
-
} catch (error) {
|
|
4373
|
-
this.log.error(`[getPreviousCronRun] - ${error}`);
|
|
4374
|
-
}
|
|
4375
|
-
}
|
|
4376
|
-
|
|
4377
2351
|
/**
|
|
4378
2352
|
* @param {() => void} callback
|
|
4379
2353
|
*/
|