zigbee-herdsman 1.0.1 → 2.0.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 (140) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +23 -0
  3. package/dist/adapter/adapter.d.ts +8 -12
  4. package/dist/adapter/adapter.d.ts.map +1 -1
  5. package/dist/adapter/adapter.js +3 -0
  6. package/dist/adapter/adapter.js.map +1 -1
  7. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +7 -15
  8. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
  9. package/dist/adapter/deconz/adapter/deconzAdapter.js +154 -693
  10. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
  11. package/dist/adapter/deconz/driver/constants.d.ts +102 -56
  12. package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
  13. package/dist/adapter/deconz/driver/constants.js +1 -2
  14. package/dist/adapter/deconz/driver/constants.js.map +1 -1
  15. package/dist/adapter/deconz/driver/driver.d.ts.map +1 -1
  16. package/dist/adapter/deconz/driver/driver.js +46 -41
  17. package/dist/adapter/deconz/driver/driver.js.map +1 -1
  18. package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -1
  19. package/dist/adapter/deconz/driver/frameParser.js +174 -107
  20. package/dist/adapter/deconz/driver/frameParser.js.map +1 -1
  21. package/dist/adapter/ember/adapter/emberAdapter.d.ts +5 -22
  22. package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
  23. package/dist/adapter/ember/adapter/emberAdapter.js +92 -325
  24. package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
  25. package/dist/adapter/ember/adapter/oneWaitress.d.ts +17 -14
  26. package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
  27. package/dist/adapter/ember/adapter/oneWaitress.js +16 -42
  28. package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
  29. package/dist/adapter/events.d.ts +1 -9
  30. package/dist/adapter/events.d.ts.map +1 -1
  31. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +12 -19
  32. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
  33. package/dist/adapter/ezsp/adapter/ezspAdapter.js +90 -272
  34. package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
  35. package/dist/adapter/ezsp/driver/driver.d.ts +6 -14
  36. package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
  37. package/dist/adapter/ezsp/driver/driver.js +56 -37
  38. package/dist/adapter/ezsp/driver/driver.js.map +1 -1
  39. package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -1
  40. package/dist/adapter/ezsp/driver/ezsp.js +3 -0
  41. package/dist/adapter/ezsp/driver/ezsp.js.map +1 -1
  42. package/dist/adapter/tstype.d.ts +1 -27
  43. package/dist/adapter/tstype.d.ts.map +1 -1
  44. package/dist/adapter/z-stack/adapter/manager.d.ts.map +1 -1
  45. package/dist/adapter/z-stack/adapter/manager.js +20 -10
  46. package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
  47. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +7 -15
  48. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
  49. package/dist/adapter/z-stack/adapter/zStackAdapter.js +128 -253
  50. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
  51. package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -1
  52. package/dist/adapter/z-stack/znp/definition.js +256 -302
  53. package/dist/adapter/z-stack/znp/definition.js.map +1 -1
  54. package/dist/adapter/z-stack/znp/tstype.d.ts +8 -8
  55. package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -1
  56. package/dist/adapter/z-stack/znp/utils.d.ts +3 -2
  57. package/dist/adapter/z-stack/znp/utils.d.ts.map +1 -1
  58. package/dist/adapter/z-stack/znp/utils.js +8 -7
  59. package/dist/adapter/z-stack/znp/utils.js.map +1 -1
  60. package/dist/adapter/z-stack/znp/znp.d.ts +3 -1
  61. package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -1
  62. package/dist/adapter/z-stack/znp/znp.js +31 -14
  63. package/dist/adapter/z-stack/znp/znp.js.map +1 -1
  64. package/dist/adapter/z-stack/znp/zpiObject.d.ts +5 -6
  65. package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -1
  66. package/dist/adapter/z-stack/znp/zpiObject.js +28 -11
  67. package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -1
  68. package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +8 -16
  69. package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -1
  70. package/dist/adapter/zboss/adapter/zbossAdapter.js +124 -162
  71. package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -1
  72. package/dist/adapter/zboss/commands.d.ts +3 -0
  73. package/dist/adapter/zboss/commands.d.ts.map +1 -1
  74. package/dist/adapter/zboss/commands.js +248 -205
  75. package/dist/adapter/zboss/commands.js.map +1 -1
  76. package/dist/adapter/zboss/driver.d.ts +4 -14
  77. package/dist/adapter/zboss/driver.d.ts.map +1 -1
  78. package/dist/adapter/zboss/driver.js +63 -89
  79. package/dist/adapter/zboss/driver.js.map +1 -1
  80. package/dist/adapter/zboss/enums.d.ts +24 -2
  81. package/dist/adapter/zboss/enums.d.ts.map +1 -1
  82. package/dist/adapter/zboss/enums.js +35 -3
  83. package/dist/adapter/zboss/enums.js.map +1 -1
  84. package/dist/adapter/zboss/frame.d.ts +6 -1
  85. package/dist/adapter/zboss/frame.d.ts.map +1 -1
  86. package/dist/adapter/zboss/frame.js +56 -11
  87. package/dist/adapter/zboss/frame.js.map +1 -1
  88. package/dist/adapter/zboss/uart.d.ts +1 -0
  89. package/dist/adapter/zboss/uart.d.ts.map +1 -1
  90. package/dist/adapter/zboss/uart.js +4 -2
  91. package/dist/adapter/zboss/uart.js.map +1 -1
  92. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts +5 -0
  93. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts.map +1 -0
  94. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js +44 -0
  95. package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js.map +1 -0
  96. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +6 -10
  97. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
  98. package/dist/adapter/zigate/adapter/zigateAdapter.js +99 -289
  99. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
  100. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
  101. package/dist/adapter/zigate/driver/buffaloZiGate.js +2 -18
  102. package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
  103. package/dist/adapter/zigate/driver/commandType.js +218 -218
  104. package/dist/adapter/zigate/driver/commandType.js.map +1 -1
  105. package/dist/adapter/zigate/driver/constants.d.ts +14 -8
  106. package/dist/adapter/zigate/driver/constants.d.ts.map +1 -1
  107. package/dist/adapter/zigate/driver/constants.js +36 -9
  108. package/dist/adapter/zigate/driver/constants.js.map +1 -1
  109. package/dist/adapter/zigate/driver/messageType.js +42 -42
  110. package/dist/adapter/zigate/driver/messageType.js.map +1 -1
  111. package/dist/adapter/zigate/driver/zigate.d.ts +17 -13
  112. package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
  113. package/dist/adapter/zigate/driver/zigate.js +83 -18
  114. package/dist/adapter/zigate/driver/zigate.js.map +1 -1
  115. package/dist/controller/controller.d.ts +5 -0
  116. package/dist/controller/controller.d.ts.map +1 -1
  117. package/dist/controller/controller.js +143 -37
  118. package/dist/controller/controller.js.map +1 -1
  119. package/dist/controller/greenPower.js +3 -3
  120. package/dist/controller/greenPower.js.map +1 -1
  121. package/dist/controller/model/device.d.ts +8 -7
  122. package/dist/controller/model/device.d.ts.map +1 -1
  123. package/dist/controller/model/device.js +176 -72
  124. package/dist/controller/model/device.js.map +1 -1
  125. package/dist/controller/model/endpoint.d.ts +1 -0
  126. package/dist/controller/model/endpoint.d.ts.map +1 -1
  127. package/dist/controller/model/endpoint.js +27 -4
  128. package/dist/controller/model/endpoint.js.map +1 -1
  129. package/dist/zspec/zdo/buffaloZdo.d.ts +1 -139
  130. package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
  131. package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
  132. package/dist/zspec/zdo/definition/tstypes.d.ts +168 -1
  133. package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -1
  134. package/dist/zspec/zdo/definition/tstypes.js +1 -0
  135. package/dist/zspec/zdo/definition/tstypes.js.map +1 -1
  136. package/dist/zspec/zdo/utils.d.ts +2 -3
  137. package/dist/zspec/zdo/utils.d.ts.map +1 -1
  138. package/dist/zspec/zdo/utils.js +3 -4
  139. package/dist/zspec/zdo/utils.js.map +1 -1
  140. package/package.json +5 -4
