iobroker.zigbee 1.7.5 → 1.8.0

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 (50) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +22 -29
  3. package/admin/admin.js +494 -469
  4. package/admin/i18n/de/translations.json +108 -0
  5. package/admin/i18n/en/translations.json +108 -0
  6. package/admin/i18n/es/translations.json +102 -0
  7. package/admin/i18n/fr/translations.json +108 -0
  8. package/admin/i18n/it/translations.json +102 -0
  9. package/admin/i18n/nl/translations.json +108 -0
  10. package/admin/i18n/pl/translations.json +108 -0
  11. package/admin/i18n/pt/translations.json +102 -0
  12. package/admin/i18n/ru/translations.json +108 -0
  13. package/admin/i18n/uk/translations.json +108 -0
  14. package/admin/i18n/zh-cn/translations.json +102 -0
  15. package/admin/index_m.html +1 -1
  16. package/admin/tab_m.html +44 -3
  17. package/admin/words.js +107 -108
  18. package/io-package.json +326 -357
  19. package/lib/backup.js +2 -2
  20. package/lib/binding.js +23 -24
  21. package/lib/colors.js +16 -14
  22. package/lib/commands.js +89 -82
  23. package/lib/developer.js +6 -7
  24. package/lib/devices.js +145 -154
  25. package/lib/exclude.js +30 -36
  26. package/lib/exposes.js +106 -111
  27. package/lib/groups.js +53 -54
  28. package/lib/json.js +3 -4
  29. package/lib/networkmap.js +2 -2
  30. package/lib/ota.js +23 -15
  31. package/lib/rgb.js +47 -44
  32. package/lib/seriallist.js +21 -10
  33. package/lib/states.js +488 -498
  34. package/lib/statescontroller.js +170 -164
  35. package/lib/utils.js +22 -21
  36. package/lib/zbBaseExtension.js +4 -4
  37. package/lib/zbDelayedAction.js +5 -13
  38. package/lib/zbDeviceAvailability.js +47 -44
  39. package/lib/zbDeviceConfigure.js +18 -23
  40. package/lib/zbDeviceEvent.js +3 -4
  41. package/lib/zigbeecontroller.js +97 -100
  42. package/main.js +149 -133
  43. package/package.json +33 -19
  44. package/.eslintignore +0 -2
  45. package/.eslintrc.json +0 -37
  46. package/.github/FUNDING.yml +0 -3
  47. package/.github/stale.yml +0 -13
  48. package/.github/workflows/test-and-release.yml +0 -151
  49. package/.travis/wiki.sh +0 -28
  50. package/admin/adapter-settings.js +0 -244
@@ -19,7 +19,7 @@ const groupConverters = [
19
19
  zigbeeHerdsmanConverters.toZigbeeConverters.light_brightness_step,
20
20
  zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_move,
21
21
  zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_step,
22
- zigbeeHerdsmanConverters.toZigbeeConverters.ight_colortemp_startup
22
+ zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp_startup
23
23
  ];
24
24
 
25
25
  function isFunction(functionToCheck) {
@@ -118,13 +118,12 @@ class ZigbeeController extends EventEmitter {
118
118
  }
119
119
 
120
120
  this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
121
-
122
121
  } catch (e) {
123
122
  this.sendError(e);
124
- this.error('Starting zigbee-herdsman problem : ' + JSON.stringify(e.message));
123
+ this.error(`Starting zigbee-herdsman problem : ${JSON.stringify(e.message)}`);
125
124
  throw 'Error herdsman start';
126
125
  }
