zigbee-herdsman 1.0.0 → 1.1.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 (132) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/dist/adapter/adapter.d.ts +6 -0
  4. package/dist/adapter/adapter.d.ts.map +1 -1
  5. package/dist/adapter/adapter.js.map +1 -1
  6. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +5 -3
  7. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
  8. package/dist/adapter/deconz/adapter/deconzAdapter.js +261 -558
  9. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
  10. package/dist/adapter/deconz/driver/constants.d.ts +102 -56
  11. package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
  12. package/dist/adapter/deconz/driver/constants.js +1 -2
  13. package/dist/adapter/deconz/driver/constants.js.map +1 -1
  14. package/dist/adapter/deconz/driver/driver.d.ts.map +1 -1
  15. package/dist/adapter/deconz/driver/driver.js +46 -41
  16. package/dist/adapter/deconz/driver/driver.js.map +1 -1
  17. package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -1
  18. package/dist/adapter/deconz/driver/frameParser.js +174 -107
  19. package/dist/adapter/deconz/driver/frameParser.js.map +1 -1
  20. package/dist/adapter/ember/adapter/emberAdapter.d.ts +4 -12
  21. package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
  22. package/dist/adapter/ember/adapter/emberAdapter.js +215 -249
  23. package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
  24. package/dist/adapter/ember/adapter/oneWaitress.d.ts +16 -12
  25. package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
  26. package/dist/adapter/ember/adapter/oneWaitress.js +16 -41
  27. package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
  28. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +10 -8
  29. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
  30. package/dist/adapter/ezsp/adapter/ezspAdapter.js +241 -238
  31. package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
  32. package/dist/adapter/ezsp/driver/driver.d.ts +6 -14
  33. package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
  34. package/dist/adapter/ezsp/driver/driver.js +56 -37
  35. package/dist/adapter/ezsp/driver/driver.js.map +1 -1
  36. package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -1
  37. package/dist/adapter/ezsp/driver/ezsp.js +3 -0
  38. package/dist/adapter/ezsp/driver/ezsp.js.map +1 -1
  39. package/dist/adapter/z-stack/adapter/manager.js +2 -2
  40. package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
  41. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +4 -3
  42. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
  43. package/dist/adapter/z-stack/adapter/zStackAdapter.js +258 -197
  44. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
  45. package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -1
  46. package/dist/adapter/z-stack/znp/definition.js +256 -302
  47. package/dist/adapter/z-stack/znp/definition.js.map +1 -1
  48. package/dist/adapter/z-stack/znp/tstype.d.ts +8 -8
  49. package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -1
  50. package/dist/adapter/z-stack/znp/utils.d.ts +3 -2
  51. package/dist/adapter/z-stack/znp/utils.d.ts.map +1 -1
  52. package/dist/adapter/z-stack/znp/utils.js +8 -7
  53. package/dist/adapter/z-stack/znp/utils.js.map +1 -1
  54. package/dist/adapter/z-stack/znp/znp.d.ts +3 -1
  55. package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -1
  56. package/dist/adapter/z-stack/znp/znp.js +31 -14
  57. package/dist/adapter/z-stack/znp/znp.js.map +1 -1
  58. package/dist/adapter/z-stack/znp/zpiObject.d.ts +5 -6
  59. package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -1
  60. package/dist/adapter/z-stack/znp/zpiObject.js +28 -11
  61. package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -1
  62. package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +7 -5
  63. package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -1
  64. package/dist/adapter/zboss/adapter/zbossAdapter.js +284 -138
  65. package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -1
  66. package/dist/adapter/zboss/commands.d.ts +3 -0
  67. package/dist/adapter/zboss/commands.d.ts.map +1 -1
  68. package/dist/adapter/zboss/commands.js +248 -205
  69. package/dist/adapter/zboss/commands.js.map +1 -1
  70. package/dist/adapter/zboss/driver.d.ts +4 -14
  71. package/dist/adapter/zboss/driver.d.ts.map +1 -1
  72. package/dist/adapter/zboss/driver.js +63 -89
  73. package/dist/adapter/zboss/driver.js.map +1 -1
  74. package/dist/adapter/zboss/enums.d.ts +24 -2
  75. package/dist/adapter/zboss/enums.d.ts.map +1 -1
  76. package/dist/adapter/zboss/enums.js +35 -3
  77. package/dist/adapter/zboss/enums.js.map +1 -1
  78. package/dist/adapter/zboss/frame.d.ts +6 -1
  79. package/dist/adapter/zboss/frame.d.ts.map +1 -1
  80. package/dist/adapter/zboss/frame.js +56 -11
  81. package/dist/adapter/zboss/frame.js.map +1 -1
  82. package/dist/adapter/zboss/uart.d.ts +1 -0
  83. package/dist/adapter/zboss/uart.d.ts.map +1 -1
  84. package/dist/adapter/zboss/uart.js +4 -2
  85. package/dist/adapter/zboss/uart.js.map +1 -1
  86. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts +5 -0
  87. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts.map +1 -0
  88. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js +44 -0
  89. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js.map +1 -0
  90. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +5 -0
  91. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
  92. package/dist/adapter/zigate/adapter/zigateAdapter.js +247 -262
  93. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
  94. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
  95. package/dist/adapter/zigate/driver/buffaloZiGate.js +2 -18
  96. package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
  97. package/dist/adapter/zigate/driver/commandType.js +218 -218
  98. package/dist/adapter/zigate/driver/commandType.js.map +1 -1
  99. package/dist/adapter/zigate/driver/constants.d.ts +14 -8
  100. package/dist/adapter/zigate/driver/constants.d.ts.map +1 -1
  101. package/dist/adapter/zigate/driver/constants.js +36 -9
  102. package/dist/adapter/zigate/driver/constants.js.map +1 -1
  103. package/dist/adapter/zigate/driver/messageType.js +42 -42
  104. package/dist/adapter/zigate/driver/messageType.js.map +1 -1
  105. package/dist/adapter/zigate/driver/zigate.d.ts +17 -13
  106. package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
  107. package/dist/adapter/zigate/driver/zigate.js +83 -18
  108. package/dist/adapter/zigate/driver/zigate.js.map +1 -1
  109. package/dist/controller/controller.d.ts +1 -0
  110. package/dist/controller/controller.d.ts.map +1 -1
  111. package/dist/controller/controller.js +28 -0
  112. package/dist/controller/controller.js.map +1 -1
  113. package/dist/utils/patchBigIntSerialization.d.ts +2 -0
  114. package/dist/utils/patchBigIntSerialization.d.ts.map +1 -0
  115. package/dist/utils/patchBigIntSerialization.js +9 -0
  116. package/dist/utils/patchBigIntSerialization.js.map +1 -0
  117. package/dist/zspec/zcl/zclFrame.d.ts +1 -0
  118. package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
  119. package/dist/zspec/zcl/zclFrame.js +1 -0
  120. package/dist/zspec/zcl/zclFrame.js.map +1 -1
  121. package/dist/zspec/zdo/buffaloZdo.d.ts +1 -139
  122. package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
  123. package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
  124. package/dist/zspec/zdo/definition/tstypes.d.ts +168 -1
  125. package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -1
  126. package/dist/zspec/zdo/definition/tstypes.js +1 -0
  127. package/dist/zspec/zdo/definition/tstypes.js.map +1 -1
  128. package/dist/zspec/zdo/utils.d.ts +2 -3
  129. package/dist/zspec/zdo/utils.d.ts.map +1 -1
  130. package/dist/zspec/zdo/utils.js +3 -4
  131. package/dist/zspec/zdo/utils.js.map +1 -1
  132. package/package.json +1 -1
