iobroker.zigbee 1.8.1 → 1.8.3

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 (89) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +37 -0
  3. package/.github/FUNDING.yml +3 -0
  4. package/.github/auto-merge.yml +17 -0
  5. package/.github/dependabot.yml +24 -0
  6. package/.github/stale.yml +13 -0
  7. package/.github/workflows/codeql.yml +41 -0
  8. package/.github/workflows/dependabot-automerge.yml +22 -0
  9. package/.github/workflows/test-and-release.yml +149 -0
  10. package/.releaseconfig.json +3 -0
  11. package/.travis/wiki.sh +28 -0
  12. package/.travis.yml +41 -0
  13. package/README.md +31 -8
  14. package/admin/admin.js +466 -482
  15. package/admin/i18n/de/translations.json +2 -2
  16. package/admin/index_m.html +1 -1
  17. package/admin/tab_m.html +3 -44
  18. package/admin/words.js +2 -2
  19. package/gulpfile.js +464 -0
  20. package/io-package.json +18 -25
  21. package/lib/backup.js +2 -2
  22. package/lib/binding.js +37 -32
  23. package/lib/colors.js +158 -163
  24. package/lib/commands.js +90 -99
  25. package/lib/developer.js +12 -9
  26. package/lib/devices.js +179 -169
  27. package/lib/exclude.js +36 -30
  28. package/lib/exposes.js +139 -163
  29. package/lib/groups.js +83 -81
  30. package/lib/json.js +6 -5
  31. package/lib/networkmap.js +3 -2
  32. package/lib/ota.js +18 -34
  33. package/lib/rgb.js +72 -114
  34. package/lib/seriallist.js +20 -25
  35. package/lib/states.js +526 -511
  36. package/lib/statescontroller.js +183 -206
  37. package/lib/utils.js +23 -24
  38. package/lib/zbBaseExtension.js +4 -4
  39. package/lib/zbDelayedAction.js +13 -5
  40. package/lib/zbDeviceAvailability.js +65 -69
  41. package/lib/zbDeviceConfigure.js +21 -9
  42. package/lib/zbDeviceEvent.js +4 -3
  43. package/lib/zigbeecontroller.js +103 -109
  44. package/main.js +147 -163
  45. package/package.json +15 -29
  46. package/test/integration.js +5 -0
  47. package/test/mocha.custom.opts +2 -0
  48. package/test/mocha.setup.js +14 -0
  49. package/test/package.js +5 -0
  50. package/test/unit.js +5 -0
  51. package/docs/de/img/CC2531.png +0 -0
  52. package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
  53. package/docs/de/img/CC2591.png +0 -0
  54. package/docs/de/img/boards.jpg +0 -0
  55. package/docs/de/img/cc26x2r.PNG +0 -0
  56. package/docs/de/img/results.jpg +0 -0
  57. package/docs/de/img/sku_429478_2.png +0 -0
  58. package/docs/de/img/sku_429601_2.png +0 -0
  59. package/docs/de/readme.md +0 -27
  60. package/docs/en/img/CC2531.png +0 -0
  61. package/docs/en/img/CC2591.png +0 -0
  62. package/docs/en/img/deconz.png +0 -0
  63. package/docs/en/img/sku_429478_2.png +0 -0
  64. package/docs/en/img/sku_429601_2.png +0 -0
  65. package/docs/en/readme.md +0 -30
  66. package/docs/flashing_via_arduino_(en).md +0 -110
  67. package/docs/ru/img/CC2531.png +0 -0
  68. package/docs/ru/img/CC2591.png +0 -0
  69. package/docs/ru/img/sku_429478_2.png +0 -0
  70. package/docs/ru/img/sku_429601_2.png +0 -0
  71. package/docs/ru/readme.md +0 -28
  72. package/docs/tutorial/CC2530_20190425.zip +0 -0
  73. package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
  74. package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
  75. package/docs/tutorial/CC2531_20190425.zip +0 -0
  76. package/docs/tutorial/adm5_1.PNG +0 -0
  77. package/docs/tutorial/adm5_2.PNG +0 -0
  78. package/docs/tutorial/cat.PNG +0 -0
  79. package/docs/tutorial/groups-1.png +0 -0
  80. package/docs/tutorial/groups-2.png +0 -0
  81. package/docs/tutorial/inst.PNG +0 -0
  82. package/docs/tutorial/reflash-finish.PNG +0 -0
  83. package/docs/tutorial/reflash-step0.png +0 -0
  84. package/docs/tutorial/reflash-step1.PNG +0 -0
  85. package/docs/tutorial/reflash-step2.PNG +0 -0
  86. package/docs/tutorial/settings.png +0 -0
  87. package/docs/tutorial/tab-dev-1.png +0 -0
  88. package/docs/tutorial/zigbee.png +0 -0
  89. package/docs/tutorial/zigbee15.png +0 -0