127
- // Check if we have to turn off the led
126
+ // Check if we have to turn off the LED
128
127
  try {
129
128
  if (this.disableLed) {
130
129
  this.info('Disable LED');
@@ -141,7 +140,7 @@ class ZigbeeController extends EventEmitter {
141
140
  let powerText = 'normal';
142
141
 
143
142
  if (this.transmitPower != '0') {
144
- switch(this.transmitPower) {
143
+ switch (this.transmitPower) {
145
144
  case '-22':
146
145
  powerText = 'low';
147
146
  break;
@@ -157,7 +156,7 @@ class ZigbeeController extends EventEmitter {
157
156
  }
158
157
 
159
158
 
160
- this.info(' --> transmitPower : ' + powerText);
159
+ this.info(` --> transmitPower : ${powerText}`);
161
160
  try {
162
161
  await this.herdsman.setTransmitPower(this.transmitPower);
163
162
  } catch (e) {
@@ -165,7 +164,6 @@ class ZigbeeController extends EventEmitter {
165
164
  this.info('Unable to set transmit power, unsupported function.');
166
165
  }
167
166
 
168
-
169
167
  // Call extensions
170
168
  this.callExtensionMethod('onZigbeeStarted', []);
171
169
 
@@ -176,20 +174,21 @@ class ZigbeeController extends EventEmitter {
176
174
  } else {
177
175
  this.info(`Currently no devices.`);
178
176
  }
177
+
179
178
  for (const device of devices) {
180
179
  const entity = await this.resolveEntity(device);
181
- this.adapter.getObject(device.ieeeAddr.substr(2),(err, obj) => {
182
- if (obj && obj.common && obj.common.deactivated)
183
- {
180
+ this.adapter.getObject(device.ieeeAddr.substr(2), (err, obj) => {
181
+ if (obj && obj.common && obj.common.deactivated) {
184
182
  this.callExtensionMethod('deregisterDevicePing', [device, entity]);
185
- }
186
- else {
183
+ } else {
187
184
  this.callExtensionMethod('registerDevicePing', [device, entity]);
188
185
  }
189
186
  });
190
187
  // ensure that objects for all found clients are present
191
188
 
192
- if (entity.mapped) this.emit('new', entity);
189
+ if (entity.mapped) {
190
+ this.emit('new', entity);
191
+ }
193
192
  this.info(
194
193
  (entity.device.ieeeAddr) +
195
194
  ` (addr ${entity.device.networkAddress}): ` +
@@ -261,8 +260,7 @@ class ZigbeeController extends EventEmitter {
261
260
 
262
261
  async getGroups() {
263
262
  try {
264
- const rv = await this.herdsman.getGroups();
265
- return rv;
263
+ return await this.herdsman.getGroups();
266
264
  } catch (error) {
267
265
  this.sendError(error);
268
266
  this.error(JSON.stringify(error));
@@ -271,12 +269,12 @@ class ZigbeeController extends EventEmitter {
271
269
  }
272
270
 
273
271
  async removeGroupById(id) {
274
- const group = await this.getGroupByID(id);
272
+ const group = await this.getGroupByID(id);
275
273
  try {
276
- if (group) group.removeFromDatabase();
274
+ group && group.removeFromDatabase();
277
275
  } catch (error) {
278
276
  this.sendError(error);
279
- this.error('error in removeGroupById: ' + error);
277
+ this.error(`error in removeGroupById: ${error}`);
280
278
  }
281
279
  }
282
280
 
@@ -290,16 +288,15 @@ class ZigbeeController extends EventEmitter {
290
288
  }
291
289
 
292
290
  async verifyGroupExists(id) {
293
- const nid = (typeof(id) === 'number' ? id:parseInt(id));
291
+ const nid = (typeof (id) === 'number' ? id : parseInt(id));
294
292
  let group = await this.herdsman.getGroupByID(nid);
295
293
  if (!group) {
296
294
  group = await this.herdsman.createGroup(nid);
297
295
  group.toZigbee = groupConverters;
298
296
  group.model = 'group';
299
- this.debug('verifyGroupExists: created group ' + nid);
300
- }
301
- else {
302
- this.debug('verifyGroupExists: group ' + nid + ' exists');
297
+ this.debug(`verifyGroupExists: created group ${nid}`);
298
+ } else {
299
+ this.debug(`verifyGroupExists: group ${nid} exists`);
303
300
  }
304
301
 
305
302
  }
@@ -316,15 +313,17 @@ class ZigbeeController extends EventEmitter {
316
313
  const device = this.getDeviceByNetworkAddress(nwk);
317
314
  if (device && device.ieeeAddr) members.push( { ieee:device.ieeeAddr, model:device.modelID, epid:epid, ep:member } );
318
315
  }
319
- }
320
- else {
316
+ } else {
321
317
  return undefined;
322
318
  }
323
319
 
324
320
  } catch (error) {
325
321
  this.sendError(error);
326
- if (error) this.error('getGroupMembersFromController: error is ' + JSON.stringify(error) + ' ' + JSON.stringify(new Error().stack));
327
- else this.error('unidentifed error in getGroupMembersFromController');
322
+ if (error) {
323
+ this.error(`getGroupMembersFromController: error is ${JSON.stringify(error)} ${JSON.stringify(new Error().stack)}`);
324
+ } else {
325
+ this.error('unidentified error in getGroupMembersFromController');
326
+ }
328
327
  }
329
328
  return members;
330
329
  }
@@ -404,7 +403,7 @@ class ZigbeeController extends EventEmitter {
404
403
  }
405
404
  }
406
405
 
407
- async incMsgHandler(message){
406
+ async incMsgHandler(message) {
408
407
  this.debug('incoming msg', message);
409
408
  const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr);
410
409
  if (!device) {
@@ -462,8 +461,8 @@ class ZigbeeController extends EventEmitter {
462
461
  } else {
463
462
  this.info('Zigbee: disabling joining new devices.');
464
463
  }
465
- try
466
- {
464
+
465
+ try {
467
466
  if (permitTime && !this.herdsman.getPermitJoin()) {
468
467
  clearInterval(this._permitJoinInterval);
469
468
  this._permitJoinTime = permitTime;
@@ -509,6 +508,7 @@ class ZigbeeController extends EventEmitter {
509
508
  this.debug(`Force remove`);
510
509
  }
511
510
  }
511
+
512
512
  try {
513
513
  await device.removeFromDatabase();
514
514
  } catch (error) {
@@ -518,7 +518,7 @@ class ZigbeeController extends EventEmitter {
518
518
  this.debug(`Failed to remove from DB ${error.stack}`);
519
519
  }
520
520
  this.debug('Remove successful.');
521
- if (callback) callback();
521
+ callback && callback();
522
522
  this.callExtensionMethod(
523
523
  'onDeviceRemove',
524
524
  [device],
@@ -527,7 +527,7 @@ class ZigbeeController extends EventEmitter {
527
527
  } catch (error) {
528
528
  this.sendError(error);
529
529
  this.error(`Failed to remove ${error.stack}`);
530
- if (callback) callback(`Failed to remove ${error.stack}`);
530
+ callback && callback(`Failed to remove ${error.stack}`);
531
531
  }
532
532
  }
533
533
 
@@ -536,7 +536,7 @@ class ZigbeeController extends EventEmitter {
536
536
  try {
537
537
  this.debug('handleDeviceLeave', message);
538
538
  const entity = await this.resolveEntity(message.device || message.ieeeAddr);
539
- const friendlyName = (entity) ? entity.name : message.ieeeAddr;
539
+ const friendlyName = entity ? entity.name : message.ieeeAddr;
540
540
  this.debug(`Device '${friendlyName}' left the network`);
541
541
  this.emit('leave', message.ieeeAddr);
542
542
  // Call extensions
@@ -556,10 +556,15 @@ class ZigbeeController extends EventEmitter {
556
556
  const friendlyName = entity.name;
557
557
  this.warn(`Device '${friendlyName}' announced itself`);
558
558
 
559
- if (entity && entity.mapped) {
560
- this.callExtensionMethod(
561
- 'onZigbeeEvent',
562
- [ {'device': message.device, 'type': 'deviceAnnounce'}, (entity ? entity.mapped : null)]);
559
+ try {
560
+ if (entity && entity.mapped) {
561
+ this.callExtensionMethod(
562
+ 'onZigbeeEvent',
563
+ [ {'device': message.device, 'type': 'deviceAnnounce'}, (entity ? entity.mapped : null)]);
564
+ }
565
+ } catch (error) {
566
+ this.sendError(error);
567
+ this.error(`Failed to handleDeviceLeave ${error.stack}`);
563
568
  }
564
569
 
565
570
  this.emit('pairing', `Device '${friendlyName}' announced itself`);
@@ -645,12 +650,11 @@ class ZigbeeController extends EventEmitter {
645
650
 
646
651
  async getMap(callback) {
647
652
  try {
648
-
649
653
  const devices = this.herdsman.getDevices(true);
650
654
  const lqis = [];
651
655
  const routing = [];
652
656
 
653
- for (const device of devices.filter((d) => d.type != 'EndDevice')) {
657
+ for (const device of devices.filter((d) => d.type !== 'EndDevice')) {
654
658
  const resolved = await this.resolveEntity(device);
655
659
  let result;
656
660
 
@@ -674,7 +678,7 @@ class ZigbeeController extends EventEmitter {
674
678
 
675
679
  if (result !== undefined) {
676
680
  for (const dev of result.neighbors) {
677
- if (dev.ieeeAddr !== '0xffffffffffffffff' && dev !== undefined) {
681
+ if (dev !== undefined && dev.ieeeAddr !== '0xffffffffffffffff') {
678
682
  lqis.push({
679
683
  parent: resolved.device.ieeeAddr,
680
684
  networkAddress: dev.networkAddress,
@@ -682,7 +686,7 @@ class ZigbeeController extends EventEmitter {
682
686
  lqi: dev.linkquality,
683
687
  relationship: dev.relationship,
684
688
  depth: dev.depth,
685
- status: (dev.linkquality > 0) ? 'online' : 'offline',
689
+ status: dev.linkquality > 0 ? 'online' : 'offline',
686
690
  });
687
691
  }
688
692
  }
@@ -713,11 +717,10 @@ class ZigbeeController extends EventEmitter {
713
717
  }
714
718
  }
715
719
  this.debug(`Routing table succeeded for '${resolved.name}'`);
716
-
717
720
  }
718
721
  this.debug(`Get map succeeded ${safeJsonStringify(lqis)}`);
719
722
 
720
- if (callback) callback({lqis: lqis, routing: routing});
723
+ callback && callback({lqis, routing});
721
724
  } catch (error) {
722
725
  this.sendError(error);
723
726
  this.debug(`Failed to get map: ${safeJsonStringify(error.stack)}`);
@@ -750,7 +753,7 @@ class ZigbeeController extends EventEmitter {
750
753
  if (type === 'foundation') {
751
754
  cfg.disableDefaultResponse = true;
752
755
  if (cmd === 'read' && !Array.isArray(zclData)) {
753
- // needs to be iterateable (string[] | number [])
756
+ // needs to be iterable (string[] | number [])
754
757
  zclData[Symbol.iterator] = function* () {
755
758
  let k;
756
759
  for (k in this) {
@@ -764,17 +767,15 @@ class ZigbeeController extends EventEmitter {
764
767
  } else {
765
768
  result = await endpoint[cmd](cid, zclData, cfg);
766
769
  }
767
- if (callback) callback(undefined, result);
768
- }
769
- else if(type === 'functionalResp'){
770
- cfg.disableDefaultResponse = false;
771
- const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
772
- if (callback) callback(undefined, result);
773
- }
774
- else {
770
+ callback && callback(undefined, result);
771
+ } else if (type === 'functionalResp') {
772
+ cfg.disableDefaultResponse = false;
773
+ const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
774
+ callback && callback(undefined, result);
775
+ } else {
775
776
  cfg.disableDefaultResponse = false;
776
777
  const result = await endpoint.command(cid, cmd, zclData, cfg);
777
- if (callback) callback(undefined, result);
778
+ callback && callback(undefined, result);
778
779
  }
779
780
  }
780
781
 
@@ -785,66 +786,61 @@ class ZigbeeController extends EventEmitter {
785
786
  this.debug(`addDevFromGroup - entity: ${safeJsonStringify(entity)}`);
786
787
  this.debug(`addDevFromGroup - group: ${safeJsonStringify(group)}`);
787
788
  if (epid != undefined) {
788
- for (const ep of entity.endpoints) {
789
- if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
790
- {
791
- this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`)
792
- await(ep.addToGroup(group.mapped));
789
+ for (const ep of entity.endpoints) {
790
+ if (ep.ID === epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
791
+ this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`);
792
+ await (ep.addToGroup(group.mapped));
793
+ }
793
794
  }
794
- }
795
795
 
796
- }
797
- else
798
- {
799
- if (entity.endpoint.inputClusters.includes(4))
800
- {
801
- this.debug(`adding endpoint ${entity.endpoint.ID} to group`)
796
+ } else {
797
+ if (entity.endpoint.inputClusters.includes(4)) {
798
+ this.debug(`adding endpoint ${entity.endpoint.ID} to group`);
802
799
  await entity.endpoint.addToGroup(group.mapped);
803
- }
804
- else {
800
+ } else {
805
801
  let added = false;
806
- for (const ep of entity.endpoints)
807
- {
808
- if (ep.inputClusters.includes(4))
809
- {
810
- this.debug(`adding endpoint ${ep.ID} to group`)
802
+ for (const ep of entity.endpoints) {
803
+ if (ep.inputClusters.includes(4)) {
804
+ this.debug(`adding endpoint ${ep.ID} to group`);
811
805
  await ep.addToGroup(group.mapped);
812
806
  added = true;
813
807
  break;
814
808
  }
815
809
  }
816
- if (!added) throw ('cluster genGroups not supported');
810
+ if (!added) {
811
+ throw ('cluster genGroups not supported');
812
+ }
817
813
  }
818
814
  }
819
815
  } catch (error) {
820
816
  this.sendError(error);
821
817
  this.error(`Exception when trying to Add ${devId} to group ${groupId}`, error);
822
- return { error:`Failed to add ${devId} to group ${groupId}: ${JSON.stringify(error)}` };
818
+ return {error: `Failed to add ${devId} to group ${groupId}: ${JSON.stringify(error)}`};
823
819
  }
824
820
  return {};
825
821
  }
826
822
 
827
823
  async removeDevFromGroup(devId, groupId, epid) {
828
- try {
829
- const entity = await this.resolveEntity(devId);
830
- const group = await this.resolveEntity(groupId);
831
- this.debug(`removeDevFromGroup - entity: ${safeJsonStringify(entity)}`);
832
- this.debug(`removeDevFromGroup - group: ${safeJsonStringify(group)}`);
833
- if (epid != undefined) {
834
- for (const ep of entity.endpoints) {
835
- if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
836
- {
837
- this.debug(`removing endpoint ${ep.ID} (${epid}) group ${groupId}`)
838
- await(ep.removeFromGroup(group.mapped))
839
- }
840
- }
841
- } else await entity.endpoint.removeFromGroup(group.mapped);
842
- } catch (error) {
843
- this.sendError(error);
844
- this.error(`Exception when trying remove ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`, error);
845
- return { error: `Failed to remove dev ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`};
846
- }
847
- return {};
824
+ let entity;
825
+ try {
826
+ entity = await this.resolveEntity(devId);
827
+ const group = await this.resolveEntity(groupId);
828
+ this.debug(`removeDevFromGroup - entity: ${safeJsonStringify(entity)}`);
829
+ this.debug(`removeDevFromGroup - group: ${safeJsonStringify(group)}`);
830
+ if (epid != undefined) {
831
+ for (const ep of entity.endpoints) {
832
+ if (ep.ID === epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
833
+ this.debug(`removing endpoint ${ep.ID} (${epid}) group ${groupId}`);
834
+ await ep.removeFromGroup(group.mapped);
835
+ }
836
+ }
837
+ } else await entity.endpoint.removeFromGroup(group.mapped);
838
+ } catch (error) {
839
+ this.sendError(error);
840
+ this.error(`Exception when trying remove ${devId} (ep ${epid ? epid : (entity ? entity.endpoint.ID : '')}) from group ${devId}`, error);
841
+ return {error: `Failed to remove dev ${devId} (ep ${epid ? epid : (entity ? entity.endpoint.ID : '')}) from group ${devId}`};
842
+ }
843
+ return {};
848
844
  }
849
845
 
850
846
  async removeDevFromAllGroups(devId) {
@@ -852,14 +848,15 @@ class ZigbeeController extends EventEmitter {
852
848
  const entity = await this.resolveEntity(devId);
853
849
  this.debug(`entity: ${safeJsonStringify(entity)}`);
854
850
  for (const ep of entity.endpoints) {
855
- if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))
856
- await ep.removefromAllGroups();
851
+ if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)) {
852
+ await ep.removefromAllGroups();
853
+ }
857
854
  }
858
855
  //await entity.endpoint.removeFromAllGroups();
859
856
  } catch (error) {
860
857
  this.sendError(error);
861
858
  this.error(`Exception when trying remove ${devId} from all groups`, error);
862
- return { error: `Failed to remove dev ${devId} from all groups: ${error}`};
859
+ return {error: `Failed to remove dev ${devId} from all groups: ${error}`};
863
860
  }
864
861
  return {};
865
862
  }
@@ -869,7 +866,7 @@ class ZigbeeController extends EventEmitter {
869
866
  target = !target ? this.getCoordinator() : target;
870
867
 
871
868
  this.debug(`Binding ${log}`);
872
- ep.bind(cluster, target, (error) => {
869
+ ep.bind(cluster, target, error => {
873
870
  if (error) {
874
871
  this.sendError(error);
875
872
  this.error(`Failed to bind ${log} - (${error})`);
@@ -900,11 +897,11 @@ class ZigbeeController extends EventEmitter {
900
897
  reset(mode, callback) {
901
898
  try {
902
899
  this.herdsman.reset(mode);
903
- if (callback) callback();
900
+ callback && callback();
904
901
  } catch (error) {
905
902
  this.sendError(error);
906
903
  this.error(`Failed to reset ${error.stack}`);
907
- if (callback) callback(error);
904
+ callback && callback(error);
908
905
  }
909
906
  }
910
907