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.
- package/.eslintignore +2 -0
- package/.eslintrc.json +37 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/auto-merge.yml +17 -0
- package/.github/dependabot.yml +24 -0
- package/.github/stale.yml +13 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependabot-automerge.yml +22 -0
- package/.github/workflows/test-and-release.yml +149 -0
- package/.releaseconfig.json +3 -0
- package/.travis/wiki.sh +28 -0
- package/.travis.yml +41 -0
- package/README.md +31 -8
- package/admin/admin.js +466 -482
- package/admin/i18n/de/translations.json +2 -2
- package/admin/index_m.html +1 -1
- package/admin/tab_m.html +3 -44
- package/admin/words.js +2 -2
- package/gulpfile.js +464 -0
- package/io-package.json +18 -25
- package/lib/backup.js +2 -2
- package/lib/binding.js +37 -32
- package/lib/colors.js +158 -163
- package/lib/commands.js +90 -99
- package/lib/developer.js +12 -9
- package/lib/devices.js +179 -169
- package/lib/exclude.js +36 -30
- package/lib/exposes.js +139 -163
- package/lib/groups.js +83 -81
- package/lib/json.js +6 -5
- package/lib/networkmap.js +3 -2
- package/lib/ota.js +18 -34
- package/lib/rgb.js +72 -114
- package/lib/seriallist.js +20 -25
- package/lib/states.js +526 -511
- package/lib/statescontroller.js +183 -206
- package/lib/utils.js +23 -24
- package/lib/zbBaseExtension.js +4 -4
- package/lib/zbDelayedAction.js +13 -5
- package/lib/zbDeviceAvailability.js +65 -69
- package/lib/zbDeviceConfigure.js +21 -9
- package/lib/zbDeviceEvent.js +4 -3
- package/lib/zigbeecontroller.js +103 -109
- package/main.js +147 -163
- package/package.json +15 -29
- package/test/integration.js +5 -0
- package/test/mocha.custom.opts +2 -0
- package/test/mocha.setup.js +14 -0
- package/test/package.js +5 -0
- package/test/unit.js +5 -0
- package/docs/de/img/CC2531.png +0 -0
- package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
- package/docs/de/img/CC2591.png +0 -0
- package/docs/de/img/boards.jpg +0 -0
- package/docs/de/img/cc26x2r.PNG +0 -0
- package/docs/de/img/results.jpg +0 -0
- package/docs/de/img/sku_429478_2.png +0 -0
- package/docs/de/img/sku_429601_2.png +0 -0
- package/docs/de/readme.md +0 -27
- package/docs/en/img/CC2531.png +0 -0
- package/docs/en/img/CC2591.png +0 -0
- package/docs/en/img/deconz.png +0 -0
- package/docs/en/img/sku_429478_2.png +0 -0
- package/docs/en/img/sku_429601_2.png +0 -0
- package/docs/en/readme.md +0 -30
- package/docs/flashing_via_arduino_(en).md +0 -110
- package/docs/ru/img/CC2531.png +0 -0
- package/docs/ru/img/CC2591.png +0 -0
- package/docs/ru/img/sku_429478_2.png +0 -0
- package/docs/ru/img/sku_429601_2.png +0 -0
- package/docs/ru/readme.md +0 -28
- package/docs/tutorial/CC2530_20190425.zip +0 -0
- package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
- package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
- package/docs/tutorial/CC2531_20190425.zip +0 -0
- package/docs/tutorial/adm5_1.PNG +0 -0
- package/docs/tutorial/adm5_2.PNG +0 -0
- package/docs/tutorial/cat.PNG +0 -0
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/inst.PNG +0 -0
- package/docs/tutorial/reflash-finish.PNG +0 -0
- package/docs/tutorial/reflash-step0.png +0 -0
- package/docs/tutorial/reflash-step1.PNG +0 -0
- package/docs/tutorial/reflash-step2.PNG +0 -0
- package/docs/tutorial/settings.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/docs/tutorial/zigbee.png +0 -0
- package/docs/tutorial/zigbee15.png +0 -0
package/lib/zigbeecontroller.js
CHANGED
|
@@ -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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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),
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
|
274
|
+
const group = await this.getGroupByID(id);
|
|
278
275
|
try {
|
|
279
|
-
group
|
|
276
|
+
if (group) group.removeFromDatabase();
|
|
280
277
|
} catch (error) {
|
|
281
278
|
this.sendError(error);
|
|
282
|
-
this.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
|
-
|
|
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(
|
|
303
|
-
}
|
|
304
|
-
|
|
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
|
|
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
|
-
}
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
329
321
|
return undefined;
|
|
330
322
|
}
|
|
331
323
|
|
|
332
324
|
} catch (error) {
|
|
333
325
|
this.sendError(error);
|
|
334
|
-
if (error)
|
|
335
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 !==
|
|
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
|
|
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
|
|
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
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
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
|
|
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
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
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
|
-
}
|
|
811
|
-
|
|
812
|
-
|
|
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
|
-
}
|
|
808
|
+
}
|
|
809
|
+
else {
|
|
815
810
|
let added = false;
|
|
816
|
-
for (const ep of entity.endpoints)
|
|
817
|
-
|
|
818
|
-
|
|
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
|
|
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
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
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
|
-
|
|
866
|
-
|
|
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
|
|
908
|
+
if (callback) callback();
|
|
915
909
|
} catch (error) {
|
|
916
910
|
this.sendError(error);
|
|
917
911
|
this.error(`Failed to reset ${error.stack}`);
|
|
918
|
-
callback
|
|
912
|
+
if (callback) callback(error);
|
|
919
913
|
}
|
|
920
914
|
}
|
|
921
915
|
|