@@ -85,12 +85,7 @@ class ZigbeeController extends EventEmitter {
85
85
 
86
86
  this.debug(`Using zigbee-herdsman with settings: ${JSON.stringify(herdsmanSettings)}`);
87
87
  this.herdsman = new ZigbeeHerdsman.Controller(herdsmanSettings, this.adapter.log);
88
- this.callExtensionMethod('setOptions', [{
89
- disableActivePing: options.disablePing,
90
- disableForcedPing: false,
91
- pingTimeout: 300,
92
- pingCount: 3
93
- }]);
88
+ this.callExtensionMethod('setOptions', [{ disableActivePing: options.disablePing, disableForcedPing: false, pingTimeout:300, pingCount:3 }] );
94
89
  }
95
90
 
96
91
  // Start controller
@@ -113,22 +108,23 @@ class ZigbeeController extends EventEmitter {
113
108
 
114
109
  // debug info from herdsman getNetworkParameters
115
110
  const debNetworkParam = JSON.parse(JSON.stringify(await this.herdsman.getNetworkParameters()));
116
- const extendedPanIDDebug = typeof debNetworkParam.extendedPanID === 'string' ? debNetworkParam.extendedPanID.replace('0x', '') : debNetworkParam.extendedPanID;
111
+ const extendedPanIDDebug = (typeof debNetworkParam.extendedPanID == 'string') ? debNetworkParam.extendedPanID.replace('0x','') : debNetworkParam.extendedPanID;
117
112
 
118
113
  let extPanIDDebug = '';
119
114
  for (let i = extendedPanIDDebug.length - 1; i >= 0; i--) {
120
- extPanIDDebug += extendedPanIDDebug[i - 1];
115
+ extPanIDDebug += extendedPanIDDebug[i-1];
121
116
  extPanIDDebug += extendedPanIDDebug[i];
122
117
  i--;
123
118
  }
124
119
 
125
120
  this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
121
+
126
122
  } catch (e) {
127
123
  this.sendError(e);
128
- this.error(`Starting zigbee-herdsman problem : ${JSON.stringify(e.message)}`);
124
+ this.error('Starting zigbee-herdsman problem : ' + JSON.stringify(e.message));
129
125
  throw 'Error herdsman start';
130
126
  }
