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.
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/adapter/adapter.d.ts +6 -0
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +5 -3
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.js +261 -558
- package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
- package/dist/adapter/deconz/driver/constants.d.ts +102 -56
- package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/constants.js +1 -2
- package/dist/adapter/deconz/driver/constants.js.map +1 -1
- package/dist/adapter/deconz/driver/driver.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/driver.js +46 -41
- package/dist/adapter/deconz/driver/driver.js.map +1 -1
- package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/frameParser.js +174 -107
- package/dist/adapter/deconz/driver/frameParser.js.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +4 -12
- package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.js +215 -249
- package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +16 -12
- package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.js +16 -41
- package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +10 -8
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.js +241 -238
- package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
- package/dist/adapter/ezsp/driver/driver.d.ts +6 -14
- package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/driver.js +56 -37
- package/dist/adapter/ezsp/driver/driver.js.map +1 -1
- package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/ezsp.js +3 -0
- package/dist/adapter/ezsp/driver/ezsp.js.map +1 -1
- package/dist/adapter/z-stack/adapter/manager.js +2 -2
- package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +4 -3
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +258 -197
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
- package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/definition.js +256 -302
- package/dist/adapter/z-stack/znp/definition.js.map +1 -1
- package/dist/adapter/z-stack/znp/tstype.d.ts +8 -8
- package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/utils.d.ts +3 -2
- package/dist/adapter/z-stack/znp/utils.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/utils.js +8 -7
- package/dist/adapter/z-stack/znp/utils.js.map +1 -1
- package/dist/adapter/z-stack/znp/znp.d.ts +3 -1
- package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/znp.js +31 -14
- package/dist/adapter/z-stack/znp/znp.js.map +1 -1
- package/dist/adapter/z-stack/znp/zpiObject.d.ts +5 -6
- package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/zpiObject.js +28 -11
- package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +7 -5
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.js +284 -138
- package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -1
- package/dist/adapter/zboss/commands.d.ts +3 -0
- package/dist/adapter/zboss/commands.d.ts.map +1 -1
- package/dist/adapter/zboss/commands.js +248 -205
- package/dist/adapter/zboss/commands.js.map +1 -1
- package/dist/adapter/zboss/driver.d.ts +4 -14
- package/dist/adapter/zboss/driver.d.ts.map +1 -1
- package/dist/adapter/zboss/driver.js +63 -89
- package/dist/adapter/zboss/driver.js.map +1 -1
- package/dist/adapter/zboss/enums.d.ts +24 -2
- package/dist/adapter/zboss/enums.d.ts.map +1 -1
- package/dist/adapter/zboss/enums.js +35 -3
- package/dist/adapter/zboss/enums.js.map +1 -1
- package/dist/adapter/zboss/frame.d.ts +6 -1
- package/dist/adapter/zboss/frame.d.ts.map +1 -1
- package/dist/adapter/zboss/frame.js +56 -11
- package/dist/adapter/zboss/frame.js.map +1 -1
- package/dist/adapter/zboss/uart.d.ts +1 -0
- package/dist/adapter/zboss/uart.d.ts.map +1 -1
- package/dist/adapter/zboss/uart.js +4 -2
- package/dist/adapter/zboss/uart.js.map +1 -1
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts +5 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts.map +1 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js +44 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js.map +1 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +5 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.js +247 -262
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.js +2 -18
- package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
- package/dist/adapter/zigate/driver/commandType.js +218 -218
- package/dist/adapter/zigate/driver/commandType.js.map +1 -1
- package/dist/adapter/zigate/driver/constants.d.ts +14 -8
- package/dist/adapter/zigate/driver/constants.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/constants.js +36 -9
- package/dist/adapter/zigate/driver/constants.js.map +1 -1
- package/dist/adapter/zigate/driver/messageType.js +42 -42
- package/dist/adapter/zigate/driver/messageType.js.map +1 -1
- package/dist/adapter/zigate/driver/zigate.d.ts +17 -13
- package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/zigate.js +83 -18
- package/dist/adapter/zigate/driver/zigate.js.map +1 -1
- package/dist/controller/controller.d.ts +1 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/controller.js +28 -0
- package/dist/controller/controller.js.map +1 -1
- package/dist/utils/patchBigIntSerialization.d.ts +2 -0
- package/dist/utils/patchBigIntSerialization.d.ts.map +1 -0
- package/dist/utils/patchBigIntSerialization.js +9 -0
- package/dist/utils/patchBigIntSerialization.js.map +1 -0
- package/dist/zspec/zcl/zclFrame.d.ts +1 -0
- package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
- package/dist/zspec/zcl/zclFrame.js +1 -0
- package/dist/zspec/zcl/zclFrame.js.map +1 -1
- package/dist/zspec/zdo/buffaloZdo.d.ts +1 -139
- package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
- package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
- package/dist/zspec/zdo/definition/tstypes.d.ts +168 -1
- package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -1
- package/dist/zspec/zdo/definition/tstypes.js +1 -0
- package/dist/zspec/zdo/definition/tstypes.js.map +1 -1
- package/dist/zspec/zdo/utils.d.ts +2 -3
- package/dist/zspec/zdo/utils.d.ts.map +1 -1
- package/dist/zspec/zdo/utils.js +3 -4
- package/dist/zspec/zdo/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -37,6 +37,8 @@ const adapter_1 = __importDefault(require("../../adapter"));
|
|
|
37
37
|
const Constants = __importStar(require("../constants"));
|
|
38
38
|
const unpi_1 = require("../unpi");
|
|
39
39
|
const znp_1 = require("../znp");
|
|
40
|
+
const definition_1 = __importDefault(require("../znp/definition"));
|
|
41
|
+
const utils_2 = require("../znp/utils");
|
|
40
42
|
const manager_1 = require("./manager");
|
|
41
43
|
const tstype_1 = require("./tstype");
|
|
42
44
|
const NS = 'zh:zstack';
|
|
@@ -175,14 +177,23 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
175
177
|
});
|
|
176
178
|
}
|
|
177
179
|
async permitJoin(seconds, networkAddress) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
+
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
|
|
181
|
+
// `authentication`: TC significance always 1 (zb specs)
|
|
182
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
|
|
183
|
+
if (networkAddress === undefined) {
|
|
184
|
+
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// NOTE: `sendZdo` takes care of adjusting the payload as appropriate based on `networkAddress === 0` or not
|
|
188
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
189
|
+
/* istanbul ignore next */
|
|
190
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
191
|
+
// TODO: will disappear once moved upstream
|
|
192
|
+
throw new Zdo.StatusError(result[0]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
180
195
|
await this.queue.execute(async () => {
|
|
181
196
|
this.checkInterpanLock();
|
|
182
|
-
const payload = { addrmode, dstaddr, duration: seconds, tcsignificance: 0 };
|
|
183
|
-
const permitJoinRsp = this.waitForAreqZdo('mgmtPermitJoinRsp');
|
|
184
|
-
await this.znp.request(Subsystem.ZDO, 'mgmtPermitJoinReq', payload);
|
|
185
|
-
await permitJoinRsp.start();
|
|
186
197
|
await this.setLED(seconds == 0 ? 'off' : 'on');
|
|
187
198
|
});
|
|
188
199
|
}
|
|
@@ -231,10 +242,17 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
231
242
|
* this is currently not handled, the first nwkAddrRsp is taken.
|
|
232
243
|
*/
|
|
233
244
|
logger_1.logger.debug(`Request network address of '${ieeeAddr}'`, NS);
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
const result = await
|
|
237
|
-
|
|
245
|
+
const clusterId = Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
|
|
246
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, ieeeAddr, false, 0);
|
|
247
|
+
const result = await this.sendZdo(ieeeAddr, ZSpec.NULL_NODE_ID, clusterId, zdoPayload, false);
|
|
248
|
+
/* istanbul ignore else */
|
|
249
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
250
|
+
return result[1].nwkAddress;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
// TODO: will disappear once moved upstream
|
|
254
|
+
throw new Zdo.StatusError(result[0]);
|
|
255
|
+
}
|
|
238
256
|
}
|
|
239
257
|
supportsAssocRemove() {
|
|
240
258
|
return this.version.product === tstype_1.ZnpVersion.zStack3x0 && parseInt(this.version.revision) >= 20200805;
|
|
@@ -251,67 +269,141 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
251
269
|
}
|
|
252
270
|
}
|
|
253
271
|
async nodeDescriptor(networkAddress) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// https://github.com/Koenkk/zigbee2mqtt/issues/3276
|
|
264
|
-
await this.discoverRoute(networkAddress);
|
|
265
|
-
const result = await this.nodeDescriptorInternal(networkAddress);
|
|
266
|
-
return result;
|
|
267
|
-
}
|
|
268
|
-
}, networkAddress);
|
|
269
|
-
}
|
|
270
|
-
async nodeDescriptorInternal(networkAddress) {
|
|
271
|
-
const response = this.waitForAreqZdo('nodeDescRsp', { srcaddr: networkAddress });
|
|
272
|
-
const payload = { dstaddr: networkAddress, nwkaddrofinterest: networkAddress };
|
|
273
|
-
await this.znp.request(Subsystem.ZDO, 'nodeDescReq', payload, response.ID);
|
|
274
|
-
const descriptor = await response.start();
|
|
275
|
-
let type = 'Unknown';
|
|
276
|
-
const logicalType = descriptor.logicalType;
|
|
277
|
-
for (const [key, value] of Object.entries(Constants.ZDO.deviceLogicalType)) {
|
|
278
|
-
if (value === logicalType) {
|
|
279
|
-
if (key === 'COORDINATOR')
|
|
272
|
+
const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
|
|
273
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
|
|
274
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
275
|
+
/* istanbul ignore else */
|
|
276
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
277
|
+
const payload = result[1];
|
|
278
|
+
let type = 'Unknown';
|
|
279
|
+
switch (payload.logicalType) {
|
|
280
|
+
case 0x0:
|
|
280
281
|
type = 'Coordinator';
|
|
281
|
-
|
|
282
|
+
break;
|
|
283
|
+
case 0x1:
|
|
282
284
|
type = 'Router';
|
|
283
|
-
|
|
285
|
+
break;
|
|
286
|
+
case 0x2:
|
|
284
287
|
type = 'EndDevice';
|
|
285
|
-
|
|
288
|
+
break;
|
|
286
289
|
}
|
|
290
|
+
return { type, manufacturerCode: payload.manufacturerCode };
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// TODO: will disappear once moved upstream
|
|
294
|
+
throw new Zdo.StatusError(result[0]);
|
|
287
295
|
}
|
|
288
|
-
return { manufacturerCode: descriptor.manufacturerCode, type };
|
|
289
296
|
}
|
|
290
297
|
async activeEndpoints(networkAddress) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
298
|
+
const clusterId = Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST;
|
|
299
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
|
|
300
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
301
|
+
/* istanbul ignore else */
|
|
302
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
303
|
+
return { endpoints: result[1].endpointList };
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
// TODO: will disappear once moved upstream
|
|
307
|
+
throw new Zdo.StatusError(result[0]);
|
|
308
|
+
}
|
|
299
309
|
}
|
|
300
310
|
async simpleDescriptor(networkAddress, endpointID) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const
|
|
311
|
+
const clusterId = Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST;
|
|
312
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress, endpointID);
|
|
313
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
314
|
+
/* istanbul ignore else */
|
|
315
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
316
|
+
const payload = result[1];
|
|
307
317
|
return {
|
|
308
|
-
profileID:
|
|
309
|
-
endpointID:
|
|
310
|
-
deviceID:
|
|
311
|
-
inputClusters:
|
|
312
|
-
outputClusters:
|
|
318
|
+
profileID: payload.profileId,
|
|
319
|
+
endpointID: payload.endpoint,
|
|
320
|
+
deviceID: payload.deviceId,
|
|
321
|
+
inputClusters: payload.inClusterList,
|
|
322
|
+
outputClusters: payload.outClusterList,
|
|
313
323
|
};
|
|
314
|
-
}
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
// TODO: will disappear once moved upstream
|
|
327
|
+
throw new Zdo.StatusError(result[0]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
async sendZdo(ieeeAddress, networkAddress, clusterId, payload, disableResponse) {
|
|
331
|
+
return await this.queue.execute(async () => {
|
|
332
|
+
this.checkInterpanLock();
|
|
333
|
+
// stack-specific requirements
|
|
334
|
+
switch (clusterId) {
|
|
335
|
+
case Zdo.ClusterId.PERMIT_JOINING_REQUEST: {
|
|
336
|
+
const finalPayload = Buffer.alloc(payload.length + 3);
|
|
337
|
+
finalPayload.writeUInt8(ZSpec.BroadcastAddress[networkAddress] ? AddressMode.ADDR_BROADCAST : AddressMode.ADDR_16BIT, 0);
|
|
338
|
+
// zstack uses AddressMode.ADDR_16BIT + ZSpec.BroadcastAddress.DEFAULT to signal "coordinator-only"
|
|
339
|
+
finalPayload.writeUInt16LE(networkAddress === 0 ? ZSpec.BroadcastAddress.DEFAULT : networkAddress, 1);
|
|
340
|
+
finalPayload.set(payload, 3);
|
|
341
|
+
payload = finalPayload;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case Zdo.ClusterId.NWK_UPDATE_REQUEST: {
|
|
345
|
+
// extra zeroes for empty nwkManagerAddr if necessary
|
|
346
|
+
const zeroes = 9 - payload.length - 1; /* zstack doesn't have nwkUpdateId */
|
|
347
|
+
const finalPayload = Buffer.alloc(payload.length + 3 + zeroes);
|
|
348
|
+
finalPayload.writeUInt16LE(networkAddress, 0);
|
|
349
|
+
finalPayload.writeUInt8(ZSpec.BroadcastAddress[networkAddress] ? AddressMode.ADDR_BROADCAST : AddressMode.ADDR_16BIT, 2);
|
|
350
|
+
finalPayload.set(payload, 3);
|
|
351
|
+
payload = finalPayload;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
case Zdo.ClusterId.BIND_REQUEST:
|
|
355
|
+
case Zdo.ClusterId.UNBIND_REQUEST: {
|
|
356
|
+
// extra zeroes for uint16 (in place of ieee when MULTICAST) and endpoint (not used when MULTICAST)
|
|
357
|
+
const zeroes = 21 - payload.length;
|
|
358
|
+
const finalPayload = Buffer.alloc(payload.length + 2 + zeroes);
|
|
359
|
+
finalPayload.writeUInt16LE(networkAddress, 0);
|
|
360
|
+
finalPayload.set(payload, 2);
|
|
361
|
+
payload = finalPayload;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
case Zdo.ClusterId.NETWORK_ADDRESS_REQUEST:
|
|
365
|
+
case Zdo.ClusterId.IEEE_ADDRESS_REQUEST: {
|
|
366
|
+
// no modification necessary
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
default: {
|
|
370
|
+
const finalPayload = Buffer.alloc(payload.length + 2);
|
|
371
|
+
finalPayload.writeUInt16LE(networkAddress, 0);
|
|
372
|
+
finalPayload.set(payload, 2);
|
|
373
|
+
payload = finalPayload;
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
let waiter;
|
|
378
|
+
if (!disableResponse) {
|
|
379
|
+
const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
|
|
380
|
+
/* istanbul ignore else */
|
|
381
|
+
if (responseClusterId) {
|
|
382
|
+
const cmd = definition_1.default[Subsystem.ZDO].find((c) => (0, utils_2.isMtCmdAreqZdo)(c) && c.zdoClusterId === responseClusterId);
|
|
383
|
+
(0, assert_1.default)(cmd, `Response for ZDO cluster ID '${responseClusterId}' not supported.`);
|
|
384
|
+
waiter = this.znp.waitFor(unpi_1.Constants.Type.AREQ, Subsystem.ZDO, cmd.name, responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? ieeeAddress : networkAddress, undefined, undefined);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
await this.znp.requestZdo(clusterId, payload, waiter?.ID);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
if (clusterId === Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST) {
|
|
392
|
+
// Discover route when node descriptor request fails
|
|
393
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/3276
|
|
394
|
+
logger_1.logger.debug(`Discover route to '${networkAddress}' because node descriptor request failed`, NS);
|
|
395
|
+
await this.discoverRoute(networkAddress);
|
|
396
|
+
await this.znp.requestZdo(clusterId, payload, waiter?.ID);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (waiter) {
|
|
403
|
+
const response = await waiter.start().promise;
|
|
404
|
+
return response.payload.zdo;
|
|
405
|
+
}
|
|
406
|
+
}, networkAddress /* TODO: replace with ieeeAddress once zdo moved upstream */);
|
|
315
407
|
}
|
|
316
408
|
async sendZclFrameToEndpoint(ieeeAddr, networkAddress, endpoint, zclFrame, timeout, disableResponse, disableRecovery, sourceEndpoint) {
|
|
317
409
|
return await this.queue.execute(async () => {
|
|
@@ -498,68 +590,70 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
498
590
|
});
|
|
499
591
|
}
|
|
500
592
|
async lqi(networkAddress) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const add = (list) => {
|
|
511
|
-
for (const entry of list) {
|
|
593
|
+
const clusterId = Zdo.ClusterId.LQI_TABLE_REQUEST;
|
|
594
|
+
const neighbors = [];
|
|
595
|
+
const request = async (startIndex) => {
|
|
596
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
|
|
597
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
598
|
+
/* istanbul ignore else */
|
|
599
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
600
|
+
const payload = result[1];
|
|
601
|
+
for (const entry of payload.entryList) {
|
|
512
602
|
neighbors.push({
|
|
513
|
-
linkquality: entry.lqi,
|
|
514
|
-
networkAddress: entry.nwkAddress,
|
|
515
603
|
ieeeAddr: entry.eui64,
|
|
604
|
+
networkAddress: entry.nwkAddress,
|
|
605
|
+
linkquality: entry.lqi,
|
|
516
606
|
relationship: entry.relationship,
|
|
517
607
|
depth: entry.depth,
|
|
518
608
|
});
|
|
519
609
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
610
|
+
return [payload.neighborTableEntries, payload.entryList.length];
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
// TODO: will disappear once moved upstream
|
|
614
|
+
throw new Zdo.StatusError(result[0]);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
let [tableEntries, entryCount] = await request(0);
|
|
618
|
+
const size = tableEntries;
|
|
619
|
+
let nextStartIndex = entryCount;
|
|
620
|
+
while (neighbors.length < size) {
|
|
621
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
622
|
+
nextStartIndex += entryCount;
|
|
623
|
+
}
|
|
624
|
+
return { neighbors };
|
|
532
625
|
}
|
|
533
626
|
async routingTable(networkAddress) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const add = (list) => {
|
|
544
|
-
for (const entry of list) {
|
|
627
|
+
const clusterId = Zdo.ClusterId.ROUTING_TABLE_REQUEST;
|
|
628
|
+
const table = [];
|
|
629
|
+
const request = async (startIndex) => {
|
|
630
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
|
|
631
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
632
|
+
/* istanbul ignore else */
|
|
633
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
634
|
+
const payload = result[1];
|
|
635
|
+
for (const entry of payload.entryList) {
|
|
545
636
|
table.push({
|
|
546
637
|
destinationAddress: entry.destinationAddress,
|
|
547
638
|
status: entry.status,
|
|
548
639
|
nextHop: entry.nextHopAddress,
|
|
549
640
|
});
|
|
550
641
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
642
|
+
return [payload.routingTableEntries, payload.entryList.length];
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
// TODO: will disappear once moved upstream
|
|
646
|
+
throw new Zdo.StatusError(result[0]);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
let [tableEntries, entryCount] = await request(0);
|
|
650
|
+
const size = tableEntries;
|
|
651
|
+
let nextStartIndex = entryCount;
|
|
652
|
+
while (table.length < size) {
|
|
653
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
654
|
+
nextStartIndex += entryCount;
|
|
655
|
+
}
|
|
656
|
+
return { table };
|
|
563
657
|
}
|
|
564
658
|
async addInstallCode(ieeeAddress, key) {
|
|
565
659
|
(0, assert_1.default)(this.version.product !== tstype_1.ZnpVersion.zStack12, 'Install code is not supported for ZStack 1.2 adapter');
|
|
@@ -567,40 +661,38 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
567
661
|
await this.znp.request(Subsystem.APP_CNF, 'bdbAddInstallCode', payload);
|
|
568
662
|
}
|
|
569
663
|
async bind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
|
|
570
|
-
|
|
664
|
+
const clusterId = Zdo.ClusterId.BIND_REQUEST;
|
|
665
|
+
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
|
|
666
|
+
destinationAddressOrGroup, // not used with UNICAST_BINDING
|
|
667
|
+
destinationEndpoint ?? 0);
|
|
668
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
|
|
669
|
+
/* istanbul ignore next */
|
|
670
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
671
|
+
// TODO: will disappear once moved upstream
|
|
672
|
+
throw new Zdo.StatusError(result[0]);
|
|
673
|
+
}
|
|
571
674
|
}
|
|
572
675
|
async unbind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
clusterid: clusterID,
|
|
584
|
-
dstaddrmode: targetType === 'group' ? AddressMode.ADDR_GROUP : AddressMode.ADDR_64BIT,
|
|
585
|
-
dstaddress: this.toAddressString(destinationAddressOrGroup),
|
|
586
|
-
dstendpoint: targetType === 'group' ? 0xff : destinationEndpoint,
|
|
587
|
-
};
|
|
588
|
-
await this.znp.request(Subsystem.ZDO, `${bindType}Req`, payload, response.ID);
|
|
589
|
-
await response.start();
|
|
590
|
-
}, destinationNetworkAddress);
|
|
676
|
+
const clusterId = Zdo.ClusterId.UNBIND_REQUEST;
|
|
677
|
+
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
|
|
678
|
+
destinationAddressOrGroup, // not used with UNICAST_BINDING
|
|
679
|
+
destinationEndpoint ?? 0);
|
|
680
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
|
|
681
|
+
/* istanbul ignore next */
|
|
682
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
683
|
+
// TODO: will disappear once moved upstream
|
|
684
|
+
throw new Zdo.StatusError(result[0]);
|
|
685
|
+
}
|
|
591
686
|
}
|
|
592
|
-
removeDevice(networkAddress, ieeeAddr) {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
await this.znp.request(Subsystem.ZDO, 'mgmtLeaveReq', payload, response.ID);
|
|
602
|
-
await response.start();
|
|
603
|
-
}, networkAddress);
|
|
687
|
+
async removeDevice(networkAddress, ieeeAddr) {
|
|
688
|
+
const clusterId = Zdo.ClusterId.LEAVE_REQUEST;
|
|
689
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
|
|
690
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
691
|
+
/* istanbul ignore next */
|
|
692
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
693
|
+
// TODO: will disappear once moved upstream
|
|
694
|
+
throw new Zdo.StatusError(result[0]);
|
|
695
|
+
}
|
|
604
696
|
}
|
|
605
697
|
/**
|
|
606
698
|
* Event handlers
|
|
@@ -615,6 +707,9 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
615
707
|
return;
|
|
616
708
|
}
|
|
617
709
|
if (object.subsystem === Subsystem.ZDO) {
|
|
710
|
+
if ((0, utils_2.isMtCmdAreqZdo)(object.command)) {
|
|
711
|
+
this.emit('zdoResponse', object.command.zdoClusterId, object.payload.zdo);
|
|
712
|
+
}
|
|
618
713
|
if (object.command.name === 'tcDeviceInd') {
|
|
619
714
|
const payload = {
|
|
620
715
|
networkAddress: object.payload.nwkaddr,
|
|
@@ -623,15 +718,16 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
623
718
|
this.emit('deviceJoined', payload);
|
|
624
719
|
}
|
|
625
720
|
else if (object.command.name === 'endDeviceAnnceInd') {
|
|
626
|
-
|
|
721
|
+
// TODO: better way???
|
|
627
722
|
/* istanbul ignore else */
|
|
628
|
-
if (Zdo.Buffalo.checkStatus(
|
|
723
|
+
if (Zdo.Buffalo.checkStatus(object.payload.zdo)) {
|
|
724
|
+
const zdoPayload = object.payload.zdo[1];
|
|
629
725
|
const payload = {
|
|
630
|
-
networkAddress:
|
|
631
|
-
ieeeAddr:
|
|
726
|
+
networkAddress: zdoPayload.nwkAddress,
|
|
727
|
+
ieeeAddr: zdoPayload.eui64,
|
|
632
728
|
};
|
|
633
729
|
// Only discover routes to end devices, if bit 1 of capabilities === 0 it's an end device.
|
|
634
|
-
const isEndDevice =
|
|
730
|
+
const isEndDevice = zdoPayload.capabilities.deviceType === 0;
|
|
635
731
|
if (isEndDevice) {
|
|
636
732
|
if (!this.deviceAnnounceRouteDiscoveryDebouncers.has(payload.networkAddress)) {
|
|
637
733
|
// If a device announces multiple times in a very short time, it makes no sense
|
|
@@ -649,18 +745,6 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
649
745
|
(0, assert_1.default)(debouncer);
|
|
650
746
|
debouncer();
|
|
651
747
|
}
|
|
652
|
-
this.emit('deviceAnnounce', payload);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
else if (object.command.name === 'nwkAddrRsp') {
|
|
656
|
-
const zdoResult = object.parseZdoPayload();
|
|
657
|
-
/* istanbul ignore else */
|
|
658
|
-
if (Zdo.Buffalo.checkStatus(zdoResult)) {
|
|
659
|
-
const payload = {
|
|
660
|
-
networkAddress: zdoResult[1].nwkAddress,
|
|
661
|
-
ieeeAddr: zdoResult[1].eui64,
|
|
662
|
-
};
|
|
663
|
-
this.emit('networkAddress', payload);
|
|
664
748
|
}
|
|
665
749
|
}
|
|
666
750
|
else if (object.command.name === 'concentratorIndCb') {
|
|
@@ -674,11 +758,15 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
674
758
|
// mappings.
|
|
675
759
|
// https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/158/4403.zstacktask.c
|
|
676
760
|
// https://github.com/Koenkk/zigbee-herdsman/issues/74
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
761
|
+
this.emit('zdoResponse', Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE, [
|
|
762
|
+
Zdo.Status.SUCCESS,
|
|
763
|
+
{
|
|
764
|
+
eui64: object.payload.extaddr,
|
|
765
|
+
nwkAddress: object.payload.srcaddr,
|
|
766
|
+
startIndex: 0,
|
|
767
|
+
assocDevList: [],
|
|
768
|
+
},
|
|
769
|
+
]);
|
|
682
770
|
}
|
|
683
771
|
else {
|
|
684
772
|
/* istanbul ignore else */
|
|
@@ -774,46 +862,17 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
774
862
|
});
|
|
775
863
|
}
|
|
776
864
|
async changeChannel(newChannel) {
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
channelmask: [newChannel].reduce((a, c) => a + (1 << c), 0),
|
|
783
|
-
scanduration: 0xfe, // change channel
|
|
784
|
-
scancount: 0,
|
|
785
|
-
nwkmanageraddr: 0,
|
|
786
|
-
};
|
|
787
|
-
await this.znp.request(Subsystem.ZDO, 'mgmtNwkUpdateReq', payload);
|
|
788
|
-
// wait for the broadcast to propagate and the adapter to actually change
|
|
789
|
-
await (0, utils_1.Wait)(10000);
|
|
790
|
-
});
|
|
865
|
+
const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
|
|
866
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, [newChannel], 0xfe, 0, undefined, 0);
|
|
867
|
+
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.SLEEPY, clusterId, zdoPayload, true /* handled below */);
|
|
868
|
+
// wait for the broadcast to propagate and the adapter to actually change
|
|
869
|
+
await (0, utils_1.Wait)(10000);
|
|
791
870
|
}
|
|
792
871
|
async setTransmitPower(value) {
|
|
793
872
|
return await this.queue.execute(async () => {
|
|
794
873
|
await this.znp.request(Subsystem.SYS, 'stackTune', { operation: 0, value });
|
|
795
874
|
});
|
|
796
875
|
}
|
|
797
|
-
waitForAreqZdo(command, payload) {
|
|
798
|
-
const result = this.znp.waitFor(unpi_1.Constants.Type.AREQ, Subsystem.ZDO, command, payload);
|
|
799
|
-
const start = () => {
|
|
800
|
-
const startResult = result.start();
|
|
801
|
-
return new Promise((resolve, reject) => {
|
|
802
|
-
startResult.promise
|
|
803
|
-
.then((response) => {
|
|
804
|
-
const [status, payload] = response.parseZdoPayload();
|
|
805
|
-
if (status === Zdo.Status.SUCCESS) {
|
|
806
|
-
resolve(payload);
|
|
807
|
-
}
|
|
808
|
-
else {
|
|
809
|
-
reject(new Zdo.StatusError(status));
|
|
810
|
-
}
|
|
811
|
-
})
|
|
812
|
-
.catch(reject);
|
|
813
|
-
});
|
|
814
|
-
};
|
|
815
|
-
return { start, ID: result.ID };
|
|
816
|
-
}
|
|
817
876
|
waitForInternal(networkAddress, endpoint, frameType, direction, transactionSequenceNumber, clusterID, commandIdentifier, timeout) {
|
|
818
877
|
const payload = {
|
|
819
878
|
address: networkAddress,
|
|
@@ -837,7 +896,7 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
837
896
|
*/
|
|
838
897
|
async dataRequest(destinationAddress, destinationEndpoint, sourceEndpoint, clusterID, radius, data, timeout) {
|
|
839
898
|
const transactionID = this.nextTransactionID();
|
|
840
|
-
const response = this.znp.waitFor(Type.AREQ, Subsystem.AF, 'dataConfirm',
|
|
899
|
+
const response = this.znp.waitFor(Type.AREQ, Subsystem.AF, 'dataConfirm', undefined, transactionID, undefined, timeout);
|
|
841
900
|
await this.znp.request(Subsystem.AF, 'dataRequest', {
|
|
842
901
|
dstaddr: destinationAddress,
|
|
843
902
|
destendpoint: destinationEndpoint,
|
|
@@ -861,7 +920,9 @@ class ZStackAdapter extends adapter_1.default {
|
|
|
861
920
|
}
|
|
862
921
|
async dataRequestExtended(addressMode, destinationAddressOrGroupID, destinationEndpoint, panID, sourceEndpoint, clusterID, radius, data, timeout, confirmation, attemptsLeft = 5) {
|
|
863
922
|
const transactionID = this.nextTransactionID();
|
|
864
|
-
const response = confirmation
|
|
923
|
+
const response = confirmation
|
|
924
|
+
? this.znp.waitFor(Type.AREQ, Subsystem.AF, 'dataConfirm', undefined, transactionID, undefined, timeout)
|
|
925
|
+
: undefined;
|
|
865
926
|
await this.znp.request(Subsystem.AF, 'dataRequestExt', {
|
|
866
927
|
dstaddrmode: addressMode,
|
|
867
928
|
dstaddr: this.toAddressString(destinationAddressOrGroupID),
|