iobroker.zigbee 1.8.22 → 1.8.23
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/LICENSE +21 -21
- package/README.md +417 -414
- package/admin/adapter-settings.js +244 -244
- package/admin/admin.js +2981 -2981
- package/admin/i18n/de/translations.json +108 -108
- package/admin/i18n/en/translations.json +108 -108
- package/admin/i18n/es/translations.json +102 -102
- package/admin/i18n/fr/translations.json +108 -108
- package/admin/i18n/it/translations.json +102 -102
- package/admin/i18n/nl/translations.json +108 -108
- package/admin/i18n/pl/translations.json +108 -108
- package/admin/i18n/pt/translations.json +102 -102
- package/admin/i18n/ru/translations.json +108 -108
- package/admin/i18n/uk/translations.json +108 -108
- package/admin/i18n/zh-cn/translations.json +102 -102
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/index.html +159 -159
- package/admin/index_m.html +1356 -1356
- package/admin/moment.min.js +1 -1
- package/admin/shuffle.min.js +2 -2
- package/admin/tab_m.html +1009 -1009
- package/admin/vis-network.min.css +1 -1
- package/admin/vis-network.min.js +27 -27
- package/admin/words.js +110 -110
- package/docs/de/basedocu.md +19 -19
- package/docs/de/readme.md +126 -126
- package/docs/en/readme.md +128 -128
- package/docs/flashing_via_arduino_(en).md +110 -110
- package/docs/ru/readme.md +28 -28
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +14 -14
- package/lib/backup.js +171 -171
- package/lib/binding.js +319 -319
- package/lib/colors.js +465 -465
- package/lib/commands.js +534 -534
- package/lib/developer.js +145 -145
- package/lib/devices.js +3135 -3135
- package/lib/exclude.js +162 -162
- package/lib/exposes.js +913 -913
- package/lib/groups.js +345 -345
- package/lib/json.js +59 -59
- package/lib/networkmap.js +55 -55
- package/lib/ota.js +198 -198
- package/lib/rgb.js +297 -297
- package/lib/seriallist.js +48 -48
- package/lib/states.js +6420 -6420
- package/lib/statescontroller.js +672 -672
- package/lib/tools.js +54 -54
- package/lib/utils.js +165 -165
- package/lib/zbBaseExtension.js +36 -36
- package/lib/zbDelayedAction.js +144 -144
- package/lib/zbDeviceAvailability.js +319 -319
- package/lib/zbDeviceConfigure.js +147 -147
- package/lib/zbDeviceEvent.js +48 -48
- package/lib/zigbeecontroller.js +989 -989
- package/main.js +94 -75
- package/package.json +2 -2
- package/support/docgen.js +93 -93
package/main.js
CHANGED
|
@@ -124,7 +124,7 @@ class Zigbee extends utils.Adapter {
|
|
|
124
124
|
message
|
|
125
125
|
}));
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
if (typeof error == 'string') {
|
|
129
129
|
Sentry.captureException(new Error(error));
|
|
130
130
|
} else {
|
|
@@ -134,7 +134,7 @@ class Zigbee extends utils.Adapter {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
} catch (err) {
|
|
137
|
-
this.log.error(`SentryError : ${message} ${error} ${err} `);
|
|
137
|
+
this.log.error(`SentryError : ${message} ${error} ${err} `);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -278,7 +278,7 @@ class Zigbee extends utils.Adapter {
|
|
|
278
278
|
delete toAdd['homeassistant'];
|
|
279
279
|
try {
|
|
280
280
|
zigbeeHerdsmanConverters.addDeviceDefinition(toAdd);
|
|
281
|
-
} catch {
|
|
281
|
+
} catch {
|
|
282
282
|
this.log.error(`unable to apply external converter ${JSON.stringfy(toAdd)}`);
|
|
283
283
|
}
|
|
284
284
|
}
|
|
@@ -465,50 +465,57 @@ class Zigbee extends utils.Adapter {
|
|
|
465
465
|
// this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
|
|
466
466
|
meta.logger = this.log;
|
|
467
467
|
|
|
468
|
-
await this.checkIfModelUpdate(entity);
|
|
469
|
-
|
|
470
|
-
let
|
|
471
|
-
let
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
468
|
+
await this.checkIfModelUpdate(entity);
|
|
469
|
+
|
|
470
|
+
let _voltage = 0;
|
|
471
|
+
let _temperature = 0;
|
|
472
|
+
let _humidity = 0;
|
|
473
|
+
|
|
474
|
+
let isMessure = false;
|
|
475
|
+
let isBattKey = false;
|
|
476
|
+
|
|
477
|
+
if (mappedModel && mappedModel.meta && mappedModel.meta.battery) {
|
|
478
|
+
const isVoltage = mappedModel.meta.battery.hasOwnProperty('voltageToPercentage');
|
|
479
|
+
|
|
480
|
+
if (isVoltage) {
|
|
481
|
+
const keys = Object.keys(message.data);
|
|
482
|
+
|
|
483
|
+
for (const key of keys) {
|
|
484
|
+
const value = message.data[key];
|
|
485
|
+
|
|
486
|
+
if (value && value[1]) {
|
|
487
|
+
if (key == 65282 && value[1][1]) {
|
|
488
|
+
_voltage = value[1][1].elmVal;
|
|
489
|
+
isBattKey = true;
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
if (key == 65281) {
|
|
493
|
+
_voltage = value[1];
|
|
494
|
+
isBattKey = true;
|
|
495
|
+
_temperature = value[100];
|
|
496
|
+
_temperature = _temperature /100;
|
|
497
|
+
_humidity = value[101];
|
|
498
|
+
_humidity = _humidity / 100;
|
|
499
|
+
isMessure = true;
|
|
500
|
+
break;
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
503
|
}
|
|
501
504
|
}
|
|
502
505
|
}
|
|
503
|
-
|
|
506
|
+
|
|
504
507
|
// always publish link_quality and battery
|
|
505
508
|
if (message.linkquality) { // send battery with
|
|
506
509
|
this.publishToState(devId, model, {linkquality: message.linkquality});
|
|
507
|
-
if (
|
|
508
|
-
this.publishToState(devId, model, {voltage:
|
|
509
|
-
const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(
|
|
510
|
+
if (isBattKey) {
|
|
511
|
+
this.publishToState(devId, model, {voltage: _voltage});
|
|
512
|
+
const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(_voltage,entity.mapped.meta.battery.voltageToPercentage);
|
|
510
513
|
this.publishToState(devId, model, {battery: battProz});
|
|
511
514
|
}
|
|
515
|
+
if (isMessure) {
|
|
516
|
+
this.publishToState(devId, model, {temperature: _temperature});
|
|
517
|
+
this.publishToState(devId, model, {humidity: _humidity});
|
|
518
|
+
}
|
|
512
519
|
}
|
|
513
520
|
|
|
514
521
|
// publish raw event to "from_zigbee"
|
|
@@ -540,31 +547,43 @@ class Zigbee extends utils.Adapter {
|
|
|
540
547
|
return;
|
|
541
548
|
}
|
|
542
549
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
+
this.processConverters(converters, devId, model, mappedModel, message, meta)
|
|
551
|
+
// .then(() => {
|
|
552
|
+
//
|
|
553
|
+
// })
|
|
554
|
+
.catch((error) => {
|
|
555
|
+
this.log.error(`Error while processing converters: '${error}'`);
|
|
556
|
+
});
|
|
557
|
+
}
|
|
550
558
|
|
|
559
|
+
async processConverters(converters, devId, model, mappedModel, message, meta) {
|
|
551
560
|
for (const converter of converters) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
if (payload) {
|
|
557
|
-
if (Object.keys(payload).length) {
|
|
558
|
-
publish(payload);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
} catch (err) {
|
|
562
|
-
this.log.warn(`convert problem with '${model}' '${devId}' `);
|
|
561
|
+
const publish = (payload) => {
|
|
562
|
+
this.log.debug(`Publish ${safeJsonStringify(payload)} to ${safeJsonStringify(devId)}`);
|
|
563
|
+
if (payload) {
|
|
564
|
+
this.publishToState(devId, model, payload);
|
|
563
565
|
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const options = await new Promise((resolve, reject) => {
|
|
569
|
+
this.stController.collectOptions(devId, model, (options) => {
|
|
570
|
+
resolve(options);
|
|
571
|
+
});
|
|
564
572
|
});
|
|
573
|
+
|
|
574
|
+
const payload = await new Promise((resolve, reject) => {
|
|
575
|
+
const payload = converter.convert(mappedModel, message, publish, options, meta);
|
|
576
|
+
if (payload) {
|
|
577
|
+
resolve(payload);
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
publish(payload);
|
|
565
582
|
}
|
|
566
583
|
}
|
|
567
584
|
|
|
585
|
+
|
|
586
|
+
|
|
568
587
|
publishToState(devId, model, payload) {
|
|
569
588
|
this.stController.publishToState(devId, model, payload);
|
|
570
589
|
}
|
|
@@ -595,20 +614,20 @@ class Zigbee extends utils.Adapter {
|
|
|
595
614
|
}
|
|
596
615
|
try {
|
|
597
616
|
const entity = await this.zbController.resolveEntity(deviceId);
|
|
598
|
-
|
|
617
|
+
|
|
599
618
|
this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`);
|
|
600
|
-
|
|
601
|
-
const mappedModel = entity.mapped;
|
|
602
|
-
|
|
619
|
+
|
|
620
|
+
const mappedModel = entity.mapped;
|
|
621
|
+
|
|
603
622
|
if (!mappedModel) {
|
|
604
623
|
this.log.debug(`No mapped model for ${model}`);
|
|
605
624
|
return;
|
|
606
625
|
}
|
|
607
|
-
|
|
626
|
+
|
|
608
627
|
stateList.forEach(async changedState => {
|
|
609
628
|
const stateDesc = changedState.stateDesc;
|
|
610
629
|
const value = changedState.value;
|
|
611
|
-
|
|
630
|
+
|
|
612
631
|
if (stateDesc.id === 'send_payload') {
|
|
613
632
|
try {
|
|
614
633
|
const json_value = JSON.parse(value);
|
|
@@ -623,14 +642,14 @@ class Zigbee extends utils.Adapter {
|
|
|
623
642
|
}
|
|
624
643
|
return;
|
|
625
644
|
}
|
|
626
|
-
|
|
645
|
+
|
|
627
646
|
if (stateDesc.isOption) {
|
|
628
647
|
// acknowledge state with given value
|
|
629
648
|
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
630
649
|
// process sync state list
|
|
631
650
|
//this.processSyncStatesList(deviceId, modelId, syncStateList);
|
|
632
651
|
// if this is the device query state => trigger the device query
|
|
633
|
-
|
|
652
|
+
|
|
634
653
|
// on activation of the 'device_query' state trigger hardware query where possible
|
|
635
654
|
if (stateDesc.id === 'device_query') {
|
|
636
655
|
if (this.query_device_block.indexOf(deviceId) > -1) {
|
|
@@ -647,7 +666,7 @@ class Zigbee extends utils.Adapter {
|
|
|
647
666
|
await converter.convertGet(entity.device.endpoints[0], ckey, {});
|
|
648
667
|
} catch (error) {
|
|
649
668
|
this.log.warn(`Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${JSON.stringify(error)}'`);
|
|
650
|
-
|
|
669
|
+
|
|
651
670
|
}
|
|
652
671
|
}
|
|
653
672
|
}
|
|
@@ -671,7 +690,7 @@ class Zigbee extends utils.Adapter {
|
|
|
671
690
|
this.sendError(`No converter available for '${model}' with key '${stateDesc.id}' `);
|
|
672
691
|
return;
|
|
673
692
|
}
|
|
674
|
-
|
|
693
|
+
|
|
675
694
|
const preparedValue = (stateDesc.setter) ? stateDesc.setter(value, options) : value;
|
|
676
695
|
const preparedOptions = (stateDesc.setterOpt) ? stateDesc.setterOpt(value, options) : {};
|
|
677
696
|
let syncStateList = [];
|
|
@@ -683,11 +702,11 @@ class Zigbee extends utils.Adapter {
|
|
|
683
702
|
}
|
|
684
703
|
});
|
|
685
704
|
}
|
|
686
|
-
|
|
705
|
+
|
|
687
706
|
const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
|
|
688
707
|
const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
|
|
689
708
|
this.log.debug(`convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)}`);
|
|
690
|
-
|
|
709
|
+
|
|
691
710
|
let target;
|
|
692
711
|
if (model === 'group') {
|
|
693
712
|
target = entity.mapped;
|
|
@@ -695,9 +714,9 @@ class Zigbee extends utils.Adapter {
|
|
|
695
714
|
target = await this.zbController.resolveEntity(deviceId, epName);
|
|
696
715
|
target = target.endpoint;
|
|
697
716
|
}
|
|
698
|
-
|
|
717
|
+
|
|
699
718
|
this.log.debug(`target: ${safeJsonStringify(target)}`);
|
|
700
|
-
|
|
719
|
+
|
|
701
720
|
const meta = {
|
|
702
721
|
endpoint_name: epName,
|
|
703
722
|
options: preparedOptions,
|
|
@@ -707,11 +726,11 @@ class Zigbee extends utils.Adapter {
|
|
|
707
726
|
logger: this.log,
|
|
708
727
|
state: {},
|
|
709
728
|
};
|
|
710
|
-
|
|
729
|
+
|
|
711
730
|
if (preparedOptions.hasOwnProperty('state')) {
|
|
712
731
|
meta.state = preparedOptions.state;
|
|
713
732
|
}
|
|
714
|
-
|
|
733
|
+
|
|
715
734
|
try {
|
|
716
735
|
const result = await converter.convertSet(target, key, preparedValue, meta);
|
|
717
736
|
this.log.debug(`convert result ${safeJsonStringify(result)}`);
|
|
@@ -721,20 +740,20 @@ class Zigbee extends utils.Adapter {
|
|
|
721
740
|
}
|
|
722
741
|
// process sync state list
|
|
723
742
|
this.processSyncStatesList(deviceId, model, syncStateList);
|
|
724
|
-
|
|
743
|
+
|
|
725
744
|
if (isGroup) {
|
|
726
745
|
await this.callPluginMethod('queryGroupMemberState', [deviceId, stateDesc]);
|
|
727
746
|
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
728
747
|
}
|
|
729
748
|
}
|
|
730
|
-
|
|
749
|
+
|
|
731
750
|
} catch (error) {
|
|
732
751
|
this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
|
|
733
752
|
` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
|
|
734
753
|
}
|
|
735
754
|
});
|
|
736
755
|
} catch (err) {
|
|
737
|
-
this.log.error(`No entity for ${deviceId}`);
|
|
756
|
+
this.log.error(`No entity for ${deviceId}`);
|
|
738
757
|
}
|
|
739
758
|
}
|
|
740
759
|
|
|
@@ -950,7 +969,7 @@ class Zigbee extends utils.Adapter {
|
|
|
950
969
|
}
|
|
951
970
|
|
|
952
971
|
onPairing(message, data) {
|
|
953
|
-
if (Number.isInteger(data)) {
|
|
972
|
+
if (Number.isInteger(data)) {
|
|
954
973
|
this.setState('info.pairingCountdown', data, true);
|
|
955
974
|
}
|
|
956
975
|
if (data === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.23",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"tar": "^6.1.15",
|
|
26
26
|
"typescript": "^5.1.6",
|
|
27
27
|
"zigbee-herdsman": "0.17.2",
|
|
28
|
-
"zigbee-herdsman-converters": "15.
|
|
28
|
+
"zigbee-herdsman-converters": "15.55.3"
|
|
29
29
|
},
|
|
30
30
|
"description": "Zigbee devices",
|
|
31
31
|
"devDependencies": {
|
package/support/docgen.js
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This script generates the supported devices page.
|
|
3
|
-
*
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
let devices = [...require('zigbee-herdsman-converters').devices];
|
|
7
|
-
|
|
8
|
-
for (const device of devices) {
|
|
9
|
-
if (device.whiteLabel) {
|
|
10
|
-
for (const whiteLabel of device.whiteLabel) {
|
|
11
|
-
const whiteLabelDevice = {
|
|
12
|
-
...device,
|
|
13
|
-
model: whiteLabel.model,
|
|
14
|
-
vendor: whiteLabel.vendor,
|
|
15
|
-
description: whiteLabel.description,
|
|
16
|
-
whiteLabelOf: device,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
delete whiteLabelDevice.whiteLabel;
|
|
20
|
-
|
|
21
|
-
devices.push(whiteLabelDevice);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
devices = new Map(devices.map((d) => [d.model, d]));
|
|
27
|
-
|
|
28
|
-
const Devices = require('../lib/devices');
|
|
29
|
-
let iobDevices = Devices.devices;
|
|
30
|
-
Devices.fillStatesWithExposes('');
|
|
31
|
-
|
|
32
|
-
const iobCount = iobDevices.filter((d) => (!d.exposed)).length;
|
|
33
|
-
iobDevices = new Map(iobDevices.map((d) => d.models.map((m) => [m, d])).flat());
|
|
34
|
-
|
|
35
|
-
const fs = require('fs');
|
|
36
|
-
const outputdir = process.argv[2];
|
|
37
|
-
|
|
38
|
-
if (!outputdir) {
|
|
39
|
-
console.error('Please specify an output directory');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const file = 'Supported-devices.md';
|
|
43
|
-
let text = `*NOTE: Automatically generated by 'npm run docgen'* \n\n` +
|
|
44
|
-
`Currently **${iobDevices.size}**(${iobCount} described in adapter) devices are supported.\n\n` +
|
|
45
|
-
`(⭐EXP) - means that the device is presented automatically, based on the 'exposes' from the zigbee-herdsman-converters.\n\n`;
|
|
46
|
-
|
|
47
|
-
const logDevices = (devmodels) => {
|
|
48
|
-
let result = '';
|
|
49
|
-
|
|
50
|
-
devmodels.forEach((devmodel) => {
|
|
51
|
-
const iobDevice = iobDevices.get(devmodel);
|
|
52
|
-
const device = devices.get(devmodel);
|
|
53
|
-
const pathImg = (iobDevice.icon.startsWith('http')) ? devmodel : iobDevice.icon.replace(new RegExp('img/', 'g'), '').replace(new RegExp('.png', 'g'), '');
|
|
54
|
-
const icon = (iobDevice.icon.startsWith('http')) ? iobDevice.icon : `https://github.com/ioBroker/ioBroker.zigbee/raw/master/admin/${iobDevice.icon}`;
|
|
55
|
-
let brand;
|
|
56
|
-
const models = [];
|
|
57
|
-
let zmodels;
|
|
58
|
-
if (device.zigbeeModel) {
|
|
59
|
-
zmodels = device.zigbeeModel;
|
|
60
|
-
} else {
|
|
61
|
-
zmodels = [devmodel];
|
|
62
|
-
}
|
|
63
|
-
zmodels.forEach((modelId) => {
|
|
64
|
-
const re = /[^\x20-\x7E]+/g;
|
|
65
|
-
const model = modelId.replace(re, ' ');
|
|
66
|
-
const desc = `${device.description} (${device.supports})`;
|
|
67
|
-
const name = `**${device.model}${(iobDevice.exposed) ? ' (⭐EXP)': ''}**<br>`;
|
|
68
|
-
if (brand == undefined) {
|
|
69
|
-
brand= {
|
|
70
|
-
name: name,
|
|
71
|
-
desc: desc,
|
|
72
|
-
pathImg: pathImg,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
models.push(model);
|
|
76
|
-
});
|
|
77
|
-
const modelsStr = models.join(', ');
|
|
78
|
-
result += `| ${brand.name} (${modelsStr}) | ${brand.desc} |  |\n`;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
return result;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const vendors = Array.from(new Set([...iobDevices.keys()].map((m) => (devices.get(m)) ? devices.get(m).vendor : null)));
|
|
85
|
-
vendors.sort();
|
|
86
|
-
text += '| Model | Description | Picture |\n';
|
|
87
|
-
text += '| ------------- | ------------- | -------------------------- |\n';
|
|
88
|
-
vendors.forEach((vendor) => {
|
|
89
|
-
text += `| | **${vendor}** | |\n`;
|
|
90
|
-
text += logDevices([...iobDevices.keys()].map((m) => devices.get(m)).filter((d) => d && d.vendor === vendor).map((d) => d.model));
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
fs.writeFileSync(outputdir + '/' + file, text);
|
|
1
|
+
/**
|
|
2
|
+
* This script generates the supported devices page.
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
let devices = [...require('zigbee-herdsman-converters').devices];
|
|
7
|
+
|
|
8
|
+
for (const device of devices) {
|
|
9
|
+
if (device.whiteLabel) {
|
|
10
|
+
for (const whiteLabel of device.whiteLabel) {
|
|
11
|
+
const whiteLabelDevice = {
|
|
12
|
+
...device,
|
|
13
|
+
model: whiteLabel.model,
|
|
14
|
+
vendor: whiteLabel.vendor,
|
|
15
|
+
description: whiteLabel.description,
|
|
16
|
+
whiteLabelOf: device,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
delete whiteLabelDevice.whiteLabel;
|
|
20
|
+
|
|
21
|
+
devices.push(whiteLabelDevice);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
devices = new Map(devices.map((d) => [d.model, d]));
|
|
27
|
+
|
|
28
|
+
const Devices = require('../lib/devices');
|
|
29
|
+
let iobDevices = Devices.devices;
|
|
30
|
+
Devices.fillStatesWithExposes('');
|
|
31
|
+
|
|
32
|
+
const iobCount = iobDevices.filter((d) => (!d.exposed)).length;
|
|
33
|
+
iobDevices = new Map(iobDevices.map((d) => d.models.map((m) => [m, d])).flat());
|
|
34
|
+
|
|
35
|
+
const fs = require('fs');
|
|
36
|
+
const outputdir = process.argv[2];
|
|
37
|
+
|
|
38
|
+
if (!outputdir) {
|
|
39
|
+
console.error('Please specify an output directory');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const file = 'Supported-devices.md';
|
|
43
|
+
let text = `*NOTE: Automatically generated by 'npm run docgen'* \n\n` +
|
|
44
|
+
`Currently **${iobDevices.size}**(${iobCount} described in adapter) devices are supported.\n\n` +
|
|
45
|
+
`(⭐EXP) - means that the device is presented automatically, based on the 'exposes' from the zigbee-herdsman-converters.\n\n`;
|
|
46
|
+
|
|
47
|
+
const logDevices = (devmodels) => {
|
|
48
|
+
let result = '';
|
|
49
|
+
|
|
50
|
+
devmodels.forEach((devmodel) => {
|
|
51
|
+
const iobDevice = iobDevices.get(devmodel);
|
|
52
|
+
const device = devices.get(devmodel);
|
|
53
|
+
const pathImg = (iobDevice.icon.startsWith('http')) ? devmodel : iobDevice.icon.replace(new RegExp('img/', 'g'), '').replace(new RegExp('.png', 'g'), '');
|
|
54
|
+
const icon = (iobDevice.icon.startsWith('http')) ? iobDevice.icon : `https://github.com/ioBroker/ioBroker.zigbee/raw/master/admin/${iobDevice.icon}`;
|
|
55
|
+
let brand;
|
|
56
|
+
const models = [];
|
|
57
|
+
let zmodels;
|
|
58
|
+
if (device.zigbeeModel) {
|
|
59
|
+
zmodels = device.zigbeeModel;
|
|
60
|
+
} else {
|
|
61
|
+
zmodels = [devmodel];
|
|
62
|
+
}
|
|
63
|
+
zmodels.forEach((modelId) => {
|
|
64
|
+
const re = /[^\x20-\x7E]+/g;
|
|
65
|
+
const model = modelId.replace(re, ' ');
|
|
66
|
+
const desc = `${device.description} (${device.supports})`;
|
|
67
|
+
const name = `**${device.model}${(iobDevice.exposed) ? ' (⭐EXP)': ''}**<br>`;
|
|
68
|
+
if (brand == undefined) {
|
|
69
|
+
brand= {
|
|
70
|
+
name: name,
|
|
71
|
+
desc: desc,
|
|
72
|
+
pathImg: pathImg,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
models.push(model);
|
|
76
|
+
});
|
|
77
|
+
const modelsStr = models.join(', ');
|
|
78
|
+
result += `| ${brand.name} (${modelsStr}) | ${brand.desc} |  |\n`;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const vendors = Array.from(new Set([...iobDevices.keys()].map((m) => (devices.get(m)) ? devices.get(m).vendor : null)));
|
|
85
|
+
vendors.sort();
|
|
86
|
+
text += '| Model | Description | Picture |\n';
|
|
87
|
+
text += '| ------------- | ------------- | -------------------------- |\n';
|
|
88
|
+
vendors.forEach((vendor) => {
|
|
89
|
+
text += `| | **${vendor}** | |\n`;
|
|
90
|
+
text += logDevices([...iobDevices.keys()].map((m) => devices.get(m)).filter((d) => d && d.vendor === vendor).map((d) => d.model));
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
fs.writeFileSync(outputdir + '/' + file, text);
|