iobroker.zigbee 1.8.18 → 1.8.20
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 +421 -415
- 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 +27 -9
- 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 +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 +65 -37
- package/package.json +6 -4
- package/support/docgen.js +93 -93
package/main.js
CHANGED
|
@@ -13,6 +13,8 @@ try {
|
|
|
13
13
|
}
|
|
14
14
|
const originalLogMethod = debug.log;
|
|
15
15
|
|
|
16
|
+
const zigbeeHerdsmanConvertersUtils = require('zigbee-herdsman-converters/lib/utils');
|
|
17
|
+
|
|
16
18
|
const safeJsonStringify = require('./lib/json');
|
|
17
19
|
const fs = require('fs');
|
|
18
20
|
const path = require('path');
|
|
@@ -271,30 +273,6 @@ class Zigbee extends utils.Adapter {
|
|
|
271
273
|
|
|
272
274
|
}
|
|
273
275
|
}
|
|
274
|
-
|
|
275
|
-
/* if (this.config.external === undefined) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const extfiles = this.config.external.split(';');
|
|
279
|
-
for (const moduleName of extfiles) {
|
|
280
|
-
if (!moduleName) continue;
|
|
281
|
-
this.log.info(`Apply converter from module: ${moduleName}`);
|
|
282
|
-
const sandbox = {
|
|
283
|
-
require,
|
|
284
|
-
module: {},
|
|
285
|
-
};
|
|
286
|
-
const converterCode = fs.readFileSync(moduleName, {encoding: 'utf8'});
|
|
287
|
-
vm.runInNewContext(converterCode, sandbox);
|
|
288
|
-
const converter = sandbox.module.exports;
|
|
289
|
-
if (Array.isArray(converter)) {
|
|
290
|
-
for (const item of converter) {
|
|
291
|
-
yield item;
|
|
292
|
-
}
|
|
293
|
-
} else {
|
|
294
|
-
yield converter;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
*/
|
|
298
276
|
}
|
|
299
277
|
|
|
300
278
|
applyExternalConverters() {
|
|
@@ -483,6 +461,7 @@ class Zigbee extends utils.Adapter {
|
|
|
483
461
|
|
|
484
462
|
async onZigbeeEvent(type, entity, message) {
|
|
485
463
|
this.log.debug(`Type ${type} device ${safeJsonStringify(entity)} incoming event: ${safeJsonStringify(message)}`);
|
|
464
|
+
|
|
486
465
|
const device = entity.device;
|
|
487
466
|
const mappedModel = entity.mapped;
|
|
488
467
|
const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
|
|
@@ -493,25 +472,65 @@ class Zigbee extends utils.Adapter {
|
|
|
493
472
|
// this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
|
|
494
473
|
meta.logger = this.log;
|
|
495
474
|
|
|
496
|
-
await this.checkIfModelUpdate(entity);
|
|
497
|
-
|
|
498
|
-
|
|
475
|
+
await this.checkIfModelUpdate(entity);
|
|
476
|
+
|
|
477
|
+
let voltage = 0;
|
|
478
|
+
let battKey = false;
|
|
479
|
+
|
|
480
|
+
if (mappedModel.meta != undefined && mappedModel.meta.battery != undefined) {
|
|
481
|
+
const isVoltage = entity.mapped.meta.battery.hasOwnProperty('voltageToPercentage');
|
|
482
|
+
|
|
483
|
+
if (isVoltage) {
|
|
484
|
+
const keys = Object.keys(message.data);
|
|
485
|
+
|
|
486
|
+
for (const key of keys) {
|
|
487
|
+
const value = message.data[key];
|
|
488
|
+
|
|
489
|
+
this.log.debug(`--> BatteryValue ${safeJsonStringify(value)} from battery search`);
|
|
490
|
+
|
|
491
|
+
if (value != undefined && value[1] != undefined) {
|
|
492
|
+
if (key == 65282 && value[1][1] != undefined) {
|
|
493
|
+
voltage = value[1][1].elmVal;
|
|
494
|
+
battKey = true;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
if (key == 65281) {
|
|
498
|
+
voltage = value[1];
|
|
499
|
+
battKey = true;
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// always publish link_quality and battery
|
|
508
|
+
if (message.linkquality) { // send battery with
|
|
499
509
|
this.publishToState(devId, model, {linkquality: message.linkquality});
|
|
510
|
+
if (battKey) {
|
|
511
|
+
this.publishToState(devId, model, {voltage: voltage});
|
|
512
|
+
const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(voltage,entity.mapped.meta.battery.voltageToPercentage);
|
|
513
|
+
this.publishToState(devId, model, {battery: battProz});
|
|
514
|
+
}
|
|
500
515
|
}
|
|
516
|
+
|
|
501
517
|
// publish raw event to "from_zigbee"
|
|
502
518
|
// some cleanup
|
|
503
519
|
const msgForState = Object.assign({}, message);
|
|
504
520
|
delete msgForState['device'];
|
|
505
521
|
delete msgForState['endpoint'];
|
|
522
|
+
|
|
506
523
|
msgForState['endpoint_id'] = message.endpoint.ID;
|
|
507
524
|
this.publishToState(devId, model, {msg_from_zigbee: safeJsonStringify(msgForState)});
|
|
508
525
|
|
|
509
526
|
if (!entity.mapped) {
|
|
510
527
|
return;
|
|
511
528
|
}
|
|
529
|
+
|
|
512
530
|
let converters = mappedModel.fromZigbee.filter(c => c && c.cluster === cluster && (
|
|
513
531
|
(c.type instanceof Array) ? c.type.includes(type) : c.type === type));
|
|
514
532
|
|
|
533
|
+
|
|
515
534
|
if (!converters.length && type === 'readResponse') {
|
|
516
535
|
converters = mappedModel.fromZigbee.filter(c => c.cluster === cluster && (
|
|
517
536
|
(c.type instanceof Array) ? c.type.includes('attributeReport') : c.type === 'attributeReport'));
|
|
@@ -519,24 +538,33 @@ class Zigbee extends utils.Adapter {
|
|
|
519
538
|
|
|
520
539
|
if (!converters.length) {
|
|
521
540
|
if (type !== 'readResponse') {
|
|
522
|
-
this.log.debug(`No converter available for '${mappedModel.model}' '${devId}' with cluster '${cluster}' and type '${type}'`
|
|
523
|
-
);
|
|
541
|
+
this.log.debug(`No converter available for '${mappedModel.model}' '${devId}' with cluster '${cluster}' and type '${type}'`);
|
|
524
542
|
}
|
|
525
543
|
return;
|
|
526
544
|
}
|
|
527
545
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
546
|
+
let payload = {};
|
|
547
|
+
|
|
548
|
+
const publish = (_payload) => {
|
|
549
|
+
if (_payload) {
|
|
550
|
+
this.publishToState(devId, model, _payload);
|
|
532
551
|
}
|
|
533
552
|
};
|
|
534
553
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
554
|
+
try {
|
|
555
|
+
for (const converter of converters) {
|
|
556
|
+
this.stController.collectOptions(devId, model, (options) => {
|
|
557
|
+
payload = converter.convert(mappedModel, message, publish, options, meta);
|
|
558
|
+
|
|
559
|
+
if (payload) {
|
|
560
|
+
if (Object.keys(payload).length) {
|
|
561
|
+
publish(payload);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
});
|
|
539
565
|
}
|
|
566
|
+
} catch (err) {
|
|
567
|
+
this.log.error(`convert problem with '${model}' '${devId}' `);
|
|
540
568
|
}
|
|
541
569
|
}
|
|
542
570
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.20",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -25,13 +25,14 @@
|
|
|
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.49.0"
|
|
29
29
|
},
|
|
30
30
|
"description": "Zigbee devices",
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@alcalzone/release-script": "^3.
|
|
33
|
-
"@alcalzone/release-script-plugin-iobroker": "^3.
|
|
32
|
+
"@alcalzone/release-script": "^3.6.0",
|
|
33
|
+
"@alcalzone/release-script-plugin-iobroker": "^3.6.0",
|
|
34
34
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
35
|
+
"@alcalzone/release-script-plugin-manual-review": "^3.5.9",
|
|
35
36
|
"@iobroker/testing": "^4.1.0",
|
|
36
37
|
"axios": "^1.3.4",
|
|
37
38
|
"chai": "^4.3.7",
|
|
@@ -83,6 +84,7 @@
|
|
|
83
84
|
"test:integration": "mocha test/integration --exit",
|
|
84
85
|
"watch:parcel": "parcel admin/src/index.tsx -d admin/build --hmr-port 1235",
|
|
85
86
|
"test:js": "mocha --opts test/mocha.custom.opts",
|
|
87
|
+
"lint": "eslint .",
|
|
86
88
|
"release": "release-script",
|
|
87
89
|
"release-patch": "release-script patch --yes --no-update-lockfile",
|
|
88
90
|
"release-minor": "release-script minor --yes --no-update-lockfile",
|
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);
|