@@ -312,6 +312,7 @@ class EmberAdapter extends __1.Adapter {
312
312
  async onMessageSent(status, type, indexOrDestination, apsFrame, messageTag) {
313
313
  switch (status) {
314
314
  case enums_1.SLStatus.ZIGBEE_DELIVERY_FAILED: {
315
+ logger_1.logger.debug(() => `~x~> DELIVERY_FAILED [indexOrDestination=${indexOrDestination} apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
315
316
  // no ACK was received from the destination
316
317
  switch (type) {
317
318
  case enums_1.EmberOutgoingMessageType.BROADCAST:
@@ -319,7 +320,7 @@ class EmberAdapter extends __1.Adapter {
319
320
  case enums_1.EmberOutgoingMessageType.MULTICAST:
320
321
  case enums_1.EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
321
322
  // BC/MC not checking for message sent, avoid unnecessary waitress lookups
322
- logger_1.logger.error(`Delivery of ${enums_1.EmberOutgoingMessageType[type]} failed for '${indexOrDestination}' [apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
323
+ logger_1.logger.error(`Delivery of ${enums_1.EmberOutgoingMessageType[type]} failed for '${indexOrDestination}'.`, NS);
323
324
  break;
324
325
  }
325
326
  default: {
@@ -373,26 +374,20 @@ class EmberAdapter extends __1.Adapter {
373
374
  * @param messageContents The content of the response.
374
375
  */
375
376
  async onZDOResponse(apsFrame, sender, messageContents) {
376
- const [status, payload] = Zdo.Buffalo.readResponse(this.hasZdoMessageOverhead, apsFrame.clusterId, messageContents);
377
- if (status === Zdo.Status.SUCCESS) {
378
- logger_1.logger.debug(() => `<~~~ [ZDO ${Zdo.ClusterId[apsFrame.clusterId]} from=${sender} ${payload ? JSON.stringify(payload) : 'OK'}]`, NS);
379
- this.oneWaitress.resolveZDO(sender, apsFrame, payload);
380
- if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
381
- this.emit('networkAddress', {
382
- networkAddress: payload.nwkAddress,
383
- ieeeAddr: payload.eui64,
384
- });
385
- }
386
- else if (apsFrame.clusterId === Zdo.ClusterId.END_DEVICE_ANNOUNCE) {
387
- this.emit('deviceAnnounce', {
388
- networkAddress: payload.nwkAddress,
389
- ieeeAddr: payload.eui64,
390
- });
377
+ const result = Zdo.Buffalo.readResponse(this.hasZdoMessageOverhead, apsFrame.clusterId, messageContents);
378
+ logger_1.logger.debug(() => `<~~~ [ZDO ${Zdo.ClusterId[apsFrame.clusterId]} from=${sender} ${result[1] ? JSON.stringify(result[1]) : 'OK'}]`, NS);
379
+ if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
380
+ // special case to properly resolve a NETWORK_ADDRESS_RESPONSE following a NETWORK_ADDRESS_REQUEST (based on EUI64 from ZDO payload)
381
+ // NOTE: if response has invalid status (no EUI64 available), response waiter will eventually time out
382
+ /* istanbul ignore else */
383
+ if (Zdo.Buffalo.checkStatus(result)) {
384
+ this.oneWaitress.resolveZDO(result[1].eui64, apsFrame, result);
391
385
  }
392
386
  }
393
387
  else {
394
- this.oneWaitress.resolveZDO(sender, apsFrame, new Zdo.StatusError(status));
388
+ this.oneWaitress.resolveZDO(sender, apsFrame, result);
395
389
  }
390
+ this.emit('zdoResponse', apsFrame.clusterId, result);
396
391
  }
397
392
  /**
398
393
  * Emitted from @see Ezsp.ezspIncomingMessageHandler @see Ezsp.ezspGpepIncomingMessageHandler
@@ -1164,48 +1159,6 @@ class EmberAdapter extends __1.Adapter {
1164
1159
  nextZDORequestSequence() {
1165
1160
  return (this.zdoRequestSequence = ++this.zdoRequestSequence & APPLICATION_ZDO_SEQUENCE_MASK);
1166
1161
  }
1167
- /**
1168
- * ZDO
1169
- *
1170
- * @param destination
1171
- * @param clusterId uint16_t
1172
- * @param messageContents Content of the ZDO request (sequence to be assigned at index zero)
1173
- * @param options
1174
- * @returns status Indicates success or failure (with reason) of send
1175
- * @returns apsFrame The APS Frame resulting of the request being built and sent (`sequence` set from stack-given value).
1176
- * @returns messageTag The tag passed to ezspSend${x} function.
1177
- */
1178
- async sendZDORequest(destination, clusterId, messageContents, options) {
1179
- const messageTag = this.nextZDORequestSequence();
1180
- messageContents[0] = messageTag;
1181
- const apsFrame = {
1182
- profileId: Zdo.ZDO_PROFILE_ID,
1183
- clusterId,
1184
- sourceEndpoint: Zdo.ZDO_ENDPOINT,
1185
- destinationEndpoint: Zdo.ZDO_ENDPOINT,
1186
- options,
1187
- groupId: 0,
1188
- sequence: 0, // set by stack
1189
- };
1190
- if (destination === ZSpec.BroadcastAddress.DEFAULT ||
1191
- destination === ZSpec.BroadcastAddress.RX_ON_WHEN_IDLE ||
1192
- destination === ZSpec.BroadcastAddress.SLEEPY) {
1193
- logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} BROADCAST to=${destination} messageTag=${messageTag} messageContents=${messageContents.toString('hex')}]`, NS);
1194
- const [status, apsSequence] = await this.ezsp.ezspSendBroadcast(ZSpec.NULL_NODE_ID, // alias
1195
- destination, 0, // nwkSequence
1196
- apsFrame, ZDO_REQUEST_RADIUS, messageTag, messageContents);
1197
- apsFrame.sequence = apsSequence;
1198
- logger_1.logger.debug(`~~~> [SENT ZDO type=BROADCAST apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_1.SLStatus[status]}`, NS);
1199
- return [status, apsFrame, messageTag];
1200
- }
1201
- else {
1202
- logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} UNICAST to=${destination} messageTag=${messageTag} messageContents=${messageContents.toString('hex')}]`, NS);
1203
- const [status, apsSequence] = await this.ezsp.ezspSendUnicast(enums_1.EmberOutgoingMessageType.DIRECT, destination, apsFrame, messageTag, messageContents);
1204
- apsFrame.sequence = apsSequence;
1205
- logger_1.logger.debug(`~~~> [SENT ZDO type=DIRECT apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_1.SLStatus[status]}`, NS);
1206
- return [status, apsFrame, messageTag];
1207
- }
1208
- }
1209
1162
  //---- END Ember ZDO
1210
1163
  //-- START Adapter implementation
1211
1164
  /* istanbul ignore next */
@@ -1362,16 +1315,11 @@ class EmberAdapter extends __1.Adapter {
1362
1315
  }
1363
1316
  // queued
1364
1317
  async changeChannel(newChannel) {
1365
- return await this.queue.execute(async () => {
1366
- this.checkInterpanLock();
1367
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.NWK_UPDATE_REQUEST, [newChannel], 0xfe, undefined, undefined, undefined);
1368
- const [status] = await this.sendZDORequest(ZSpec.BroadcastAddress.SLEEPY, Zdo.ClusterId.NWK_UPDATE_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1369
- if (status !== enums_1.SLStatus.OK) {
1370
- throw new Error(`[ZDO] Failed broadcast channel change to '${newChannel}' with status=${enums_1.SLStatus[status]}.`);
1371
- }
1372
- await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED }, DEFAULT_NETWORK_REQUEST_TIMEOUT * 2, // observed to ~9sec
1373
- '[ZDO] Change Channel');
1374
- });
1318
+ const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
1319
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, [newChannel], 0xfe, undefined, undefined, undefined);
1320
+ await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.SLEEPY, clusterId, zdoPayload, true /* handled below */);
1321
+ await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED }, DEFAULT_NETWORK_REQUEST_TIMEOUT * 2, // observed to ~9sec
1322
+ '[ZDO] Change Channel');
1375
1323
  }
