iobroker.zigbee 1.8.10 → 1.8.13
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 -400
- 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/img/Bild10.png +0 -0
- package/docs/de/img/Bild12.png +0 -0
- package/docs/de/img/Bild13.png +0 -0
- package/docs/de/img/Bild14.png +0 -0
- package/docs/de/img/Bild15.png +0 -0
- package/docs/de/img/Bild16.png +0 -0
- package/docs/de/img/Bild17.png +0 -0
- package/docs/de/img/Bild18.png +0 -0
- package/docs/de/img/Bild19.png +0 -0
- package/docs/de/img/Bild2.png +0 -0
- package/docs/de/img/Bild20.png +0 -0
- package/docs/de/img/Bild21.png +0 -0
- package/docs/de/img/Bild22.png +0 -0
- package/docs/de/img/Bild23.png +0 -0
- package/docs/de/img/Bild24.png +0 -0
- package/docs/de/img/Bild25.png +0 -0
- package/docs/de/img/Bild26.png +0 -0
- package/docs/de/img/Bild28.png +0 -0
- package/docs/de/img/Bild3.png +0 -0
- package/docs/de/img/Bild30.png +0 -0
- package/docs/de/img/Bild31.png +0 -0
- package/docs/de/img/Bild32.png +0 -0
- package/docs/de/img/Bild33.png +0 -0
- package/docs/de/img/Bild34.png +0 -0
- package/docs/de/img/Bild35.png +0 -0
- package/docs/de/img/Bild36.png +0 -0
- package/docs/de/img/Bild37.png +0 -0
- package/docs/de/img/Bild4.png +0 -0
- package/docs/de/img/Bild5.jpg +0 -0
- package/docs/de/img/Bild6.png +0 -0
- package/docs/de/img/Bild7.png +0 -0
- package/docs/de/img/Bild8.png +0 -0
- package/docs/de/img/Bild9.png +0 -0
- package/docs/de/img/software1.jpg +0 -0
- package/docs/de/img/sonoff.png +0 -0
- package/docs/de/readme.md +126 -27
- package/docs/en/img/Bild13.png +0 -0
- package/docs/en/img/Bild18.png +0 -0
- package/docs/en/img/Bild23.png +0 -0
- package/docs/en/img/Bild25.png +0 -0
- package/docs/en/img/Bild26.png +0 -0
- package/docs/en/img/Bild4.png +0 -0
- package/docs/en/img/Bild9.png +0 -0
- package/docs/en/img/software1.jpg +0 -0
- package/docs/en/readme.md +128 -30
- 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 +32 -21
- 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 -830
- package/lib/groups.js +345 -345
- package/lib/json.js +59 -59
- package/lib/networkmap.js +55 -55
- package/lib/ota.js +198 -195
- package/lib/rgb.js +297 -297
- package/lib/seriallist.js +48 -48
- package/lib/states.js +6420 -6420
- package/lib/statescontroller.js +672 -693
- package/lib/tools.js +54 -54
- package/lib/utils.js +163 -163
- 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 +133 -123
- package/package.json +10 -10
- package/support/docgen.js +93 -93
- /package/admin/img/{paumann_spot.png → paulmann_spot.png} +0 -0
package/main.js
CHANGED
|
@@ -516,7 +516,7 @@ class Zigbee extends utils.Adapter {
|
|
|
516
516
|
if (!converters.length) {
|
|
517
517
|
if (type !== 'readResponse') {
|
|
518
518
|
this.log.debug(
|
|
519
|
-
`No converter available for '${mappedModel.model}' with cluster '${cluster}' and type '${type}'`
|
|
519
|
+
`No converter available for '${mappedModel.model}' '${devId}' with cluster '${cluster}' and type '${type}'`
|
|
520
520
|
);
|
|
521
521
|
}
|
|
522
522
|
return;
|
|
@@ -562,144 +562,155 @@ class Zigbee extends utils.Adapter {
|
|
|
562
562
|
|
|
563
563
|
async publishFromState(deviceId, model, stateModel, stateList, options) {
|
|
564
564
|
let isGroup = false;
|
|
565
|
+
|
|
566
|
+
this.log.debug(`publishFromState : ${deviceId} ${model}`);
|
|
565
567
|
if (model === 'group') {
|
|
566
568
|
isGroup = true;
|
|
567
569
|
deviceId = parseInt(deviceId);
|
|
568
570
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
stateList.forEach(async changedState => {
|
|
579
|
-
const stateDesc = changedState.stateDesc;
|
|
580
|
-
const value = changedState.value;
|
|
581
|
-
|
|
582
|
-
if (stateDesc.id === 'send_payload') {
|
|
583
|
-
try {
|
|
584
|
-
const json_value = JSON.parse(value);
|
|
585
|
-
const payload = {device: deviceId.replace('0x', ''), payload: json_value};
|
|
586
|
-
const result = await this.sendPayload(payload);
|
|
587
|
-
if (result.hasOwnProperty('success') && result.success) {
|
|
588
|
-
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
589
|
-
}
|
|
590
|
-
} catch (error) {
|
|
591
|
-
this.log.warn(`send_payload: ${value} does not parse as JSON Object : ${error.message}`);
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
571
|
+
try {
|
|
572
|
+
const entity = await this.zbController.resolveEntity(deviceId);
|
|
573
|
+
|
|
574
|
+
this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`);
|
|
575
|
+
|
|
576
|
+
const mappedModel = entity.mapped;
|
|
577
|
+
|
|
578
|
+
if (!mappedModel) {
|
|
579
|
+
this.log.debug(`No mapped model for ${model}`);
|
|
594
580
|
return;
|
|
595
581
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
582
|
+
|
|
583
|
+
stateList.forEach(async changedState => {
|
|
584
|
+
const stateDesc = changedState.stateDesc;
|
|
585
|
+
const value = changedState.value;
|
|
586
|
+
|
|
587
|
+
if (stateDesc.id === 'send_payload') {
|
|
588
|
+
try {
|
|
589
|
+
const json_value = JSON.parse(value);
|
|
590
|
+
const payload = {device: deviceId.replace('0x', ''), payload: json_value};
|
|
591
|
+
const result = await this.sendPayload(payload);
|
|
592
|
+
if (result.hasOwnProperty('success') && result.success) {
|
|
593
|
+
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
594
|
+
}
|
|
595
|
+
} catch (error) {
|
|
596
|
+
this.log.warn(`send_payload: ${value} does not parse as JSON Object : ${error.message}`);
|
|
608
597
|
return;
|
|
609
598
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if (stateDesc.isOption) {
|
|
603
|
+
// acknowledge state with given value
|
|
604
|
+
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
605
|
+
// process sync state list
|
|
606
|
+
//this.processSyncStatesList(deviceId, modelId, syncStateList);
|
|
607
|
+
// if this is the device query state => trigger the device query
|
|
608
|
+
|
|
609
|
+
// on activation of the 'device_query' state trigger hardware query where possible
|
|
610
|
+
if (stateDesc.id === 'device_query') {
|
|
611
|
+
if (this.query_device_block.indexOf(deviceId) > -1) {
|
|
612
|
+
this.log.warn(`Device query for '${entity.device.ieeeAddr}' blocked`);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
if (mappedModel) {
|
|
616
|
+
this.query_device_block.push(deviceId);
|
|
617
|
+
this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`);
|
|
618
|
+
for (const converter of mappedModel.toZigbee) {
|
|
619
|
+
if (converter.hasOwnProperty('convertGet')) {
|
|
620
|
+
for (const ckey of converter.key) {
|
|
621
|
+
try {
|
|
622
|
+
await converter.convertGet(entity.device.endpoints[0], ckey, {});
|
|
623
|
+
} catch (error) {
|
|
624
|
+
this.log.warn(`Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${JSON.stringify(error)}'`);
|
|
625
|
+
|
|
626
|
+
}
|
|
621
627
|
}
|
|
622
628
|
}
|
|
623
629
|
}
|
|
630
|
+
this.log.debug(`Device query for '${entity.device.ieeeAddr}' done`);
|
|
631
|
+
const idToRemove = deviceId;
|
|
632
|
+
setTimeout(() => {
|
|
633
|
+
const idx = this.query_device_block.indexOf(idToRemove);
|
|
634
|
+
if (idx > -1) {
|
|
635
|
+
this.query_device_block.splice(idx);
|
|
636
|
+
}
|
|
637
|
+
}, 10000);
|
|
624
638
|
}
|
|
625
|
-
|
|
626
|
-
const idToRemove = deviceId;
|
|
627
|
-
setTimeout(() => {
|
|
628
|
-
const idx = this.query_device_block.indexOf(idToRemove);
|
|
629
|
-
if (idx > -1) {
|
|
630
|
-
this.query_device_block.splice(idx);
|
|
631
|
-
}
|
|
632
|
-
}, 10000);
|
|
639
|
+
return;
|
|
633
640
|
}
|
|
634
641
|
return;
|
|
635
642
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
643
|
+
const converter = mappedModel.toZigbee.find(c => c && (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)));
|
|
644
|
+
if (!converter) {
|
|
645
|
+
this.log.error(`No converter available for '${model}' with key '${stateDesc.id}' `);
|
|
646
|
+
this.sendError(`No converter available for '${model}' with key '${stateDesc.id}' `);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const preparedValue = (stateDesc.setter) ? stateDesc.setter(value, options) : value;
|
|
651
|
+
const preparedOptions = (stateDesc.setterOpt) ? stateDesc.setterOpt(value, options) : {};
|
|
652
|
+
let syncStateList = [];
|
|
653
|
+
if (stateModel && stateModel.syncStates) {
|
|
654
|
+
stateModel.syncStates.forEach(syncFunct => {
|
|
655
|
+
const res = syncFunct(stateDesc, value, options);
|
|
656
|
+
if (res) {
|
|
657
|
+
syncStateList = syncStateList.concat(res);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
|
|
663
|
+
const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
|
|
664
|
+
this.log.debug(`convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)}`);
|
|
665
|
+
|
|
666
|
+
let target;
|
|
667
|
+
if (model === 'group') {
|
|
668
|
+
target = entity.mapped;
|
|
669
|
+
} else {
|
|
670
|
+
target = await this.zbController.resolveEntity(deviceId, epName);
|
|
671
|
+
target = target.endpoint;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
this.log.debug(`target: ${safeJsonStringify(target)}`);
|
|
675
|
+
|
|
676
|
+
const meta = {
|
|
677
|
+
endpoint_name: epName,
|
|
678
|
+
options: preparedOptions,
|
|
679
|
+
device: entity.device,
|
|
680
|
+
mapped: model === 'group' ? [] : mappedModel,
|
|
681
|
+
message: {[key]: preparedValue},
|
|
682
|
+
logger: this.log,
|
|
683
|
+
state: {},
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
if (preparedOptions.hasOwnProperty('state')) {
|
|
687
|
+
meta.state = preparedOptions.state;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
try {
|
|
691
|
+
const result = await converter.convertSet(target, key, preparedValue, meta);
|
|
692
|
+
this.log.debug(`convert result ${safeJsonStringify(result)}`);
|
|
693
|
+
if (result !== undefined) {
|
|
694
|
+
if (stateModel && !isGroup) {
|
|
695
|
+
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
696
|
+
}
|
|
697
|
+
// process sync state list
|
|
698
|
+
this.processSyncStatesList(deviceId, model, syncStateList);
|
|
699
|
+
|
|
700
|
+
if (isGroup) {
|
|
701
|
+
await this.callPluginMethod('queryGroupMemberState', [deviceId, stateDesc]);
|
|
702
|
+
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
703
|
+
}
|
|
696
704
|
}
|
|
705
|
+
|
|
706
|
+
} catch (error) {
|
|
707
|
+
this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
|
|
708
|
+
` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
|
|
697
709
|
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
});
|
|
710
|
+
});
|
|
711
|
+
} catch (err) {
|
|
712
|
+
this.log.error(`No entity for ${deviceId}`);
|
|
713
|
+
}
|
|
703
714
|
}
|
|
704
715
|
|
|
705
716
|
// This function is introduced to explicitly allow user level scripts to send Commands
|
|
@@ -917,7 +928,6 @@ class Zigbee extends utils.Adapter {
|
|
|
917
928
|
if (Number.isInteger(data)) {
|
|
918
929
|
_pairingMode = true;
|
|
919
930
|
this.setState('info.pairingCountdown', data, true);
|
|
920
|
-
_pairingMode = true;
|
|
921
931
|
}
|
|
922
932
|
if (data === 0) {
|
|
923
933
|
// set pairing mode off
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.13",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"serialport": "^10.5.0"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@iobroker/adapter-core": "^2.6.
|
|
25
|
-
"tar": "^6.1.
|
|
26
|
-
"typescript": "^
|
|
27
|
-
"zigbee-herdsman": "0.
|
|
28
|
-
"zigbee-herdsman-converters": "15.
|
|
24
|
+
"@iobroker/adapter-core": "^2.6.8",
|
|
25
|
+
"tar": "^6.1.15",
|
|
26
|
+
"typescript": "^5.1.6",
|
|
27
|
+
"zigbee-herdsman": "0.16.0",
|
|
28
|
+
"zigbee-herdsman-converters": "15.35.1"
|
|
29
29
|
},
|
|
30
30
|
"description": "Zigbee devices",
|
|
31
31
|
"devDependencies": {
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"@alcalzone/release-script-plugin-iobroker": "^3.5.9",
|
|
34
34
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
35
35
|
"@iobroker/testing": "^4.1.0",
|
|
36
|
-
"axios": "^1.
|
|
36
|
+
"axios": "^1.3.4",
|
|
37
37
|
"chai": "^4.3.7",
|
|
38
38
|
"chai-as-promised": "^7.1.1",
|
|
39
|
-
"eslint": "^8.
|
|
40
|
-
"eslint-config-prettier": "^8.
|
|
39
|
+
"eslint": "^8.44.0",
|
|
40
|
+
"eslint-config-prettier": "^8.8.0",
|
|
41
41
|
"eslint-plugin-prettier": "^4.2.1",
|
|
42
42
|
"gulp": "^4.0.2",
|
|
43
43
|
"gulp-jsdoc3": "^3.0.0",
|
|
44
|
-
"gulp-replace": "^1.1.
|
|
44
|
+
"gulp-replace": "^1.1.4",
|
|
45
45
|
"mixin-deep": "^2.0.1",
|
|
46
46
|
"mocha": "^10.2.0"
|
|
47
47
|
},
|
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);
|
|
File without changes
|