@@ -28,11 +28,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  const assert_1 = __importDefault(require("assert"));
31
- const __1 = require("../../..");
32
31
  const device_1 = __importDefault(require("../../../controller/model/device"));
33
32
  const utils_1 = require("../../../utils");
34
33
  const logger_1 = require("../../../utils/logger");
34
+ const ZSpec = __importStar(require("../../../zspec"));
35
35
  const Zcl = __importStar(require("../../../zspec/zcl"));
36
+ const Zdo = __importStar(require("../../../zspec/zdo"));
36
37
  const adapter_1 = __importDefault(require("../../adapter"));
37
38
  const constants_1 = __importDefault(require("../driver/constants"));
38
39
  const driver_1 = __importDefault(require("../driver/driver"));
@@ -40,18 +41,18 @@ const frameParser_1 = __importStar(require("../driver/frameParser"));
40
41
  const NS = 'zh:deconz';
41
42
  class DeconzAdapter extends adapter_1.default {
42
43
  driver;
43
- queue;
44
44
  openRequestsQueue;
45
45
  transactionID;
46
46
  frameParserEvent = frameParser_1.frameParserEvents;
47
- joinPermitted;
48
47
  fwVersion;
49
48
  waitress;
50
49
  TX_OPTIONS = 0x00; // No APS ACKS
50
+ joinPermitted = false;
51
51
  constructor(networkOptions, serialPortOptions, backupPath, adapterOptions) {
52
52
  super(networkOptions, serialPortOptions, backupPath, adapterOptions);
53
53
  this.hasZdoMessageOverhead = true;
54
- const concurrent = this.adapterOptions && this.adapterOptions.concurrent ? this.adapterOptions.concurrent : 2;
54
+ this.manufacturerID = Zcl.ManufacturerCode.DRESDEN_ELEKTRONIK_INGENIEURTECHNIK_GMBH;
55
+ // const concurrent = this.adapterOptions && this.adapterOptions.concurrent ? this.adapterOptions.concurrent : 2;
55
56
  // TODO: https://github.com/Koenkk/zigbee2mqtt/issues/4884#issuecomment-728903121
56
57
  const delay = this.adapterOptions && typeof this.adapterOptions.delay === 'number' ? this.adapterOptions.delay : 0;
57
58
  this.waitress = new utils_1.Waitress(this.waitressValidator, this.waitressTimeoutFormatter);
@@ -63,10 +64,8 @@ class DeconzAdapter extends adapter_1.default {
63
64
  this.driver.on('rxFrame', (frame) => {
64
65
  (0, frameParser_1.default)(frame);
65
66
  });
66
- this.queue = new utils_1.Queue(concurrent);
67
67
  this.transactionID = 0;
68
68
  this.openRequestsQueue = [];
69
- this.joinPermitted = false;
70
69
  this.fwVersion = undefined;
71
70
  this.frameParserEvent.on('receivedDataPayload', (data) => {
72
71
  this.checkReceivedDataPayload(data);
@@ -77,9 +76,6 @@ class DeconzAdapter extends adapter_1.default {
77
76
  setInterval(() => {
78
77
  this.checkReceivedDataPayload(null);
79
78
  }, 1000);
80
- setTimeout(async () => {
81
- await this.checkCoordinatorSimpleDescriptor(false);
82
- }, 3000);
83
79
  }
84
80
  static async isValidPath(path) {
85
81
  return await driver_1.default.isValidPath(path);
@@ -160,7 +156,7 @@ class DeconzAdapter extends adapter_1.default {
160
156
  }
161
157
  try {
162
158
  await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.CHANNEL_MASK, setChannelMask);
163
- await this.sleep(500);
159
+ await (0, utils_1.Wait)(500);
164
160
  changed = true;
165
161
  }
166
162
  catch (error) {
@@ -172,7 +168,7 @@ class DeconzAdapter extends adapter_1.default {
172
168
  logger_1.logger.debug('panid in configuration.yaml (' + this.networkOptions.panID + ') differs from current panid (' + panid + '). Changing panid.', NS);
173
169
  try {
174
170
  await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.PAN_ID, this.networkOptions.panID);
175
- await this.sleep(500);
171
+ await (0, utils_1.Wait)(500);
176
172
  changed = true;
177
173
  }
178
174
  catch (error) {
@@ -188,7 +184,7 @@ class DeconzAdapter extends adapter_1.default {
188
184
  '). Changing extended panid.', NS);
189
185
  try {
190
186
  await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.APS_EXT_PAN_ID, this.networkOptions.extendedPanID);
191
- await this.sleep(500);
187
+ await (0, utils_1.Wait)(500);
192
188
  changed = true;
193
189
  }
194
190
  catch (error) {
@@ -200,7 +196,7 @@ class DeconzAdapter extends adapter_1.default {
200
196
  logger_1.logger.debug('network key in configuration.yaml (hidden) differs from current network key (' + networkKey + '). Changing network key.', NS);
201
197
  try {
202
198
  await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.NETWORK_KEY, this.networkOptions.networkKey);
203
- await this.sleep(500);
199
+ await (0, utils_1.Wait)(500);
204
200
  changed = true;
205
201
  }
206
202
  catch (error) {
@@ -209,75 +205,49 @@ class DeconzAdapter extends adapter_1.default {
209
205
  }
210
206
  if (changed) {
211
207
  await this.driver.changeNetworkStateRequest(constants_1.default.PARAM.Network.NET_OFFLINE);
212
- await this.sleep(2000);
208
+ await (0, utils_1.Wait)(2000);
213
209
  await this.driver.changeNetworkStateRequest(constants_1.default.PARAM.Network.NET_CONNECTED);
214
- await this.sleep(2000);
210
+ await (0, utils_1.Wait)(2000);
215
211
  }
212
+ // write endpoints
213
+ //[ sd1 ep proId devId vers #inCl iCl1 iCl2 iCl3 iCl4 iCl5 #outC oCl1 oCl2 oCl3 oCl4 ]
214
+ const sd = [
215
+ 0x00, 0x01, 0x04, 0x01, 0x05, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x19, 0x00, 0x01, 0x05, 0x04, 0x01, 0x00, 0x20, 0x00,
216
+ 0x00, 0x05, 0x02, 0x05,
217
+ ];
218
+ const sd1 = sd.reverse();
219
+ await this.driver.writeParameterRequest(constants_1.default.PARAM.STK.Endpoint, sd1);
216
220
  return 'resumed';
217
221
  }
218
222
  async stop() {
219
223
  await this.driver.close();
220
224
  }
221
- async getCoordinator() {
222
- const ieeeAddr = await this.driver.readParameterRequest(constants_1.default.PARAM.Network.MAC);
223
- const nwkAddr = await this.driver.readParameterRequest(constants_1.default.PARAM.Network.NWK_ADDRESS);
224
- const endpoints = [
225
- {
226
- ID: 0x01,
227
- profileID: 0x0104,
228
- deviceID: 0x0005,
229
- inputClusters: [0x0000, 0x0006, 0x000a, 0x0019, 0x0501],
230
- outputClusters: [0x0001, 0x0020, 0x0500, 0x0502],
231
- },
232
- {
233
- ID: 0xf2,
234
- profileID: 0xa1e0,
235
- deviceID: 0x0064,
236
- inputClusters: [],
237
- outputClusters: [0x0021],
238
- },
239
- ];
240
- return {
241
- networkAddress: nwkAddr,
242
- manufacturerID: 0x1135,
243
- ieeeAddr: ieeeAddr,
244
- endpoints,
245
- };
225
+ async getCoordinatorIEEE() {
226
+ return (await this.driver.readParameterRequest(constants_1.default.PARAM.Network.MAC));
246
227
  }
247
228
  async permitJoin(seconds, networkAddress) {
248
- const transactionID = this.nextTransactionID();
249
- const request = {};
250
- const zdpFrame = [transactionID, seconds, 0]; // tc_significance 1 or 0 ?
251
- request.requestId = transactionID;
252
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
253
- request.destAddr16 = networkAddress || 0xfffc;
254
- request.destEndpoint = 0;
255
- request.profileId = 0;
256
- request.clusterId = 0x36; // permit join
257
- request.srcEndpoint = 0;
258
- request.asduLength = 3;
259
- request.asduPayload = zdpFrame;
260
- request.txOptions = 0;
261
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
262
- request.timeout = 5;
263
- try {
264
- await this.driver.enqueueSendDataRequest(request);
265
- if (seconds === 0) {
266
- this.joinPermitted = false;
229
+ const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
230
+ if (networkAddress) {
231
+ // `authentication`: TC significance always 1 (zb specs)
232
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
233
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
234
+ /* istanbul ignore next */
235
+ if (!Zdo.Buffalo.checkStatus(result)) {
236
+ // TODO: will disappear once moved upstream
237
+ throw new Zdo.StatusError(result[0]);
267
238
  }
268
- else {
269
- this.joinPermitted = true;
270
- }
271
- await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.PERMIT_JOIN, seconds);
272
- logger_1.logger.debug('PERMIT_JOIN - ' + seconds + ' seconds', NS);
273
239
  }
274
- catch (error) {
275
- const msg = 'PERMIT_JOIN FAILED - ' + error;
276
- logger_1.logger.debug(msg, NS);
277
- // try again
278
- await this.permitJoin(seconds, networkAddress);
279
- //return Promise.reject(new Error(msg)); // do not reject
240
+ else {
241
+ await this.driver.writeParameterRequest(constants_1.default.PARAM.Network.PERMIT_JOIN, seconds);
242
+ logger_1.logger.debug(`Permit joining on coordinator for ${seconds} sec.`, NS);
243
+ // broadcast permit joining ZDO
244
+ if (networkAddress === undefined) {
245
+ // `authentication`: TC significance always 1 (zb specs)
246
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
247
+ await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
248
+ }
280
249
  }
250
+ this.joinPermitted = seconds !== 0;
281
251
  }
282
252
  async getCoordinatorVersion() {
283
253
  // product: number; transportrev: number; majorrel: number; minorrel: number; maintrel: number; revision: string;
@@ -316,396 +286,6 @@ class DeconzAdapter extends adapter_1.default {
316
286
  async reset(type) {
317
287
  return await Promise.reject(new Error('Reset is not supported'));
318
288
  }
319
- async lqi(networkAddress) {
320
- const neighbors = [];
321
- const add = (list) => {
322
- for (const entry of list) {
323
- const relationByte = entry.readUInt8(18);
324
- const extAddr = [];
325
- for (let i = 8; i < 16; i++) {
326
- extAddr.push(entry[i]);
327
- }
328
- neighbors.push({
329
- linkquality: entry.readUInt8(21),
330
- networkAddress: entry.readUInt16LE(16),
331
- ieeeAddr: this.driver.macAddrArrayToString(extAddr),
332
- relationship: (relationByte >> 1) & ((1 << 3) - 1),
333
- depth: entry.readUInt8(20),
334
- });
335
- }
336
- };
337
- const request = async (startIndex) => {
338
- const transactionID = this.nextTransactionID();
339
- const req = {};
340
- req.requestId = transactionID;
341
- req.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
342
- req.destAddr16 = networkAddress;
343
- req.destEndpoint = 0;
344
- req.profileId = 0;
345
- req.clusterId = 0x31; // mgmt_lqi_request
346
- req.srcEndpoint = 0;
347
- req.asduLength = 2;
348
- req.asduPayload = [transactionID, startIndex];
349
- req.txOptions = 0;
350
- req.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
351
- this.driver
352
- .enqueueSendDataRequest(req)
353
- .then(() => { })
354
- .catch(() => { });
355
- try {
356
- const d = await this.waitForData(networkAddress, 0, 0x8031);
357
- const data = d.asduPayload;
358
- if (data[1] !== 0) {
359
- // status
360
- throw new Error(`LQI for '${networkAddress}' failed`);
361
- }
362
- const tableList = [];
363
- const response = {
364
- status: data[1],
365
- tableEntrys: data[2],
366
- startIndex: data[3],
367
- tableListCount: data[4],
368
- tableList: tableList,
369
- };
370
- let tableEntry = [];
371
- let counter = 0;
372
- for (let i = 5; i < response.tableListCount * 22 + 5; i++) {
373
- // one tableentry = 22 bytes
374
- tableEntry.push(data[i]);
375
- counter++;
376
- if (counter === 22) {
377
- response.tableList.push(Buffer.from(tableEntry));
378
- tableEntry = [];
379
- counter = 0;
380
- }
381
- }
382
- logger_1.logger.debug('LQI RESPONSE - addr: 0x' +
383
- networkAddress.toString(16) +
384
- ' status: ' +
385
- response.status +
386
- ' read ' +
387
- (response.tableListCount + response.startIndex) +
388
- '/' +
389
- response.tableEntrys +
390
- ' entrys', NS);
391
- return response;
392
- }
393
- catch (error) {
394
- const msg = 'LQI REQUEST FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
395
- logger_1.logger.debug(msg, NS);
396
- return await Promise.reject(new Error(msg));
397
- }
398
- };
399
- let response = await request(0);
400
- add(response.tableList);
401
- let nextStartIndex = response.tableListCount;
402
- while (neighbors.length < response.tableEntrys) {
403
- response = await request(nextStartIndex);
404
- add(response.tableList);
405
- nextStartIndex += response.tableListCount;
406
- }
407
- return { neighbors };
408
- }
409
- async routingTable(networkAddress) {
410
- const table = [];
411
- const statusLookup = {
412
- 0: 'ACTIVE',
413
- 1: 'DISCOVERY_UNDERWAY',
414
- 2: 'DISCOVERY_FAILED',
415
- 3: 'INACTIVE',
416
- };
417
- const add = (list) => {
418
- for (const entry of list) {
419
- const statusByte = entry.readUInt8(2);
420
- const extAddr = [];
421
- for (let i = 8; i < 16; i++) {
422
- extAddr.push(entry[i]);
423
- }
424
- table.push({
425
- destinationAddress: entry.readUInt16LE(0),
426
- status: statusLookup[(statusByte >> 5) & ((1 << 3) - 1)],
427
- nextHop: entry.readUInt16LE(3),
428
- });
429
- }
430
- };
431
- const request = async (startIndex) => {
432
- const transactionID = this.nextTransactionID();
433
- const req = {};
434
- req.requestId = transactionID;
435
- req.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
436
- req.destAddr16 = networkAddress;
437
- req.destEndpoint = 0;
438
- req.profileId = 0;
439
- req.clusterId = 0x32; // mgmt_rtg_request
440
- req.srcEndpoint = 0;
441
- req.asduLength = 2;
442
- req.asduPayload = [transactionID, startIndex];
443
- req.txOptions = 0;
444
- req.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
445
- req.timeout = 30;
446
- this.driver
447
- .enqueueSendDataRequest(req)
448
- .then(() => { })
449
- .catch(() => { });
450
- try {
451
- const d = await this.waitForData(networkAddress, 0, 0x8032);
452
- const data = d.asduPayload;
453
- if (data[1] !== 0) {
454
- // status
455
- throw new Error(`Routingtables for '${networkAddress}' failed`);
456
- }
457
- const tableList = [];
458
- const response = {
459
- status: data[1],
460
- tableEntrys: data[2],
461
- startIndex: data[3],
462
- tableListCount: data[4],
463
- tableList: tableList,
464
- };
465
- let tableEntry = [];
466
- let counter = 0;
467
- for (let i = 5; i < response.tableListCount * 5 + 5; i++) {
468
- // one tableentry = 5 bytes
469
- tableEntry.push(data[i]);
470
- counter++;
471
- if (counter === 5) {
472
- response.tableList.push(Buffer.from(tableEntry));
473
- tableEntry = [];
474
- counter = 0;
475
- }
476
- }
477
- logger_1.logger.debug('ROUTING_TABLE RESPONSE - addr: 0x' +
478
- networkAddress.toString(16) +
479
- ' status: ' +
480
- response.status +
481
- ' read ' +
482
- (response.tableListCount + response.startIndex) +
483
- '/' +
484
- response.tableEntrys +
485
- ' entrys', NS);
486
- return response;
487
- }
488
- catch (error) {
489
- const msg = 'ROUTING_TABLE REQUEST FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
490
- logger_1.logger.debug(msg, NS);
491
- return await Promise.reject(new Error(msg));
492
- }
493
- };
494
- let response = await request(0);
495
- add(response.tableList);
496
- let nextStartIndex = response.tableListCount;
497
- while (table.length < response.tableEntrys) {
498
- response = await request(nextStartIndex);
499
- add(response.tableList);
500
- nextStartIndex += response.tableListCount;
501
- }
502
- return { table };
503
- }
504
- async nodeDescriptor(networkAddress) {
505
- const transactionID = this.nextTransactionID();
506
- const nwk1 = networkAddress & 0xff;
507
- const nwk2 = (networkAddress >> 8) & 0xff;
508
- const request = {};
509
- const zdpFrame = [transactionID, nwk1, nwk2];
510
- request.requestId = transactionID;
511
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
512
- request.destAddr16 = networkAddress;
513
- request.destEndpoint = 0;
514
- request.profileId = 0;
515
- request.clusterId = 0x02; // node descriptor
516
- request.srcEndpoint = 0;
517
- request.asduLength = 3;
518
- request.asduPayload = zdpFrame;
519
- request.txOptions = 0;
520
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
521
- request.timeout = 30;
522
- this.driver
523
- .enqueueSendDataRequest(request)
524
- .then(() => { })
525
- .catch(() => { });
526
- try {
527
- const d = await this.waitForData(networkAddress, 0, 0x8002);
528
- const data = d.asduPayload;
529
- const buf = Buffer.from(data);
530
- const logicaltype = data[4] & 7;
531
- const type = logicaltype === 1 ? 'Router' : logicaltype === 2 ? 'EndDevice' : logicaltype === 0 ? 'Coordinator' : 'Unknown';
532
- const manufacturer = buf.readUInt16LE(7);
533
- logger_1.logger.debug('RECEIVING NODE_DESCRIPTOR - addr: 0x' +
534
- networkAddress.toString(16) +
535
- ' type: ' +
536
- type +
537
- ' manufacturer: 0x' +
538
- manufacturer.toString(16), NS);
539
- return { manufacturerCode: manufacturer, type };
540
- }
541
- catch (error) {
542
- const msg = 'RECEIVING NODE_DESCRIPTOR FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
543
- logger_1.logger.debug(msg, NS);
544
- return await Promise.reject(new Error(msg));
545
- }
546
- }
547
- async activeEndpoints(networkAddress) {
548
- const transactionID = this.nextTransactionID();
549
- const nwk1 = networkAddress & 0xff;
550
- const nwk2 = (networkAddress >> 8) & 0xff;
551
- const request = {};
552
- const zdpFrame = [transactionID, nwk1, nwk2];
553
- request.requestId = transactionID;
554
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
555
- request.destAddr16 = networkAddress;
556
- request.destEndpoint = 0;
557
- request.profileId = 0;
558
- request.clusterId = 0x05; // active endpoints
559
- request.srcEndpoint = 0;
560
- request.asduLength = 3;
561
- request.asduPayload = zdpFrame;
562
- request.txOptions = 0;
563
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
564
- request.timeout = 30;
565
- this.driver
566
- .enqueueSendDataRequest(request)
567
- .then(() => { })
568
- .catch(() => { });
569
- try {
570
- const d = await this.waitForData(networkAddress, 0, 0x8005);
571
- const data = d.asduPayload;
572
- const buf = Buffer.from(data);
573
- const epCount = buf.readUInt8(4);
574
- const epList = [];
575
- for (let i = 5; i < epCount + 5; i++) {
576
- epList.push(buf.readUInt8(i));
577
- }
578
- logger_1.logger.debug('ACTIVE_ENDPOINTS - addr: 0x' + networkAddress.toString(16) + ' EP list: ' + epList, NS);
579
- return { endpoints: epList };
580
- }
581
- catch (error) {
582
- const msg = 'READING ACTIVE_ENDPOINTS FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
583
- logger_1.logger.debug(msg, NS);
584
- return await Promise.reject(new Error(msg));
585
- }
586
- }
587
- async simpleDescriptor(networkAddress, endpointID) {
588
- const transactionID = this.nextTransactionID();
589
- const nwk1 = networkAddress & 0xff;
590
- const nwk2 = (networkAddress >> 8) & 0xff;
591
- const request = {};
592
- const zdpFrame = [transactionID, nwk1, nwk2, endpointID];
593
- request.requestId = transactionID;
594
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
595
- request.destAddr16 = networkAddress;
596
- request.destEndpoint = 0;
597
- request.profileId = 0;
598
- request.clusterId = 0x04; // simple descriptor
599
- request.srcEndpoint = 0;
600
- request.asduLength = 4;
601
- request.asduPayload = zdpFrame;
602
- request.txOptions = 0;
603
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
604
- request.timeout = 30;
605
- this.driver
606
- .enqueueSendDataRequest(request)
607
- .then(() => { })
608
- .catch(() => { });
609
- try {
610
- const d = await this.waitForData(networkAddress, 0, 0x8004);
611
- const data = d.asduPayload;
612
- const buf = Buffer.from(data);
613
- const inCount = buf.readUInt8(11);
614
- const inClusters = [];
615
- let cIndex = 12;
616
- for (let i = 0; i < inCount; i++) {
617
- inClusters[i] = buf.readUInt16LE(cIndex);
618
- cIndex += 2;
619
- }
620
- const outCount = buf.readUInt8(12 + inCount * 2);
621
- const outClusters = [];
622
- cIndex = 13 + inCount * 2;
623
- for (let l = 0; l < outCount; l++) {
624
- outClusters[l] = buf.readUInt16LE(cIndex);
625
- cIndex += 2;
626
- }
627
- const simpleDesc = {
628
- profileID: buf.readUInt16LE(6),
629
- endpointID: buf.readUInt8(5),
630
- deviceID: buf.readUInt16LE(8),
631
- inputClusters: inClusters,
632
- outputClusters: outClusters,
633
- };
634
- logger_1.logger.debug('RECEIVING SIMPLE_DESCRIPTOR - addr: 0x' +
635
- networkAddress.toString(16) +
636
- ' EP:' +
637
- simpleDesc.endpointID +
638
- ' inClusters: ' +
639
- inClusters +
640
- ' outClusters: ' +
641
- outClusters, NS);
642
- return simpleDesc;
643
- }
644
- catch (error) {
645
- const msg = 'RECEIVING SIMPLE_DESCRIPTOR FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
646
- logger_1.logger.debug(msg, NS);
647
- return await Promise.reject(new Error(msg));
648
- }
649
- }
650
- async checkCoordinatorSimpleDescriptor(skip) {
651
- logger_1.logger.debug('checking coordinator simple descriptor', NS);
652
- let simpleDesc;
653
- if (skip === false) {
654
- try {
655
- simpleDesc = await this.simpleDescriptor(0x0, 1);
656
- }
657
- catch {
658
- /* empty */
659
- }
660
- if (simpleDesc == undefined) {
661
- await this.checkCoordinatorSimpleDescriptor(false);
662
- return;
663
- }
664
- logger_1.logger.debug('EP: ' + simpleDesc.endpointID, NS);
665
- logger_1.logger.debug('profile ID: ' + simpleDesc.profileID, NS);
666
- logger_1.logger.debug('device ID: ' + simpleDesc.deviceID, NS);
667
- for (let i = 0; i < simpleDesc.inputClusters.length; i++) {
668
- logger_1.logger.debug('input cluster: 0x' + simpleDesc.inputClusters[i].toString(16), NS);
669
- }
670
- for (let o = 0; o < simpleDesc.outputClusters.length; o++) {
671
- logger_1.logger.debug('output cluster: 0x' + simpleDesc.outputClusters[o].toString(16), NS);
672
- }
673
- let ok = true;
674
- if (simpleDesc.endpointID === 0x1) {
675
- if (!simpleDesc.inputClusters.includes(0x0) ||
676
- !simpleDesc.inputClusters.includes(0x0a) ||
677
- !simpleDesc.inputClusters.includes(0x06) ||
678
- !simpleDesc.inputClusters.includes(0x19) ||
679
- !simpleDesc.inputClusters.includes(0x0501) ||
680
- !simpleDesc.outputClusters.includes(0x01) ||
681
- !simpleDesc.outputClusters.includes(0x20) ||
682
- !simpleDesc.outputClusters.includes(0x500) ||
683
- !simpleDesc.outputClusters.includes(0x502)) {
684
- logger_1.logger.debug('missing cluster', NS);
685
- ok = false;
686
- }
687
- if (ok === true) {
688
- return;
689
- }
690
- }
691
- }
692
- logger_1.logger.debug('setting new simple descriptor', NS);
693
- try {
694
- //[ sd1 ep proId devId vers #inCl iCl1 iCl2 iCl3 iCl4 iCl5 #outC oCl1 oCl2 oCl3 oCl4 ]
695
- const sd = [
696
- 0x00, 0x01, 0x04, 0x01, 0x05, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x19, 0x00, 0x01, 0x05, 0x04, 0x01, 0x00, 0x20,
697
- 0x00, 0x00, 0x05, 0x02, 0x05,
698
- ];
699
- const sd1 = sd.reverse();
700
- await this.driver.writeParameterRequest(constants_1.default.PARAM.STK.Endpoint, sd1);
701
- }
702
- catch (error) {
703
- logger_1.logger.debug(`error setting simple descriptor: ${error} - try again`, NS);
704
- await this.checkCoordinatorSimpleDescriptor(true);
705
- return;
706
- }
707
- logger_1.logger.debug('success setting simple descriptor', NS);
708
- }
709
289
  waitFor(networkAddress, endpoint, frameType, direction, transactionSequenceNumber, clusterID, commandIdentifier, timeout) {
710
290
  const payload = {
711
291
  address: networkAddress,
@@ -720,24 +300,54 @@ class DeconzAdapter extends adapter_1.default {
720
300
  const cancel = () => this.waitress.remove(waiter.ID);
721
301
  return { promise: waiter.start().promise, cancel };
722
302
  }
303
+ async sendZdo(ieeeAddress, networkAddress, clusterId, payload, disableResponse) {
304
+ const transactionID = this.nextTransactionID();
305
+ payload[0] = transactionID;
306
+ const isNwkAddrRequest = clusterId === Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
307
+ const req = {
308
+ requestId: transactionID,
309
+ destAddrMode: isNwkAddrRequest ? constants_1.default.PARAM.addressMode.IEEE_ADDR : constants_1.default.PARAM.addressMode.NWK_ADDR,
310
+ destAddr16: isNwkAddrRequest ? undefined : networkAddress,
311
+ destAddr64: isNwkAddrRequest ? ieeeAddress : undefined,
312
+ destEndpoint: Zdo.ZDO_ENDPOINT,
313
+ profileId: Zdo.ZDO_PROFILE_ID,
314
+ clusterId,
315
+ srcEndpoint: Zdo.ZDO_ENDPOINT,
316
+ asduLength: payload.length,
317
+ asduPayload: payload,
318
+ txOptions: 0,
319
+ radius: constants_1.default.PARAM.txRadius.DEFAULT_RADIUS,
320
+ timeout: 30,
321
+ };
322
+ this.driver
323
+ .enqueueSendDataRequest(req)
324
+ .then(() => { })
325
+ .catch(() => { });
326
+ if (!disableResponse) {
327
+ const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
328
+ if (responseClusterId) {
329
+ const response = await this.waitForData(isNwkAddrRequest ? ieeeAddress : networkAddress, Zdo.ZDO_PROFILE_ID, responseClusterId);
330
+ return response.zdo;
331
+ }
332
+ }
333
+ }
723
334
  async sendZclFrameToEndpoint(ieeeAddr, networkAddress, endpoint, zclFrame, timeout, disableResponse, disableRecovery, sourceEndpoint) {
724
335
  const transactionID = this.nextTransactionID();
725
- const request = {};
726
- const pay = zclFrame.toBuffer();
727
- //logger.info("zclFramte.toBuffer:", NS);
728
- //logger.info(pay, NS);
729
- request.requestId = transactionID;
730
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
731
- request.destAddr16 = networkAddress;
732
- request.destEndpoint = endpoint;
733
- request.profileId = sourceEndpoint === 242 && endpoint === 242 ? 0xa1e0 : 0x104;
734
- request.clusterId = zclFrame.cluster.ID;
735
- request.srcEndpoint = sourceEndpoint || 1;
736
- request.asduLength = pay.length;
737
- request.asduPayload = [...pay];
738
- request.txOptions = this.TX_OPTIONS; // 0x00 normal; 0x04 APS ACK
739
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
740
- request.timeout = timeout;
336
+ const payload = zclFrame.toBuffer();
337
+ const request = {
338
+ requestId: transactionID,
339
+ destAddrMode: constants_1.default.PARAM.addressMode.NWK_ADDR,
340
+ destAddr16: networkAddress,
341
+ destEndpoint: endpoint,
342
+ profileId: sourceEndpoint === 242 && endpoint === 242 ? 0xa1e0 : 0x104,
343
+ clusterId: zclFrame.cluster.ID,
344
+ srcEndpoint: sourceEndpoint || 1,
345
+ asduLength: payload.length,
346
+ asduPayload: payload,
347
+ txOptions: this.TX_OPTIONS, // 0x00 normal, 0x04 APS ACK
348
+ radius: constants_1.default.PARAM.txRadius.DEFAULT_RADIUS,
349
+ timeout: timeout,
350
+ };
741
351
  const command = zclFrame.command;
742
352
  this.driver
743
353
  .enqueueSendDataRequest(request)
@@ -763,16 +373,14 @@ class DeconzAdapter extends adapter_1.default {
763
373
  try {
764
374
  let data = null;
765
375
  if ((command.response != undefined && !disableResponse) || !zclFrame.header.frameControl.disableDefaultResponse) {
766
- data = await this.waitForData(networkAddress, 0x104, zclFrame.cluster.ID, zclFrame.header.transactionSequenceNumber, request.timeout);
376
+ data = await this.waitForData(networkAddress, ZSpec.HA_PROFILE_ID, zclFrame.cluster.ID, zclFrame.header.transactionSequenceNumber, request.timeout);
767
377
  }
768
378
  if (data !== null) {
769
- const asdu = data.asduPayload;
770
- const buffer = Buffer.from(asdu);
771
379
  const response = {
772
380
  address: data.srcAddr16 ?? `0x${data.srcAddr64}`,
773
- data: buffer,
381
+ data: data.asduPayload,
774
382
  clusterID: zclFrame.cluster.ID,
775
- header: Zcl.Header.fromBuffer(buffer),
383
+ header: Zcl.Header.fromBuffer(data.asduPayload),
776
384
  endpoint: data.srcEndpoint,
777
385
  linkquality: data.lqi,
778
386
  groupID: data.srcAddrMode === 0x01 ? data.srcAddr16 : 0,
@@ -792,181 +400,43 @@ class DeconzAdapter extends adapter_1.default {
792
400
  }
793
401
  async sendZclFrameToGroup(groupID, zclFrame) {
794
402
  const transactionID = this.nextTransactionID();
795
- const request = {};
796
- const pay = zclFrame.toBuffer();
797
- logger_1.logger.debug('zclFrame to group - zclFrame.payload:', NS);
798
- logger_1.logger.debug(zclFrame.payload, NS);
799
- //logger.info("zclFramte.toBuffer:", NS);
800
- //logger.info(pay, NS);
801
- request.requestId = transactionID;
802
- request.destAddrMode = constants_1.default.PARAM.addressMode.GROUP_ADDR;
803
- request.destAddr16 = groupID;
804
- request.profileId = 0x104;
805
- request.clusterId = zclFrame.cluster.ID;
806
- request.srcEndpoint = 1;
807
- request.asduLength = pay.length;
808
- request.asduPayload = [...pay];
809
- request.txOptions = 0;
810
- request.radius = constants_1.default.PARAM.txRadius.UNLIMITED;
403
+ const payload = zclFrame.toBuffer();
404
+ logger_1.logger.debug(`zclFrame to group - ${groupID}`, NS);
405
+ const request = {
406
+ requestId: transactionID,
407
+ destAddrMode: constants_1.default.PARAM.addressMode.GROUP_ADDR,
408
+ destAddr16: groupID,
409
+ profileId: 0x104,
410
+ clusterId: zclFrame.cluster.ID,
411
+ srcEndpoint: 1,
412
+ asduLength: payload.length,
413
+ asduPayload: payload,
414
+ txOptions: 0,
415
+ radius: constants_1.default.PARAM.txRadius.UNLIMITED,
416
+ };
811
417
  logger_1.logger.debug(`sendZclFrameToGroup - message send`, NS);
812
418
  return await this.driver.enqueueSendDataRequest(request);
813
419
  }
814
420
  async sendZclFrameToAll(endpoint, zclFrame, sourceEndpoint, destination) {
815
421
  const transactionID = this.nextTransactionID();
816
- const request = {};
817
- const pay = zclFrame.toBuffer();
818
- logger_1.logger.debug('zclFrame to all - zclFrame.payload:', NS);
819
- logger_1.logger.debug(zclFrame.payload, NS);
820
- request.requestId = transactionID;
821
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
822
- request.destAddr16 = destination;
823
- request.destEndpoint = endpoint;
824
- request.profileId = sourceEndpoint === 242 && endpoint === 242 ? 0xa1e0 : 0x104;
825
- request.clusterId = zclFrame.cluster.ID;
826
- request.srcEndpoint = sourceEndpoint;
827
- request.asduLength = pay.length;
828
- request.asduPayload = [...pay];
829
- request.txOptions = 0;
830
- request.radius = constants_1.default.PARAM.txRadius.UNLIMITED;
422
+ const payload = zclFrame.toBuffer();
423
+ logger_1.logger.debug(`zclFrame to all - ${endpoint}`, NS);
424
+ const request = {
425
+ requestId: transactionID,
426
+ destAddrMode: constants_1.default.PARAM.addressMode.NWK_ADDR,
427
+ destAddr16: destination,
428
+ destEndpoint: endpoint,
429
+ profileId: sourceEndpoint === 242 && endpoint === 242 ? 0xa1e0 : 0x104,
430
+ clusterId: zclFrame.cluster.ID,
431
+ srcEndpoint: sourceEndpoint,
432
+ asduLength: payload.length,
433
+ asduPayload: payload,
434
+ txOptions: 0,
435
+ radius: constants_1.default.PARAM.txRadius.UNLIMITED,
436
+ };
831
437
  logger_1.logger.debug(`sendZclFrameToAll - message send`, NS);
832
438
  return await this.driver.enqueueSendDataRequest(request);
833
439
  }
834
- async bind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
835
- const transactionID = this.nextTransactionID();
836
- const clid1 = clusterID & 0xff;
837
- const clid2 = (clusterID >> 8) & 0xff;
838
- const destAddrMode = type === 'group' ? constants_1.default.PARAM.addressMode.GROUP_ADDR : constants_1.default.PARAM.addressMode.IEEE_ADDR;
839
- let destArray;
840
- if (type === 'endpoint') {
841
- (0, assert_1.default)(destinationEndpoint, 'Destination endpoint must be defined when `type === endpoint`');
842
- destArray = this.driver.macAddrStringToArray(destinationAddressOrGroup);
843
- destArray = destArray.concat([destinationEndpoint]);
844
- }
845
- else {
846
- destArray = [destinationAddressOrGroup, (destinationAddressOrGroup >> 8) & 0xff];
847
- }
848
- const request = {};
849
- const zdpFrame = [transactionID]
850
- .concat(this.driver.macAddrStringToArray(sourceIeeeAddress))
851
- .concat([sourceEndpoint, clid1, clid2, destAddrMode])
852
- .concat(destArray);
853
- request.requestId = transactionID;
854
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
855
- request.destAddr16 = destinationNetworkAddress;
856
- request.destEndpoint = 0;
857
- request.profileId = 0;
858
- request.clusterId = 0x21; // bind_request
859
- request.srcEndpoint = 0;
860
- request.asduLength = zdpFrame.length;
861
- request.asduPayload = zdpFrame;
862
- request.txOptions = 0x04; // 0x04 use APS ACKS
863
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
864
- request.timeout = 30;
865
- this.driver
866
- .enqueueSendDataRequest(request)
867
- .then(() => { })
868
- .catch(() => { });
869
- try {
870
- const d = await this.waitForData(destinationNetworkAddress, 0, 0x8021);
871
- const data = d.asduPayload;
872
- logger_1.logger.debug('BIND RESPONSE - addr: 0x' + destinationNetworkAddress.toString(16) + ' status: ' + data[1], NS);
873
- if (data[1] !== 0) {
874
- throw new Error('status: ' + data[1]);
875
- }
876
- }
877
- catch (error) {
878
- logger_1.logger.debug('BIND FAILED - addr: 0x' + destinationNetworkAddress.toString(16) + ' ' + error, NS);
879
- throw error;
880
- }
881
- }
882
- async unbind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
883
- const transactionID = this.nextTransactionID();
884
- const clid1 = clusterID & 0xff;
885
- const clid2 = (clusterID >> 8) & 0xff;
886
- const destAddrMode = type === 'group' ? constants_1.default.PARAM.addressMode.GROUP_ADDR : constants_1.default.PARAM.addressMode.IEEE_ADDR;
887
- let destArray;
888
- if (type === 'endpoint') {
889
- (0, assert_1.default)(destinationEndpoint, 'Destination endpoint must be defined when `type === endpoint`');
890
- destArray = this.driver.macAddrStringToArray(destinationAddressOrGroup);
891
- destArray = destArray.concat([destinationEndpoint]);
892
- }
893
- else {
894
- destArray = [destinationAddressOrGroup, (destinationAddressOrGroup >> 8) & 0xff];
895
- }
896
- const request = {};
897
- const zdpFrame = [transactionID]
898
- .concat(this.driver.macAddrStringToArray(sourceIeeeAddress))
899
- .concat([sourceEndpoint, clid1, clid2, destAddrMode])
900
- .concat(destArray);
901
- request.requestId = transactionID;
902
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
903
- request.destAddr16 = destinationNetworkAddress;
904
- request.destEndpoint = 0;
905
- request.profileId = 0;
906
- request.clusterId = 0x22; // unbind_request
907
- request.srcEndpoint = 0;
908
- request.asduLength = zdpFrame.length;
909
- request.asduPayload = zdpFrame;
910
- request.txOptions = 0x04; // 0x04 use APS ACKS
911
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
912
- request.timeout = 30;
913
- this.driver
914
- .enqueueSendDataRequest(request)
915
- .then(() => { })
916
- .catch(() => { });
917
- try {
918
- const d = await this.waitForData(destinationNetworkAddress, 0, 0x8022);
919
- const data = d.asduPayload;
920
- logger_1.logger.debug('UNBIND RESPONSE - addr: 0x' + destinationNetworkAddress.toString(16) + ' status: ' + data[1], NS);
921
- if (data[1] !== 0) {
922
- throw new Error('status: ' + data[1]);
923
- }
924
- }
925
- catch (error) {
926
- logger_1.logger.debug('UNBIND FAILED - addr: 0x' + destinationNetworkAddress.toString(16) + ' ' + error, NS);
927
- throw error;
928
- }
929
- }
930
- async removeDevice(networkAddress, ieeeAddr) {
931
- const transactionID = this.nextTransactionID();
932
- // const nwk1 = networkAddress & 0xff;
933
- // const nwk2 = (networkAddress >> 8) & 0xff;
934
- const request = {};
935
- //const zdpFrame = [transactionID].concat(this.driver.macAddrStringToArray(ieeeAddr)).concat([0]);
936
- const zdpFrame = [transactionID].concat([0, 0, 0, 0, 0, 0, 0, 0]).concat([0]);
937
- request.requestId = transactionID;
938
- request.destAddrMode = constants_1.default.PARAM.addressMode.NWK_ADDR;
939
- request.destAddr16 = networkAddress;
940
- request.destEndpoint = 0;
941
- request.profileId = 0;
942
- request.clusterId = 0x34; // mgmt_leave_request
943
- request.srcEndpoint = 0;
944
- request.asduLength = 10;
945
- request.asduPayload = zdpFrame;
946
- request.txOptions = 0;
947
- request.radius = constants_1.default.PARAM.txRadius.DEFAULT_RADIUS;
948
- this.driver
949
- .enqueueSendDataRequest(request)
950
- .then(() => { })
951
- .catch(() => { });
952
- try {
953
- const d = await this.waitForData(networkAddress, 0, 0x8034);
954
- const data = d.asduPayload;
955
- logger_1.logger.debug('REMOVE_DEVICE - addr: 0x' + networkAddress.toString(16) + ' status: ' + data[1], NS);
956
- const payload = {
957
- networkAddress: networkAddress,
958
- ieeeAddr: ieeeAddr,
959
- };
960
- if (data[1] !== 0) {
961
- throw new Error('status: ' + data[1]);
962
- }
963
- this.emit('deviceLeave', payload);
964
- }
965
- catch (error) {
966
- logger_1.logger.debug('REMOVE_DEVICE FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error, NS);
967
- throw error;
968
- }
969
- }
970
440
  async supportsBackup() {
971
441
  return false;
972
442
  }
@@ -1010,10 +480,6 @@ class DeconzAdapter extends adapter_1.default {
1010
480
  throw new Error('not supported');
1011
481
  }
1012
482
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1013
- async changeChannel(newChannel) {
1014
- throw new Error(`Channel change is not supported for 'deconz'`);
1015
- }
1016
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1017
483
  async setTransmitPower(value) {
1018
484
  throw new Error('not supported');
1019
485
  }
@@ -1024,9 +490,6 @@ class DeconzAdapter extends adapter_1.default {
1024
490
  /**
1025
491
  * Private methods
1026
492
  */
1027
- sleep(ms) {
1028
- return new Promise((resolve) => setTimeout(resolve, ms));
1029
- }
1030
493
  waitForData(addr, profileId, clusterId, transactionSequenceNumber, timeout) {
1031
494
  return new Promise((resolve, reject) => {
1032
495
  const ts = Date.now();
@@ -1053,20 +516,20 @@ class DeconzAdapter extends adapter_1.default {
1053
516
  data: payBuf,
1054
517
  clusterID: Zcl.Clusters.greenPower.ID,
1055
518
  address: ind.srcId & 0xffff,
1056
- endpoint: __1.ZSpec.GP_ENDPOINT,
519
+ endpoint: ZSpec.GP_ENDPOINT,
1057
520
  linkquality: 0xff, // bogus
1058
- groupID: __1.ZSpec.GP_GROUP_ID,
521
+ groupID: ZSpec.GP_GROUP_ID,
1059
522
  wasBroadcast: true, // Take the codepath that doesn't require `gppNwkAddr` as its not present in the payload
1060
- destinationEndpoint: __1.ZSpec.GP_ENDPOINT,
523
+ destinationEndpoint: ZSpec.GP_ENDPOINT,
1061
524
  };
1062
525
  this.waitress.resolve(payload);
1063
526
  this.emit('zclPayload', payload);
1064
527
  }
1065
528
  checkReceivedDataPayload(resp) {
1066
- let srcAddr = undefined;
529
+ let srcAddr;
530
+ let srcEUI64;
1067
531
  let header;
1068
- const payBuf = resp != null ? Buffer.from(resp.asduPayload) : undefined;
1069
- if (resp != null) {
532
+ if (resp) {
1070
533
  if (resp.srcAddr16 != null) {
1071
534
  srcAddr = resp.srcAddr16;
1072
535
  }
@@ -1085,26 +548,38 @@ class DeconzAdapter extends adapter_1.default {
1085
548
  // so let's make sure they get the network address
1086
549
  resp.srcAddr16 = srcAddr; // TODO: can't be undefined
1087
550
  }
1088
- if (resp.profileId != 0x00) {
1089
- header = Zcl.Header.fromBuffer(payBuf); // valid from check
551
+ if (resp.profileId === Zdo.ZDO_PROFILE_ID) {
552
+ if (resp.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
553
+ if (Zdo.Buffalo.checkStatus(resp.zdo)) {
554
+ srcEUI64 = resp.zdo[1].eui64;
555
+ }
556
+ }
557
+ else if (resp.clusterId === Zdo.ClusterId.END_DEVICE_ANNOUNCE) {
558
+ // XXX: using same response for announce (handled by controller) or joined depending on permit join status?
559
+ if (this.joinPermitted === true && Zdo.Buffalo.checkStatus(resp.zdo)) {
560
+ const payload = resp.zdo[1];
561
+ this.emit('deviceJoined', { networkAddress: payload.nwkAddress, ieeeAddr: payload.eui64 });
562
+ }
563
+ }
564
+ this.emit('zdoResponse', resp.clusterId, resp.zdo);
565
+ }
566
+ else {
567
+ header = Zcl.Header.fromBuffer(resp.asduPayload);
1090
568
  }
1091
569
  }
1092
570
  let i = this.openRequestsQueue.length;
1093
571
  while (i--) {
1094
572
  const req = this.openRequestsQueue[i];
1095
- if (srcAddr != null && req.addr === srcAddr && req.clusterId === resp?.clusterId && req.profileId === resp?.profileId) {
1096
- if (header !== undefined && req.transactionSequenceNumber != undefined) {
1097
- if (req.transactionSequenceNumber === header.transactionSequenceNumber) {
1098
- logger_1.logger.debug('resolve data request with transSeq Nr.: ' + req.transactionSequenceNumber, NS);
1099
- this.openRequestsQueue.splice(i, 1);
1100
- req.resolve?.(resp);
1101
- }
1102
- }
1103
- else {
1104
- logger_1.logger.debug('resolve data request without a transSeq Nr.', NS);
1105
- this.openRequestsQueue.splice(i, 1);
1106
- req.resolve?.(resp);
1107
- }
573
+ if (resp &&
574
+ (req.addr === undefined ||
575
+ (typeof req.addr === 'number' ? srcAddr !== undefined && req.addr === srcAddr : srcEUI64 && req.addr === srcEUI64)) &&
576
+ req.clusterId === resp.clusterId &&
577
+ req.profileId === resp.profileId &&
578
+ (header === undefined ||
579
+ req.transactionSequenceNumber === undefined ||
580
+ req.transactionSequenceNumber === header.transactionSequenceNumber)) {
581
+ this.openRequestsQueue.splice(i, 1);
582
+ req.resolve(resp);
1108
583
  }
1109
584
  const now = Date.now();
1110
585
  // Default timeout: 60 seconds.
@@ -1113,28 +588,14 @@ class DeconzAdapter extends adapter_1.default {
1113
588
  //logger.debug("Timeout for request in openRequestsQueue addr: " + req.addr.toString(16) + " clusterId: " + req.clusterId.toString(16) + " profileId: " + req.profileId.toString(16), NS);
1114
589
  //remove from busyQueue
1115
590
  this.openRequestsQueue.splice(i, 1);
1116
- req.reject?.('waiting for response TIMEOUT');
1117
- }
1118
- }
1119
- // check unattended incomming messages
1120
- if (resp != null && resp.profileId === 0x00 && resp.clusterId === 0x13) {
1121
- // device Annce
1122
- const payload = {
1123
- networkAddress: payBuf.readUInt16LE(1), // valid from check
1124
- ieeeAddr: this.driver.macAddrArrayToString(resp.asduPayload.slice(3, 11)),
1125
- };
1126
- if (this.joinPermitted === true) {
1127
- this.emit('deviceJoined', payload);
1128
- }
1129
- else {
1130
- this.emit('deviceAnnounce', payload);
591
+ req.reject(new Error('waiting for response TIMEOUT'));
1131
592
  }
1132
593
  }
1133
- if (resp != null && resp.profileId != 0x00) {
594
+ if (resp && resp.profileId != Zdo.ZDO_PROFILE_ID) {
1134
595
  const payload = {
1135
596
  clusterID: resp.clusterId,
1136
597
  header,
1137
- data: payBuf, // valid from check
598
+ data: resp.asduPayload,
1138
599
  address: resp.destAddrMode === 0x03 ? `0x${resp.srcAddr64}` : resp.srcAddr16,
1139
600
  endpoint: resp.srcEndpoint,
1140
601
  linkquality: resp.lqi,