1376
1324
  // queued
1377
1325
  async setTransmitPower(value) {
@@ -1444,9 +1392,59 @@ class EmberAdapter extends __1.Adapter {
1444
1392
  promise: waiter.start().promise,
1445
1393
  };
1446
1394
  }
1447
- //---- ZDO
1395
+ async sendZdo(ieeeAddress, networkAddress, clusterId, payload, disableResponse) {
1396
+ return await this.queue.execute(async () => {
1397
+ this.checkInterpanLock();
1398
+ const clusterName = Zdo.ClusterId[clusterId];
1399
+ const messageTag = this.nextZDORequestSequence();
1400
+ payload[0] = messageTag;
1401
+ const apsFrame = {
1402
+ profileId: Zdo.ZDO_PROFILE_ID,
1403
+ clusterId,
1404
+ sourceEndpoint: Zdo.ZDO_ENDPOINT,
1405
+ destinationEndpoint: Zdo.ZDO_ENDPOINT,
1406
+ options: exports.DEFAULT_APS_OPTIONS,
1407
+ groupId: 0,
1408
+ sequence: 0, // set by stack
1409
+ };
1410
+ let status;
1411
+ let apsSequence;
1412
+ if (ZSpec.Utils.isBroadcastAddress(networkAddress)) {
1413
+ logger_1.logger.debug(() => `~~~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag} payload=${payload.toString('hex')}]`, NS);
1414
+ [status, apsSequence] = await this.ezsp.ezspSendBroadcast(ZSpec.NULL_NODE_ID, // alias
1415
+ networkAddress, 0, // nwkSequence
1416
+ apsFrame, ZDO_REQUEST_RADIUS, messageTag, payload);
1417
+ apsFrame.sequence = apsSequence;
1418
+ logger_1.logger.debug(`~~~> [SENT ZDO BROADCAST messageTag=${messageTag} apsSequence=${apsSequence} status=${enums_1.SLStatus[status]}]`, NS);
1419
+ if (status !== enums_1.SLStatus.OK) {
1420
+ throw new Error(`~x~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1421
+ }
1422
+ }
1423
+ else {
1424
+ logger_1.logger.debug(() => `~~~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag} payload=${payload.toString('hex')}]`, NS);
1425
+ [status, apsSequence] = await this.ezsp.ezspSendUnicast(enums_1.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, messageTag, payload);
1426
+ apsFrame.sequence = apsSequence;
1427
+ logger_1.logger.debug(`~~~> [SENT ZDO UNICAST messageTag=${messageTag} apsSequence=${apsSequence} status=${enums_1.SLStatus[status]}]`, NS);
1428
+ if (status !== enums_1.SLStatus.OK) {
1429
+ throw new Error(`~x~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1430
+ }
1431
+ }
1432
+ if (!disableResponse) {
1433
+ const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
1434
+ /* istanbul ignore else */
1435
+ if (responseClusterId) {
1436
+ return await this.oneWaitress.startWaitingFor({
1437
+ target: responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? ieeeAddress : networkAddress,
1438
+ apsFrame,
1439
+ zdoResponseClusterId: responseClusterId,
1440
+ }, DEFAULT_REQUEST_TIMEOUT);
1441
+ }
1442
+ }
1443
+ }, networkAddress /* TODO: replace with ieeeAddress once zdo moved upstream */);
1444
+ }
1448
1445
  // queued, non-InterPAN