131
- // Check if we have to turn off the LED
127
+ // Check if we have to turn off the led
132
128
  try {
133
129
  if (this.disableLed) {
134
130
  this.info('Disable LED');
@@ -145,7 +141,7 @@ class ZigbeeController extends EventEmitter {
145
141
  let powerText = 'normal';
146
142
 
147
143
  if (this.transmitPower != '0') {
148
- switch (this.transmitPower) {
144
+ switch(this.transmitPower) {
149
145
  case '-22':
150
146
  powerText = 'low';
151
147
  break;
@@ -161,7 +157,7 @@ class ZigbeeController extends EventEmitter {
161
157
  }
162
158
 
163
159
 
164
- this.info(` --> transmitPower : ${powerText}`);
160
+ this.info(' --> transmitPower : ' + powerText);
165
161
  try {
166
162
  await this.herdsman.setTransmitPower(this.transmitPower);
167
163
  } catch (e) {
@@ -169,6 +165,7 @@ class ZigbeeController extends EventEmitter {
169
165
  this.info('Unable to set transmit power, unsupported function.');
170
166
  }
171
167
 
168
+
172
169
  // Call extensions
173
170
  this.callExtensionMethod('onZigbeeStarted', []);
174
171
 
@@ -179,21 +176,20 @@ class ZigbeeController extends EventEmitter {
179
176
  } else {
180
177
  this.info(`Currently no devices.`);
181
178
  }
182
-
183
179
  for (const device of devices) {
184
180
  const entity = await this.resolveEntity(device);
185
- this.adapter.getObject(device.ieeeAddr.substr(2), (err, obj) => {
186
- if (obj && obj.common && obj.common.deactivated) {
181
+ this.adapter.getObject(device.ieeeAddr.substr(2),(err, obj) => {
182
+ if (obj && obj.common && obj.common.deactivated)
183
+ {
187
184
  this.callExtensionMethod('deregisterDevicePing', [device, entity]);
188
- } else {
185
+ }
186
+ else {
189
187
  this.callExtensionMethod('registerDevicePing', [device, entity]);
190
188
  }
191
189
  });
192
190
  // ensure that objects for all found clients are present
193
191
 
194
- if (entity.mapped) {
195
- this.emit('new', entity);
196
- }
192
+ if (entity.mapped) this.emit('new', entity);
197
193
  this.info(
198
194
  (entity.device.ieeeAddr) +
199
195
  ` (addr ${entity.device.networkAddress}): ` +
@@ -265,7 +261,8 @@ class ZigbeeController extends EventEmitter {
265
261
 
266
262
  async getGroups() {
267
263
  try {
268
- return await this.herdsman.getGroups();
264
+ const rv = await this.herdsman.getGroups();
265
+ return rv;
269
266
  } catch (error) {
270
267
  this.sendError(error);
271
268
  this.error(JSON.stringify(error));
@@ -274,12 +271,12 @@ class ZigbeeController extends EventEmitter {
274
271
  }
275
272
 
276
273
  async removeGroupById(id) {
277
- const group = await this.getGroupByID(id);
274
+ const group = await this.getGroupByID(id);
278
275
  try {
279
- group && group.removeFromDatabase();
276
+ if (group) group.removeFromDatabase();
280
277
  } catch (error) {
281
278
  this.sendError(error);
282
- this.error(`error in removeGroupById: ${error}`);
279
+ this.error('error in removeGroupById: ' + error);
283
280
  }
284
281
  }
285
282
 
@@ -293,15 +290,16 @@ class ZigbeeController extends EventEmitter {
293
290
  }
294
291
 
295
292
  async verifyGroupExists(id) {
296
- const nid = typeof id === 'number' ? id : parseInt(id);
293
+ const nid = (typeof(id) === 'number' ? id:parseInt(id));
297
294
  let group = await this.herdsman.getGroupByID(nid);
298
295
  if (!group) {
299
296
  group = await this.herdsman.createGroup(nid);
300
297
  group.toZigbee = groupConverters;
301
298
  group.model = 'group';
302
- this.debug(`verifyGroupExists: created group ${nid}`);
303
- } else {
304
- this.debug(`verifyGroupExists: group ${nid} exists`);
299
+ this.debug('verifyGroupExists: created group ' + nid);
300
+ }
301
+ else {
302
+ this.debug('verifyGroupExists: group ' + nid + ' exists');
305
303
  }
306
304
 
307
305
  }
@@ -313,29 +311,20 @@ class ZigbeeController extends EventEmitter {
313
311
  if (group) {
314
312
  const groupmembers = group.members;
315
313
  for (const member of groupmembers) {
316
- const epid = member.ID ? member.ID : -1;
314
+ const epid = (member.ID ? member.ID:-1);
317
315
  const nwk = member.deviceNetworkAddress;
318
316
  const device = this.getDeviceByNetworkAddress(nwk);
319
- if (device && device.ieeeAddr) {
320
- members.push({
321
- ieee: device.ieeeAddr,
322
- model: device.modelID,
323
- epid,
324
- ep: member
325
- });
326
- }
317
+ if (device && device.ieeeAddr) members.push( { ieee:device.ieeeAddr, model:device.modelID, epid:epid, ep:member } );
327
318
  }
328
- } else {
319
+ }
320
+ else {
329
321
  return undefined;
330
322
  }
331
323
 
332
324
  } catch (error) {
333
325
  this.sendError(error);
334
- if (error) {
335
- this.error(`getGroupMembersFromController: error is ${JSON.stringify(error)} ${JSON.stringify(new Error().stack)}`);
336
- } else {
337
- this.error('unidentified error in getGroupMembersFromController');
338
- }
326
+ if (error) this.error('getGroupMembersFromController: error is ' + JSON.stringify(error) + ' ' + JSON.stringify(new Error().stack));
327
+ else this.error('unidentifed error in getGroupMembersFromController');
339
328
  }
340
329
  return members;
341
330
  }
@@ -415,7 +404,7 @@ class ZigbeeController extends EventEmitter {
415
404
  }
416
405
  }
417
406
 
418
- async incMsgHandler(message) {
407
+ async incMsgHandler(message){
419
408
  this.debug('incoming msg', message);
420
409
  const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr);
421
410
  if (!device) {
@@ -473,8 +462,8 @@ class ZigbeeController extends EventEmitter {
473
462
  } else {
474
463
  this.info('Zigbee: disabling joining new devices.');
475
464
  }
476
-
477
- try {
465
+ try
466
+ {
478
467
  if (permitTime && !this.herdsman.getPermitJoin()) {
479
468
  clearInterval(this._permitJoinInterval);
480
469
  this._permitJoinTime = permitTime;
@@ -520,7 +509,6 @@ class ZigbeeController extends EventEmitter {
520
509
  this.debug(`Force remove`);
521
510
  }
522
511
  }
523
-
524
512
  try {
525
513
  await device.removeFromDatabase();
526
514
  } catch (error) {
@@ -530,7 +518,7 @@ class ZigbeeController extends EventEmitter {
530
518
  this.debug(`Failed to remove from DB ${error.stack}`);
531
519
  }
532
520
  this.debug('Remove successful.');
533
- callback && callback();
521
+ if (callback) callback();
534
522
  this.callExtensionMethod(
535
523
  'onDeviceRemove',
536
524
  [device],
@@ -539,7 +527,7 @@ class ZigbeeController extends EventEmitter {
539
527
  } catch (error) {
540
528
  this.sendError(error);
541
529
  this.error(`Failed to remove ${error.stack}`);
542
- callback && callback(`Failed to remove ${error.stack}`);
530
+ if (callback) callback(`Failed to remove ${error.stack}`);
543
531
  }
544
532
  }
545
533
 
@@ -548,7 +536,7 @@ class ZigbeeController extends EventEmitter {
548
536
  try {
549
537
  this.debug('handleDeviceLeave', message);
550
538
  const entity = await this.resolveEntity(message.device || message.ieeeAddr);
551
- const friendlyName = entity ? entity.name : message.ieeeAddr;
539
+ const friendlyName = (entity) ? entity.name : message.ieeeAddr;
552
540
  this.debug(`Device '${friendlyName}' left the network`);
553
541
  this.emit('leave', message.ieeeAddr);
554
542
  // Call extensions
@@ -572,17 +560,15 @@ class ZigbeeController extends EventEmitter {
572
560
  if (entity && entity.mapped) {
573
561
  this.callExtensionMethod(
574
562
  'onZigbeeEvent',
575
- [{'device': message.device, 'type': 'deviceAnnounce'}, entity ? entity.mapped : null]);
563
+ [ {'device': message.device, 'type': 'deviceAnnounce'}, (entity ? entity.mapped : null)]);
576
564
  }
577
565
  } catch (error) {
578
566
  this.sendError(error);
579
567
  this.error(`Failed to handleDeviceLeave ${error.stack}`);
580
568
  }
581
-
569
+
582
570
  this.emit('pairing', `Device '${friendlyName}' announced itself`);
583
- if (!this.herdsman.getPermitJoin()) {
584
- this.callExtensionMethod('registerDevicePing', [message.device, entity]);
585
- }
571
+ if (!this.herdsman.getPermitJoin()) this.callExtensionMethod('registerDevicePing', [message.device, entity]);
586
572
  // if has modelID so can create device
587
573
  if (entity.device && entity.device._modelID) {
588
574
  entity.device.modelID = entity.device._modelID;
@@ -664,11 +650,12 @@ class ZigbeeController extends EventEmitter {
664
650
 
665
651
  async getMap(callback) {
666
652
  try {
653
+
667
654
  const devices = this.herdsman.getDevices(true);
668
655
  const lqis = [];
669
656
  const routing = [];
670
657
 
671
- for (const device of devices.filter((d) => d.type !== 'EndDevice')) {
658
+ for (const device of devices.filter((d) => d.type != 'EndDevice')) {
672
659
  const resolved = await this.resolveEntity(device);
673
660
  let result;
674
661
 
@@ -692,7 +679,7 @@ class ZigbeeController extends EventEmitter {
692
679
 
693
680
  if (result !== undefined) {
694
681
  for (const dev of result.neighbors) {
695
- if (dev !== undefined && dev.ieeeAddr !== '0xffffffffffffffff') {
682
+ if (dev.ieeeAddr !== '0xffffffffffffffff' && dev !== undefined) {
696
683
  lqis.push({
697
684
  parent: resolved.device.ieeeAddr,
698
685
  networkAddress: dev.networkAddress,
@@ -700,7 +687,7 @@ class ZigbeeController extends EventEmitter {
700
687
  lqi: dev.linkquality,
701
688
  relationship: dev.relationship,
702
689
  depth: dev.depth,
703
- status: dev.linkquality > 0 ? 'online' : 'offline',
690
+ status: (dev.linkquality > 0) ? 'online' : 'offline',
704
691
  });
705
692
  }
706
693
  }
@@ -731,10 +718,11 @@ class ZigbeeController extends EventEmitter {
731
718
  }
732
719
  }
733
720
  this.debug(`Routing table succeeded for '${resolved.name}'`);
721
+
734
722
  }
735
723
  this.debug(`Get map succeeded ${safeJsonStringify(lqis)}`);
736
724
 
737
- callback && callback({lqis, routing});
725
+ if (callback) callback({lqis: lqis, routing: routing});
738
726
  } catch (error) {
739
727
  this.sendError(error);
740
728
  this.debug(`Failed to get map: ${safeJsonStringify(error.stack)}`);
@@ -767,7 +755,7 @@ class ZigbeeController extends EventEmitter {
767
755
  if (type === 'foundation') {
768
756
  cfg.disableDefaultResponse = true;
769
757
  if (cmd === 'read' && !Array.isArray(zclData)) {
770
- // needs to be iterable (string[] | number [])
758
+ // needs to be iterateable (string[] | number [])
771
759
  zclData[Symbol.iterator] = function* () {
772
760
  let k;
773
761
  for (k in this) {
@@ -781,15 +769,17 @@ class ZigbeeController extends EventEmitter {
781
769
  } else {
782
770
  result = await endpoint[cmd](cid, zclData, cfg);
783
771
  }
784
- callback && callback(undefined, result);
785
- } else if (type === 'functionalResp') {
786
- cfg.disableDefaultResponse = false;
787
- const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
788
- callback && callback(undefined, result);
789
- } else {
772
+ if (callback) callback(undefined, result);
773
+ }
774
+ else if(type === 'functionalResp'){
775
+ cfg.disableDefaultResponse = false;
776
+ const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
777
+ if (callback) callback(undefined, result);
778
+ }
779
+ else {
790
780
  cfg.disableDefaultResponse = false;
791
781
  const result = await endpoint.command(cid, cmd, zclData, cfg);
792
- callback && callback(undefined, result);
782
+ if (callback) callback(undefined, result);
793
783
  }
794
784
  }
795
785
 
@@ -800,61 +790,66 @@ class ZigbeeController extends EventEmitter {
800
790
  this.debug(`addDevFromGroup - entity: ${safeJsonStringify(entity)}`);
801
791
  this.debug(`addDevFromGroup - group: ${safeJsonStringify(group)}`);
802
792
  if (epid != undefined) {
803
- for (const ep of entity.endpoints) {
804
- if (ep.ID === epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
805
- this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`);
806
- await (ep.addToGroup(group.mapped));
807
- }
793
+ for (const ep of entity.endpoints) {
794
+ if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
795
+ {
796
+ this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`)
797
+ await(ep.addToGroup(group.mapped));
808
798
  }
799
+ }
809
800
 
810
- } else {
811
- if (entity.endpoint.inputClusters.includes(4)) {
812
- this.debug(`adding endpoint ${entity.endpoint.ID} to group`);
801
+ }
802
+ else
803
+ {
804
+ if (entity.endpoint.inputClusters.includes(4))
805
+ {
806
+ this.debug(`adding endpoint ${entity.endpoint.ID} to group`)
813
807
  await entity.endpoint.addToGroup(group.mapped);
814
- } else {
808
+ }
809
+ else {
815
810
  let added = false;
816
- for (const ep of entity.endpoints) {
817
- if (ep.inputClusters.includes(4)) {
818
- this.debug(`adding endpoint ${ep.ID} to group`);
811
+ for (const ep of entity.endpoints)
812
+ {
813
+ if (ep.inputClusters.includes(4))
814
+ {
815
+ this.debug(`adding endpoint ${ep.ID} to group`)
819
816
  await ep.addToGroup(group.mapped);
820
817
  added = true;
821
818
  break;
822
819
  }
823
820
  }
824
- if (!added) {
825
- throw ('cluster genGroups not supported');
826
- }
821
+ if (!added) throw ('cluster genGroups not supported');
827
822
  }
828
823
  }
829
824
  } catch (error) {
830
825
  this.sendError(error);
831
826
  this.error(`Exception when trying to Add ${devId} to group ${groupId}`, error);
832
- return {error: `Failed to add ${devId} to group ${groupId}: ${JSON.stringify(error)}`};
827
+ return { error:`Failed to add ${devId} to group ${groupId}: ${JSON.stringify(error)}` };
833
828
  }
834
829
  return {};
835
830
  }
836
831
 
837
832
  async removeDevFromGroup(devId, groupId, epid) {
838
- let entity;
839
- try {
840
- entity = await this.resolveEntity(devId);
841
- const group = await this.resolveEntity(groupId);
842
- this.debug(`removeDevFromGroup - entity: ${safeJsonStringify(entity)}`);
843
- this.debug(`removeDevFromGroup - group: ${safeJsonStringify(group)}`);
844
- if (epid != undefined) {
845
- for (const ep of entity.endpoints) {
846
- if (ep.ID === epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
847
- this.debug(`removing endpoint ${ep.ID} (${epid}) group ${groupId}`);
848
- await ep.removeFromGroup(group.mapped);
849
- }
850
- }
851
- } else await entity.endpoint.removeFromGroup(group.mapped);
852
- } catch (error) {
853
- this.sendError(error);
854
- this.error(`Exception when trying remove ${devId} (ep ${epid ? epid : (entity ? entity.endpoint.ID : '')}) from group ${devId}`, error);
855
- return {error: `Failed to remove dev ${devId} (ep ${epid ? epid : (entity ? entity.endpoint.ID : '')}) from group ${devId}`};
856
- }
857
- return {};
833
+ try {
834
+ const entity = await this.resolveEntity(devId);
835
+ const group = await this.resolveEntity(groupId);
836
+ this.debug(`removeDevFromGroup - entity: ${safeJsonStringify(entity)}`);
837
+ this.debug(`removeDevFromGroup - group: ${safeJsonStringify(group)}`);
838
+ if (epid != undefined) {
839
+ for (const ep of entity.endpoints) {
840
+ if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
841
+ {
842
+ this.debug(`removing endpoint ${ep.ID} (${epid}) group ${groupId}`)
843
+ await(ep.removeFromGroup(group.mapped))
844
+ }
845
+ }
846
+ } else await entity.endpoint.removeFromGroup(group.mapped);
847
+ } catch (error) {
848
+ this.sendError(error);
849
+ this.error(`Exception when trying remove ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`, error);
850
+ return { error: `Failed to remove dev ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`};
851
+ }
852
+ return {};
858
853
  }
859
854
 
860
855
  async removeDevFromAllGroups(devId) {
@@ -862,15 +857,14 @@ class ZigbeeController extends EventEmitter {
862
857
  const entity = await this.resolveEntity(devId);
863
858
  this.debug(`entity: ${safeJsonStringify(entity)}`);
864
859
  for (const ep of entity.endpoints) {
865
- if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)) {
866
- await ep.removefromAllGroups();
867
- }
860
+ if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))
861
+ await ep.removefromAllGroups();
868
862
  }
869
863
  //await entity.endpoint.removeFromAllGroups();
870
864
  } catch (error) {
871
865
  this.sendError(error);
872
866
  this.error(`Exception when trying remove ${devId} from all groups`, error);
873
- return {error: `Failed to remove dev ${devId} from all groups: ${error}`};
867
+ return { error: `Failed to remove dev ${devId} from all groups: ${error}`};
874
868
  }
875
869
  return {};
876
870
  }
@@ -880,7 +874,7 @@ class ZigbeeController extends EventEmitter {
880
874
  target = !target ? this.getCoordinator() : target;
881
875
 
882
876
  this.debug(`Binding ${log}`);
883
- ep.bind(cluster, target, error => {
877
+ ep.bind(cluster, target, (error) => {
884
878
  if (error) {
885
879
  this.sendError(error);
886
880
  this.error(`Failed to bind ${log} - (${error})`);
@@ -911,11 +905,11 @@ class ZigbeeController extends EventEmitter {
911
905
  reset(mode, callback) {
912
906
  try {
913
907
  this.herdsman.reset(mode);
914
- callback && callback();
908
+ if (callback) callback();
915
909
  } catch (error) {
916
910
  this.sendError(error);
917
911
  this.error(`Failed to reset ${error.stack}`);
918
- callback && callback(error);
912
+ if (callback) callback(error);
919
913
  }
920
914
  }
921
915