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.
Files changed (60) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +417 -414
  3. package/admin/adapter-settings.js +244 -244
  4. package/admin/admin.js +2981 -2981
  5. package/admin/i18n/de/translations.json +108 -108
  6. package/admin/i18n/en/translations.json +108 -108
  7. package/admin/i18n/es/translations.json +102 -102
  8. package/admin/i18n/fr/translations.json +108 -108
  9. package/admin/i18n/it/translations.json +102 -102
  10. package/admin/i18n/nl/translations.json +108 -108
  11. package/admin/i18n/pl/translations.json +108 -108
  12. package/admin/i18n/pt/translations.json +102 -102
  13. package/admin/i18n/ru/translations.json +108 -108
  14. package/admin/i18n/uk/translations.json +108 -108
  15. package/admin/i18n/zh-cn/translations.json +102 -102
  16. package/admin/img/philips_hue_lom001.png +0 -0
  17. package/admin/index.html +159 -159
  18. package/admin/index_m.html +1356 -1356
  19. package/admin/moment.min.js +1 -1
  20. package/admin/shuffle.min.js +2 -2
  21. package/admin/tab_m.html +1009 -1009
  22. package/admin/vis-network.min.css +1 -1
  23. package/admin/vis-network.min.js +27 -27
  24. package/admin/words.js +110 -110
  25. package/docs/de/basedocu.md +19 -19
  26. package/docs/de/readme.md +126 -126
  27. package/docs/en/readme.md +128 -128
  28. package/docs/flashing_via_arduino_(en).md +110 -110
  29. package/docs/ru/readme.md +28 -28
  30. package/docs/tutorial/groups-1.png +0 -0
  31. package/docs/tutorial/groups-2.png +0 -0
  32. package/docs/tutorial/tab-dev-1.png +0 -0
  33. package/io-package.json +14 -14
  34. package/lib/backup.js +171 -171
  35. package/lib/binding.js +319 -319
  36. package/lib/colors.js +465 -465
  37. package/lib/commands.js +534 -534
  38. package/lib/developer.js +145 -145
  39. package/lib/devices.js +3135 -3135
  40. package/lib/exclude.js +162 -162
  41. package/lib/exposes.js +913 -913
  42. package/lib/groups.js +345 -345
  43. package/lib/json.js +59 -59
  44. package/lib/networkmap.js +55 -55
  45. package/lib/ota.js +198 -198
  46. package/lib/rgb.js +297 -297
  47. package/lib/seriallist.js +48 -48
  48. package/lib/states.js +6420 -6420
  49. package/lib/statescontroller.js +672 -672
  50. package/lib/tools.js +54 -54
  51. package/lib/utils.js +165 -165
  52. package/lib/zbBaseExtension.js +36 -36
  53. package/lib/zbDelayedAction.js +144 -144
  54. package/lib/zbDeviceAvailability.js +319 -319
  55. package/lib/zbDeviceConfigure.js +147 -147
  56. package/lib/zbDeviceEvent.js +48 -48
  57. package/lib/zigbeecontroller.js +989 -989
  58. package/main.js +94 -75
  59. package/package.json +2 -2
  60. 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 voltage = 0;
471
- let battKey = false;
472
-
473
- if (mappedModel !== null && mappedModel !== undefined) {
474
- if (mappedModel.meta !== undefined && mappedModel.meta !== null) {
475
- if (mappedModel.meta.battery !== undefined) {
476
- const isVoltage = entity.mapped.meta.battery.hasOwnProperty('voltageToPercentage');
477
-
478
- if (isVoltage) {
479
- const keys = Object.keys(message.data);
480
-
481
- for (const key of keys) {
482
- const value = message.data[key];
483
-
484
- this.log.debug(`--> BatteryValue ${safeJsonStringify(value)} from battery search`);
485
-
486
- if (value != undefined && value[1] != undefined) {
487
- if (key == 65282 && value[1][1] != undefined) {
488
- voltage = value[1][1].elmVal;
489
- battKey = true;
490
- break;
491
- }
492
- if (key == 65281) {
493
- voltage = value[1];
494
- battKey = true;
495
- break;
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 (battKey) {
508
- this.publishToState(devId, model, {voltage: voltage});
509
- const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(voltage,entity.mapped.meta.battery.voltageToPercentage);
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
- let payload = {};
544
-
545
- const publish = (_payload) => {
546
- if (_payload) {
547
- this.publishToState(devId, model, _payload);
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
- this.stController.collectOptions(devId, model, (options) => {
553
- try {
554
- payload = converter.convert(mappedModel, message, publish, options, meta);
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.22",
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.54.0"
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} | ![${brand.pathImg}](${icon}) |\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} | ![${brand.pathImg}](${icon}) |\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);