1449
1446
  async permitJoin(seconds, networkAddress) {
1447
+ const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
1450
1448
  const preJoining = async () => {
1451
1449
  if (seconds) {
1452
1450
  const plaintextKey = { contents: Buffer.from(consts_1.ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY) };
@@ -1474,62 +1472,49 @@ class EmberAdapter extends __1.Adapter {
1474
1472
  };
1475
1473
  if (networkAddress) {
1476
1474
  // specific device that is not `Coordinator`
1477
- return await this.queue.execute(async () => {
1475
+ await this.queue.execute(async () => {
1478
1476
  this.checkInterpanLock();
1479
1477
  await preJoining();
1480
- // `authentication`: TC significance always 1 (zb specs)
1481
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.PERMIT_JOINING_REQUEST, seconds, 1, []);
1482
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1483
- if (status !== enums_1.SLStatus.OK) {
1484
- throw new Error(`[ZDO] Failed permit joining request for '${networkAddress}' with status=${enums_1.SLStatus[status]}.`);
1485
- }
1486
- await this.oneWaitress.startWaitingFor({
1487
- target: networkAddress,
1488
- apsFrame,
1489
- responseClusterId: Zdo.ClusterId.PERMIT_JOINING_RESPONSE,
1490
- }, DEFAULT_REQUEST_TIMEOUT);
1491
1478
  });
1479
+ // `authentication`: TC significance always 1 (zb specs)
1480
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
1481
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1482
+ /* istanbul ignore next */
1483
+ if (!Zdo.Buffalo.checkStatus(result)) {
1484
+ // TODO: will disappear once moved upstream
1485
+ throw new Zdo.StatusError(result[0]);
1486
+ }
1492
1487
  }
1493
1488
  else {
1494
1489
  // coordinator-only (0), or all
1495
- return await this.queue.execute(async () => {
1490
+ await this.queue.execute(async () => {
1496
1491
  this.checkInterpanLock();
1497
1492
  await preJoining();
1498
- const status = await this.ezsp.ezspPermitJoining(seconds);
1499
- if (status !== enums_1.SLStatus.OK) {
1500
- throw new Error(`[ZDO] Failed coordinator permit joining request with status=${enums_1.SLStatus[status]}.`);
1501
- }
1502
- logger_1.logger.debug(`Permit joining on coordinator for ${seconds} sec.`, NS);
1503
- // broadcast permit joining ZDO
1504
- if (networkAddress === undefined) {
1505
- // `authentication`: TC significance always 1 (zb specs)
1506
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.PERMIT_JOINING_REQUEST, seconds, 1, []);
1507
- const [bcStatus] = await this.sendZDORequest(ZSpec.BroadcastAddress.DEFAULT, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1508
- if (bcStatus !== enums_1.SLStatus.OK) {
1509
- // don't throw, coordinator succeeded at least
1510
- logger_1.logger.error(`[ZDO] Failed broadcast permit joining request with status=${enums_1.SLStatus[bcStatus]}.`, NS);
1511
- }
1512
- }
1513
1493
  });
1494
+ const status = await this.ezsp.ezspPermitJoining(seconds);
1495
+ if (status !== enums_1.SLStatus.OK) {
1496
+ throw new Error(`[ZDO] Failed coordinator permit joining request with status=${enums_1.SLStatus[status]}.`);
1497
+ }
1498
+ logger_1.logger.debug(`Permit joining on coordinator for ${seconds} sec.`, NS);
1499
+ // broadcast permit joining ZDO
1500
+ if (networkAddress === undefined) {
1501
+ // `authentication`: TC significance always 1 (zb specs)
1502
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
1503
+ await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
1504
+ }
1514
1505
  }
1515
1506
  }
1516
1507
  // queued, non-InterPAN
1517
1508
  async lqi(networkAddress) {
1518
- return await this.queue.execute(async () => {
1519
- this.checkInterpanLock();
1520
- const neighbors = [];
1521
- const request = async (startIndex) => {
1522
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.LQI_TABLE_REQUEST, startIndex);
1523
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LQI_TABLE_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1524
- if (status !== enums_1.SLStatus.OK) {
1525
- throw new Error(`[ZDO] Failed LQI request for '${networkAddress}' (index '${startIndex}') with status=${enums_1.SLStatus[status]}.`);
1526
- }
1527
- const result = await this.oneWaitress.startWaitingFor({
1528
- target: networkAddress,
1529
- apsFrame,
1530
- responseClusterId: Zdo.ClusterId.LQI_TABLE_RESPONSE,
1531
- }, DEFAULT_REQUEST_TIMEOUT);
1532
- for (const entry of result.entryList) {
1509
+ const clusterId = Zdo.ClusterId.LQI_TABLE_REQUEST;
1510
+ const neighbors = [];
1511
+ const request = async (startIndex) => {
1512
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
1513
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1514
+ /* istanbul ignore else */
1515
+ if (Zdo.Buffalo.checkStatus(result)) {
1516
+ const payload = result[1];
1517
+ for (const entry of payload.entryList) {
1533
1518
  neighbors.push({
1534
1519
  ieeeAddr: entry.eui64,
1535
1520
  networkAddress: entry.nwkAddress,
@@ -1538,69 +1523,65 @@ class EmberAdapter extends __1.Adapter {
1538
1523
  depth: entry.depth,
1539
1524
  });
1540
1525
  }
1541
- return [result.neighborTableEntries, result.entryList.length];
1542
- };
1543
- let [tableEntries, entryCount] = await request(0);
1544
- const size = tableEntries;
1545
- let nextStartIndex = entryCount;
1546
- while (neighbors.length < size) {
1547
- [tableEntries, entryCount] = await request(nextStartIndex);
1548
- nextStartIndex += entryCount;
1549
- }
1550
- return { neighbors };
1551
- }, networkAddress);
1526
+ return [payload.neighborTableEntries, payload.entryList.length];
1527
+ }
1528
+ else {
1529
+ // TODO: will disappear once moved upstream
1530
+ throw new Zdo.StatusError(result[0]);
1531
+ }
1532
+ };
1533
+ let [tableEntries, entryCount] = await request(0);
1534
+ const size = tableEntries;
1535
+ let nextStartIndex = entryCount;
1536
+ while (neighbors.length < size) {
1537
+ [tableEntries, entryCount] = await request(nextStartIndex);
1538
+ nextStartIndex += entryCount;
1539
+ }
1540
+ return { neighbors };
1552
1541
  }
1553
1542
  // queued, non-InterPAN
1554
1543
  async routingTable(networkAddress) {
1555
- return await this.queue.execute(async () => {
1556
- this.checkInterpanLock();
1557
- const table = [];
1558
- const request = async (startIndex) => {
1559
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.ROUTING_TABLE_REQUEST, startIndex);
1560
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ROUTING_TABLE_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1561
- if (status !== enums_1.SLStatus.OK) {
1562
- throw new Error(`[ZDO] Failed routing table request for '${networkAddress}' (index '${startIndex}') with status=${enums_1.SLStatus[status]}.`);
1563
- }
1564
- const result = await this.oneWaitress.startWaitingFor({
1565
- target: networkAddress,
1566
- apsFrame,
1567
- responseClusterId: Zdo.ClusterId.ROUTING_TABLE_RESPONSE,
1568
- }, DEFAULT_REQUEST_TIMEOUT);
1569
- for (const entry of result.entryList) {
1544
+ const clusterId = Zdo.ClusterId.ROUTING_TABLE_REQUEST;
1545
+ const table = [];
1546
+ const request = async (startIndex) => {
1547
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
1548
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1549
+ /* istanbul ignore else */
1550
+ if (Zdo.Buffalo.checkStatus(result)) {
1551
+ const payload = result[1];
1552
+ for (const entry of payload.entryList) {
1570
1553
  table.push({
1571
1554
  destinationAddress: entry.destinationAddress,
1572
1555
  status: entry.status,
1573
1556
  nextHop: entry.nextHopAddress,
1574
1557
  });
1575
1558
  }
1576
- return [result.routingTableEntries, result.entryList.length];
1577
- };
1578
- let [tableEntries, entryCount] = await request(0);
1579
- const size = tableEntries;
1580
- let nextStartIndex = entryCount;
1581
- while (table.length < size) {
1582
- [tableEntries, entryCount] = await request(nextStartIndex);
1583
- nextStartIndex += entryCount;
1584
- }
1585
- return { table };
1586
- }, networkAddress);
1559
+ return [payload.routingTableEntries, payload.entryList.length];
1560
+ }
1561
+ else {
1562
+ // TODO: will disappear once moved upstream
1563
+ throw new Zdo.StatusError(result[0]);
1564
+ }
1565
+ };
1566
+ let [tableEntries, entryCount] = await request(0);
1567
+ const size = tableEntries;
1568
+ let nextStartIndex = entryCount;
1569
+ while (table.length < size) {
1570
+ [tableEntries, entryCount] = await request(nextStartIndex);
1571
+ nextStartIndex += entryCount;
1572
+ }
1573
+ return { table };
1587
1574
  }
1588
1575
  // queued, non-InterPAN
1589
1576
  async nodeDescriptor(networkAddress) {
1590
- return await this.queue.execute(async () => {
1591
- this.checkInterpanLock();
1592
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST, networkAddress);
1593
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1594
- if (status !== enums_1.SLStatus.OK) {
1595
- throw new Error(`[ZDO] Failed node descriptor request for '${networkAddress}' with status=${enums_1.SLStatus[status]}.`);
1596
- }
1597
- const result = await this.oneWaitress.startWaitingFor({
1598
- target: networkAddress,
1599
- apsFrame,
1600
- responseClusterId: Zdo.ClusterId.NODE_DESCRIPTOR_RESPONSE,
1601
- }, DEFAULT_REQUEST_TIMEOUT);
1577
+ const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
1578
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
1579
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1580
+ /* istanbul ignore else */
1581
+ if (Zdo.Buffalo.checkStatus(result)) {
1582
+ const payload = result[1];
1602
1583
  let type = 'Unknown';
1603
- switch (result.logicalType) {
1584
+ switch (payload.logicalType) {
1604
1585
  case 0x0:
1605
1586
  type = 'Coordinator';
1606
1587
  break;
@@ -1612,105 +1593,90 @@ class EmberAdapter extends __1.Adapter {
1612
1593
  break;
1613
1594
  }
1614
1595
  /* istanbul ignore else */
1615
- if (result.serverMask.stackComplianceRevision < CURRENT_ZIGBEE_SPEC_REVISION) {
1596
+ if (payload.serverMask.stackComplianceRevision < CURRENT_ZIGBEE_SPEC_REVISION) {
1616
1597
  // always 0 before rev. 21 where field was added
1617
- const rev = result.serverMask.stackComplianceRevision < 21 ? 'pre-21' : result.serverMask.stackComplianceRevision;
1598
+ const rev = payload.serverMask.stackComplianceRevision < 21 ? 'pre-21' : payload.serverMask.stackComplianceRevision;
1618
1599
  logger_1.logger.warning(`[ZDO] Device '${networkAddress}' is only compliant to revision '${rev}' of the ZigBee specification (current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS);
1619
1600
  }
1620
- return { type, manufacturerCode: result.manufacturerCode };
1621
- }, networkAddress);
1601
+ return { type, manufacturerCode: payload.manufacturerCode };
1602
+ }
1603
+ else {
1604
+ // TODO: will disappear once moved upstream
1605
+ throw new Zdo.StatusError(result[0]);
1606
+ }
1622
1607
  }
1623
1608
  // queued, non-InterPAN
1624
1609
  async activeEndpoints(networkAddress) {
1625
- return await this.queue.execute(async () => {
1626
- this.checkInterpanLock();
1627
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST, networkAddress);
1628
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1629
- if (status !== enums_1.SLStatus.OK) {
1630
- throw new Error(`[ZDO] Failed active endpoints request for '${networkAddress}' with status=${enums_1.SLStatus[status]}.`);
1631
- }
1632
- const result = await this.oneWaitress.startWaitingFor({
1633
- target: networkAddress,
1634
- apsFrame,
1635
- responseClusterId: Zdo.ClusterId.ACTIVE_ENDPOINTS_RESPONSE,
1636
- }, DEFAULT_REQUEST_TIMEOUT);
1637
- return { endpoints: result.endpointList };
1638
- }, networkAddress);
1610
+ const clusterId = Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST;
1611
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
1612
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1613
+ /* istanbul ignore else */
1614
+ if (Zdo.Buffalo.checkStatus(result)) {
1615
+ const payload = result[1];
1616
+ return { endpoints: payload.endpointList };
1617
+ }
1618
+ else {
1619
+ // TODO: will disappear once moved upstream
1620
+ throw new Zdo.StatusError(result[0]);
1621
+ }
1639
1622
  }
1640
1623
  // queued, non-InterPAN
1641
1624
  async simpleDescriptor(networkAddress, endpointID) {
1642
- return await this.queue.execute(async () => {
1643
- this.checkInterpanLock();
1644
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST, networkAddress, endpointID);
1645
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1646
- if (status !== enums_1.SLStatus.OK) {
1647
- throw new Error(`[ZDO] Failed simple descriptor request for '${networkAddress}' endpoint '${endpointID}' with status=${enums_1.SLStatus[status]}.`);
1648
- }
1649
- const result = await this.oneWaitress.startWaitingFor({
1650
- target: networkAddress,
1651
- apsFrame,
1652
- responseClusterId: Zdo.ClusterId.SIMPLE_DESCRIPTOR_RESPONSE,
1653
- }, DEFAULT_REQUEST_TIMEOUT);
1625
+ const clusterId = Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST;
1626
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress, endpointID);
1627
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1628
+ /* istanbul ignore else */
1629
+ if (Zdo.Buffalo.checkStatus(result)) {
1630
+ const payload = result[1];
1654
1631
  return {
1655
- profileID: result.profileId,
1656
- endpointID: result.endpoint,
1657
- deviceID: result.deviceId,
1658
- inputClusters: result.inClusterList,
1659
- outputClusters: result.outClusterList,
1632
+ profileID: payload.profileId,
1633
+ endpointID: payload.endpoint,
1634
+ deviceID: payload.deviceId,
1635
+ inputClusters: payload.inClusterList,
1636
+ outputClusters: payload.outClusterList,
1660
1637
  };
1661
- }, networkAddress);
1638
+ }
1639
+ else {
1640
+ // TODO: will disappear once moved upstream
1641
+ throw new Zdo.StatusError(result[0]);
1642
+ }
1662
1643
  }
1663
1644
  // queued, non-InterPAN
1664
1645
  async bind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
1665
- return await this.queue.execute(async () => {
1666
- this.checkInterpanLock();
1667
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.BIND_REQUEST, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
1668
- destinationAddressOrGroup, // not used with UNICAST_BINDING
1669
- destinationEndpoint ?? 0);
1670
- const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.BIND_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1671
- if (status !== enums_1.SLStatus.OK) {
1672
- throw new Error(`[ZDO] Failed bind request for '${destinationNetworkAddress}' destination '${destinationAddressOrGroup}' endpoint '${destinationEndpoint}' with status=${enums_1.SLStatus[status]}.`);
1673
- }
1674
- await this.oneWaitress.startWaitingFor({
1675
- target: destinationNetworkAddress,
1676
- apsFrame,
1677
- responseClusterId: Zdo.ClusterId.BIND_RESPONSE,
1678
- }, DEFAULT_REQUEST_TIMEOUT);
1679
- }, destinationNetworkAddress);
1646
+ const clusterId = Zdo.ClusterId.BIND_REQUEST;
1647
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
1648
+ destinationAddressOrGroup, // not used with UNICAST_BINDING
1649
+ destinationEndpoint ?? 0);
1650
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
1651
+ /* istanbul ignore next */
1652
+ if (!Zdo.Buffalo.checkStatus(result)) {
1653
+ // TODO: will disappear once moved upstream
1654
+ throw new Zdo.StatusError(result[0]);
1655
+ }
1680
1656
  }
1681
1657
  // queued, non-InterPAN
1682
1658
  async unbind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
1683
- return await this.queue.execute(async () => {
1684
- this.checkInterpanLock();
1685
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.UNBIND_REQUEST, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
1686
- destinationAddressOrGroup, // not used with UNICAST_BINDING
1687
- destinationEndpoint ?? 0);
1688
- const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.UNBIND_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1689
- if (status !== enums_1.SLStatus.OK) {
1690
- throw new Error(`[ZDO] Failed unbind request for '${destinationNetworkAddress}' destination '${destinationAddressOrGroup}' endpoint '${destinationEndpoint}' with status=${enums_1.SLStatus[status]}.`);
1691
- }
1692
- await this.oneWaitress.startWaitingFor({
1693
- target: destinationNetworkAddress,
1694
- apsFrame,
1695
- responseClusterId: Zdo.ClusterId.UNBIND_RESPONSE,
1696
- }, DEFAULT_REQUEST_TIMEOUT);
1697
- }, destinationNetworkAddress);
1659
+ const clusterId = Zdo.ClusterId.UNBIND_REQUEST;
1660
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
1661
+ destinationAddressOrGroup, // not used with UNICAST_BINDING
1662
+ destinationEndpoint ?? 0);
1663
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
1664
+ /* istanbul ignore next */
1665
+ if (!Zdo.Buffalo.checkStatus(result)) {
1666
+ // TODO: will disappear once moved upstream
1667
+ throw new Zdo.StatusError(result[0]);
1668
+ }
1698
1669
  }
1699
1670
  // queued, non-InterPAN
1700
1671
  async removeDevice(networkAddress, ieeeAddr) {
1701
- return await this.queue.execute(async () => {
1702
- this.checkInterpanLock();
1703
- const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, Zdo.ClusterId.LEAVE_REQUEST, ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
1704
- const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LEAVE_REQUEST, zdoPayload, exports.DEFAULT_APS_OPTIONS);
1705
- if (status !== enums_1.SLStatus.OK) {
1706
- throw new Error(`[ZDO] Failed remove device request for '${networkAddress}' target '${ieeeAddr}' with status=${enums_1.SLStatus[status]}.`);
1707
- }
1708
- await this.oneWaitress.startWaitingFor({
1709
- target: networkAddress,
1710
- apsFrame,
1711
- responseClusterId: Zdo.ClusterId.LEAVE_RESPONSE,
1712
- }, DEFAULT_REQUEST_TIMEOUT);
1713
- }, networkAddress);
1672
+ const clusterId = Zdo.ClusterId.LEAVE_REQUEST;
1673
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
1674
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1675
+ /* istanbul ignore next */
1676
+ if (!Zdo.Buffalo.checkStatus(result)) {
1677
+ // TODO: will disappear once moved upstream
1678
+ throw new Zdo.StatusError(result[0]);
1679
+ }
1714
1680
  }
1715
1681
  //---- ZCL
1716
1682
  // queued, non-InterPAN
@@ -1740,7 +1706,7 @@ class EmberAdapter extends __1.Adapter {
1740
1706
  const data = zclFrame.toBuffer();
1741
1707
  return await this.queue.execute(async () => {
1742
1708
  this.checkInterpanLock();
1743
- logger_1.logger.debug(() => `~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
1709
+ logger_1.logger.debug(() => `~~~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
1744
1710
  for (let i = 1; i <= QUEUE_MAX_SEND_ATTEMPTS; i++) {
1745
1711
  let status = enums_1.SLStatus.FAIL;
1746
1712
  try {
@@ -1767,7 +1733,7 @@ class EmberAdapter extends __1.Adapter {
1767
1733
  break;
1768
1734
  }
1769
1735
  else if (disableRecovery || i == QUEUE_MAX_SEND_ATTEMPTS) {
1770
- throw new Error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1736
+ throw new Error(`~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1771
1737
  }
1772
1738
  else if (status === enums_1.SLStatus.ZIGBEE_MAX_MESSAGE_LIMIT_REACHED || status === enums_1.SLStatus.BUSY) {
1773
1739
  await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);
@@ -1776,9 +1742,9 @@ class EmberAdapter extends __1.Adapter {
1776
1742
  await (0, utils_1.Wait)(QUEUE_NETWORK_DOWN_DEFER_MSEC);
1777
1743
  }
1778
1744
  else {
1779
- throw new Error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1745
+ throw new Error(`~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
1780
1746
  }
1781
- logger_1.logger.debug(`~x~> [ZCL to=${networkAddress}] Failed to send request attempt ${i}/${QUEUE_MAX_SEND_ATTEMPTS} with status=${enums_1.SLStatus[status]}.`, NS);
1747
+ logger_1.logger.debug(`~x~> [ZCL to=${ieeeAddr}:${networkAddress}] Failed to send request attempt ${i}/${QUEUE_MAX_SEND_ATTEMPTS} with status=${enums_1.SLStatus[status]}.`, NS);
1782
1748
  }
1783
1749
  if (commandResponseId !== undefined) {
1784
1750
  // NOTE: aps sequence number will have been set by send function
@@ -1809,11 +1775,11 @@ class EmberAdapter extends __1.Adapter {
1809
1775
  this.checkInterpanLock();
1810
1776
  logger_1.logger.debug(() => `~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
1811
1777
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1812
- const [status, messageTag] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.MULTICAST, apsFrame.groupId, // not used with MULTICAST
1778
+ const [status, messageTag] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.MULTICAST, groupID, // not used with MULTICAST
1813
1779
  apsFrame, data, 0, // alias
1814
1780
  0);
1815
1781
  if (status !== enums_1.SLStatus.OK) {
1816
- throw new Error(`~x~> [ZCL GROUP] Failed to send with status=${enums_1.SLStatus[status]}.`);
1782
+ throw new Error(`~x~> [ZCL GROUP groupId=${groupID}] Failed to send with status=${enums_1.SLStatus[status]}.`);
1817
1783
  }
1818
1784
  // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
1819
1785
  await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);
@@ -1839,7 +1805,7 @@ class EmberAdapter extends __1.Adapter {
1839
1805
  const [status, messageTag] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.BROADCAST, destination, apsFrame, data, 0, // alias
1840
1806
  0);
1841
1807
  if (status !== enums_1.SLStatus.OK) {
1842
- throw new Error(`~x~> [ZCL BROADCAST] Failed to send with status=${enums_1.SLStatus[status]}.`);
1808
+ throw new Error(`~x~> [ZCL BROADCAST destination=${destination}] Failed to send with status=${enums_1.SLStatus[status]}.`);
1843
1809
  }
1844
1810
  // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
1845
1811
  await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);