zigbee-herdsman 0.50.1 → 0.51.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 +7 -0
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +23 -441
- package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.js +446 -1083
- package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +5 -4
- package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.js +28 -14
- package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
- package/dist/adapter/ember/adapter/requestQueue.d.ts +14 -4
- package/dist/adapter/ember/adapter/requestQueue.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/requestQueue.js +55 -35
- package/dist/adapter/ember/adapter/requestQueue.js.map +1 -1
- package/dist/adapter/ember/adapter/tokensManager.d.ts +10 -9
- package/dist/adapter/ember/adapter/tokensManager.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/tokensManager.js +34 -34
- package/dist/adapter/ember/adapter/tokensManager.js.map +1 -1
- package/dist/adapter/ember/consts.d.ts +1 -0
- package/dist/adapter/ember/consts.d.ts.map +1 -1
- package/dist/adapter/ember/consts.js +2 -0
- package/dist/adapter/ember/consts.js.map +1 -1
- package/dist/adapter/ember/enums.d.ts +128 -407
- package/dist/adapter/ember/enums.d.ts.map +1 -1
- package/dist/adapter/ember/enums.js +140 -436
- package/dist/adapter/ember/enums.js.map +1 -1
- package/dist/adapter/ember/ezsp/buffalo.d.ts +13 -2
- package/dist/adapter/ember/ezsp/buffalo.d.ts.map +1 -1
- package/dist/adapter/ember/ezsp/buffalo.js +137 -28
- package/dist/adapter/ember/ezsp/buffalo.js.map +1 -1
- package/dist/adapter/ember/ezsp/consts.d.ts +2 -1
- package/dist/adapter/ember/ezsp/consts.d.ts.map +1 -1
- package/dist/adapter/ember/ezsp/consts.js +4 -3
- package/dist/adapter/ember/ezsp/consts.js.map +1 -1
- package/dist/adapter/ember/ezsp/enums.d.ts +160 -49
- package/dist/adapter/ember/ezsp/enums.d.ts.map +1 -1
- package/dist/adapter/ember/ezsp/enums.js +177 -47
- package/dist/adapter/ember/ezsp/enums.js.map +1 -1
- package/dist/adapter/ember/ezsp/ezsp.d.ts +975 -716
- package/dist/adapter/ember/ezsp/ezsp.d.ts.map +1 -1
- package/dist/adapter/ember/ezsp/ezsp.js +2413 -1882
- package/dist/adapter/ember/ezsp/ezsp.js.map +1 -1
- package/dist/adapter/ember/ezspError.d.ts +6 -0
- package/dist/adapter/ember/ezspError.d.ts.map +1 -0
- package/dist/adapter/ember/ezspError.js +13 -0
- package/dist/adapter/ember/ezspError.js.map +1 -0
- package/dist/adapter/ember/types.d.ts +89 -42
- package/dist/adapter/ember/types.d.ts.map +1 -1
- package/dist/adapter/ember/uart/ash.d.ts +11 -7
- package/dist/adapter/ember/uart/ash.d.ts.map +1 -1
- package/dist/adapter/ember/uart/ash.js +15 -17
- package/dist/adapter/ember/uart/ash.js.map +1 -1
- package/dist/adapter/ember/utils/math.d.ts +0 -8
- package/dist/adapter/ember/utils/math.d.ts.map +1 -1
- package/dist/adapter/ember/utils/math.js +1 -20
- package/dist/adapter/ember/utils/math.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapter/ember/zdo.d.ts +0 -925
- package/dist/adapter/ember/zdo.d.ts.map +0 -1
- package/dist/adapter/ember/zdo.js +0 -723
- package/dist/adapter/ember/zdo.js.map +0 -1
|
@@ -35,17 +35,16 @@ const serialPortUtils_1 = __importDefault(require("../../serialPortUtils"));
|
|
|
35
35
|
const socketPortUtils_1 = __importDefault(require("../../socketPortUtils"));
|
|
36
36
|
const utils_1 = require("../../../utils");
|
|
37
37
|
const __1 = require("../..");
|
|
38
|
+
const ZSpec = __importStar(require("../../../zspec"));
|
|
38
39
|
const Zcl = __importStar(require("../../../zspec/zcl"));
|
|
39
|
-
const
|
|
40
|
-
const ZSpec = __importStar(require("../../../zspec/consts"));
|
|
40
|
+
const Zdo = __importStar(require("../../../zspec/zdo"));
|
|
41
41
|
const events_1 = require("../../events");
|
|
42
42
|
const math_1 = require("../utils/math");
|
|
43
43
|
const ezsp_1 = require("../ezsp/ezsp");
|
|
44
44
|
const consts_1 = require("../ezsp/consts");
|
|
45
|
-
const
|
|
45
|
+
const enums_1 = require("../ezsp/enums");
|
|
46
46
|
const buffalo_1 = require("../ezsp/buffalo");
|
|
47
|
-
const
|
|
48
|
-
const zdo_1 = require("../zdo");
|
|
47
|
+
const enums_2 = require("../enums");
|
|
49
48
|
const consts_2 = require("../consts");
|
|
50
49
|
const requestQueue_1 = require("./requestQueue");
|
|
51
50
|
const endpoints_1 = require("./endpoints");
|
|
@@ -53,7 +52,9 @@ const initters_1 = require("../utils/initters");
|
|
|
53
52
|
const crypto_1 = require("crypto");
|
|
54
53
|
const oneWaitress_1 = require("./oneWaitress");
|
|
55
54
|
const logger_1 = require("../../../utils/logger");
|
|
56
|
-
|
|
55
|
+
const ezspError_1 = require("../ezspError");
|
|
56
|
+
const buffaloZdo_1 = require("../../../zspec/zdo/buffaloZdo");
|
|
57
|
+
// import {EmberTokensManager} from './tokensManager';
|
|
57
58
|
const NS = 'zh:ember';
|
|
58
59
|
/** Enum to pass strings from numbers up to Z2M. */
|
|
59
60
|
var RoutingTableStatus;
|
|
@@ -96,8 +97,8 @@ const autoDetectDefinitions = [
|
|
|
96
97
|
* messages with non-conflicting sequence numbers.
|
|
97
98
|
*/
|
|
98
99
|
const APPLICATION_ZDO_SEQUENCE_MASK = 0x7F;
|
|
99
|
-
/** Current revision of the spec by zigbee alliance
|
|
100
|
-
const CURRENT_ZIGBEE_SPEC_REVISION =
|
|
100
|
+
/** Current revision of the spec by zigbee alliance supported by Z2M. */
|
|
101
|
+
const CURRENT_ZIGBEE_SPEC_REVISION = 22;
|
|
101
102
|
/** Each scan period is 15.36ms. Scan for at least 200ms (2^4 + 1 periods) to pick up WiFi beacon frames. */
|
|
102
103
|
const ENERGY_SCAN_DURATION = 4;
|
|
103
104
|
/** Oldest supported EZSP version for backups. Don't take the risk to restore a broken network until older backup versions can be investigated. */
|
|
@@ -123,20 +124,12 @@ const DEFAULT_STACK_CONFIG = {
|
|
|
123
124
|
CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD: 1, // zigpc: 1, ZigbeeMinimalHost: 3
|
|
124
125
|
CONCENTRATOR_MAX_HOPS: 0, // zigpc: 0
|
|
125
126
|
MAX_END_DEVICE_CHILDREN: 32, // zigpc: 6, nabucasa: 32, Dongle-E (Sonoff firmware): 32
|
|
126
|
-
APS_UNICAST_MESSAGE_COUNT: 32, // zigpc: 10, darkxst: 20, nabucasa: 20
|
|
127
|
-
RETRY_QUEUE_SIZE: 16, // nabucasa: 16
|
|
128
|
-
ADDRESS_TABLE_SIZE: 16, // zigpc: 32, darkxst: 16, nabucasa: 16
|
|
129
|
-
TRUST_CENTER_ADDRESS_CACHE_SIZE: 2,
|
|
130
|
-
KEY_TABLE_SIZE: 0, // zigpc: 4
|
|
131
|
-
BINDING_TABLE_SIZE: 32, // zigpc: 2, Z3GatewayGPCombo: 5, nabucasa: 32
|
|
132
|
-
BROADCAST_TABLE_SIZE: 15, // zigpc: 15, Z3GatewayGPCombo: 35 - NOTE: Sonoff Dongle-E fails at 35
|
|
133
|
-
MULTICAST_TABLE_SIZE: 16, // darkxst: 16, nabucasa: 16 - NOTE: should always be at least enough to register FIXED_ENDPOINTS multicastIds
|
|
134
|
-
NEIGHBOR_TABLE_SIZE: 26, // zigpc: 16, darkxst: 26, nabucasa: 26
|
|
135
|
-
SOURCE_ROUTE_TABLE_SIZE: 200, // Z3GatewayGPCombo: 100, darkxst: 200, nabucasa: 200
|
|
136
127
|
TRANSIENT_DEVICE_TIMEOUT: 10000,
|
|
137
128
|
END_DEVICE_POLL_TIMEOUT: 8, // zigpc: 8
|
|
138
129
|
TRANSIENT_KEY_TIMEOUT_S: 300, // zigpc: 65535
|
|
139
130
|
};
|
|
131
|
+
/** Default behavior is to disable app key requests */
|
|
132
|
+
const ALLOW_APP_KEY_REQUESTS = false;
|
|
140
133
|
/**
|
|
141
134
|
* NOTE: This from SDK is currently ignored here because of issues in below links:
|
|
142
135
|
* - BUGZID 12261: Concentrators use MTORRs for route discovery and should not enable route discovery in the APS options.
|
|
@@ -145,13 +138,7 @@ const DEFAULT_STACK_CONFIG = {
|
|
|
145
138
|
*
|
|
146
139
|
* Removing `ENABLE_ROUTE_DISCOVERY` leads to devices that won't reconnect/go offline, and various other issues. Keeping it for now.
|
|
147
140
|
*/
|
|
148
|
-
const DEFAULT_APS_OPTIONS = (
|
|
149
|
-
/**
|
|
150
|
-
* Enabling this allows to immediately reject requests that won't be able to get to their destination.
|
|
151
|
-
* However, it causes more NCP calls, notably to get the source route overhead.
|
|
152
|
-
* XXX: Needs further testing before enabling
|
|
153
|
-
*/
|
|
154
|
-
const CHECK_APS_PAYLOAD_LENGTH = false;
|
|
141
|
+
const DEFAULT_APS_OPTIONS = (enums_2.EmberApsOption.RETRY | enums_2.EmberApsOption.ENABLE_ROUTE_DISCOVERY | enums_2.EmberApsOption.ENABLE_ADDRESS_DISCOVERY);
|
|
155
142
|
/** Time for a ZDO request to get a callback response. ASH is 2400*6 for ACK timeout. */
|
|
156
143
|
const DEFAULT_ZDO_REQUEST_TIMEOUT = 15000; // msec
|
|
157
144
|
/** Time for a ZCL request to get a callback response. ASH is 2400*6 for ACK timeout. */
|
|
@@ -186,8 +173,6 @@ class EmberAdapter extends __1.Adapter {
|
|
|
186
173
|
oneWaitress;
|
|
187
174
|
/** Periodically retrieve counters then clear them. */
|
|
188
175
|
watchdogCountersHandle;
|
|
189
|
-
/** Hold ZDO request in process. */
|
|
190
|
-
zdoRequestBuffalo;
|
|
191
176
|
/** Sequence number used for ZDO requests. static uint8_t */
|
|
192
177
|
zdoRequestSequence;
|
|
193
178
|
/** Default radius used for broadcast ZDO requests. uint8_t */
|
|
@@ -206,16 +191,14 @@ class EmberAdapter extends __1.Adapter {
|
|
|
206
191
|
logger_1.logger.debug(`Using delay=${delay}.`, NS);
|
|
207
192
|
this.requestQueue = new requestQueue_1.EmberRequestQueue(delay);
|
|
208
193
|
this.oneWaitress = new oneWaitress_1.EmberOneWaitress();
|
|
209
|
-
this.
|
|
210
|
-
this.ezsp = new ezsp_1.Ezsp(delay, serialPortOptions);
|
|
211
|
-
this.ezsp.on(ezsp_1.EzspEvents.STACK_STATUS, this.onStackStatus.bind(this));
|
|
212
|
-
this.ezsp.on(ezsp_1.EzspEvents.MESSAGE_SENT, this.onMessageSent.bind(this));
|
|
194
|
+
this.ezsp = new ezsp_1.Ezsp(serialPortOptions);
|
|
213
195
|
this.ezsp.on(ezsp_1.EzspEvents.ZDO_RESPONSE, this.onZDOResponse.bind(this));
|
|
214
|
-
this.ezsp.on(ezsp_1.EzspEvents.END_DEVICE_ANNOUNCE, this.onEndDeviceAnnounce.bind(this));
|
|
215
196
|
this.ezsp.on(ezsp_1.EzspEvents.INCOMING_MESSAGE, this.onIncomingMessage.bind(this));
|
|
216
197
|
this.ezsp.on(ezsp_1.EzspEvents.TOUCHLINK_MESSAGE, this.onTouchlinkMessage.bind(this));
|
|
217
|
-
this.ezsp.on(ezsp_1.EzspEvents.
|
|
198
|
+
this.ezsp.on(ezsp_1.EzspEvents.STACK_STATUS, this.onStackStatus.bind(this));
|
|
218
199
|
this.ezsp.on(ezsp_1.EzspEvents.TRUST_CENTER_JOIN, this.onTrustCenterJoin.bind(this));
|
|
200
|
+
this.ezsp.on(ezsp_1.EzspEvents.MESSAGE_SENT, this.onMessageSent.bind(this));
|
|
201
|
+
this.ezsp.on(ezsp_1.EzspEvents.GREENPOWER_MESSAGE, this.onGreenpowerMessage.bind(this));
|
|
219
202
|
}
|
|
220
203
|
loadStackConfig() {
|
|
221
204
|
// store stack config in same dir as backup
|
|
@@ -253,47 +236,6 @@ class EmberAdapter extends __1.Adapter {
|
|
|
253
236
|
config.MAX_END_DEVICE_CHILDREN = DEFAULT_STACK_CONFIG.MAX_END_DEVICE_CHILDREN;
|
|
254
237
|
logger_1.logger.error(`[STACK CONFIG] Invalid MAX_END_DEVICE_CHILDREN, using default.`, NS);
|
|
255
238
|
}
|
|
256
|
-
if (!inRange(config.APS_UNICAST_MESSAGE_COUNT, 1, 255)) {
|
|
257
|
-
config.APS_UNICAST_MESSAGE_COUNT = DEFAULT_STACK_CONFIG.APS_UNICAST_MESSAGE_COUNT;
|
|
258
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid APS_UNICAST_MESSAGE_COUNT, using default.`, NS);
|
|
259
|
-
}
|
|
260
|
-
if (!inRange(config.RETRY_QUEUE_SIZE, 0, 255)) {
|
|
261
|
-
config.RETRY_QUEUE_SIZE = DEFAULT_STACK_CONFIG.RETRY_QUEUE_SIZE;
|
|
262
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid RETRY_QUEUE_SIZE, using default.`, NS);
|
|
263
|
-
}
|
|
264
|
-
if (!inRange(config.ADDRESS_TABLE_SIZE, 1, 250)) {
|
|
265
|
-
config.ADDRESS_TABLE_SIZE = DEFAULT_STACK_CONFIG.ADDRESS_TABLE_SIZE;
|
|
266
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid ADDRESS_TABLE_SIZE, using default.`, NS);
|
|
267
|
-
}
|
|
268
|
-
if (!inRange(config.TRUST_CENTER_ADDRESS_CACHE_SIZE, 0, 4)) {
|
|
269
|
-
config.TRUST_CENTER_ADDRESS_CACHE_SIZE = DEFAULT_STACK_CONFIG.TRUST_CENTER_ADDRESS_CACHE_SIZE;
|
|
270
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid TRUST_CENTER_ADDRESS_CACHE_SIZE, using default.`, NS);
|
|
271
|
-
}
|
|
272
|
-
if (!inRange(config.KEY_TABLE_SIZE, 0, 127)) {
|
|
273
|
-
config.KEY_TABLE_SIZE = DEFAULT_STACK_CONFIG.KEY_TABLE_SIZE;
|
|
274
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid KEY_TABLE_SIZE, using default.`, NS);
|
|
275
|
-
}
|
|
276
|
-
if (!inRange(config.BINDING_TABLE_SIZE, 0, 127)) {
|
|
277
|
-
config.BINDING_TABLE_SIZE = DEFAULT_STACK_CONFIG.BINDING_TABLE_SIZE;
|
|
278
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid BINDING_TABLE_SIZE, using default.`, NS);
|
|
279
|
-
}
|
|
280
|
-
if (!inRange(config.BROADCAST_TABLE_SIZE, 15, 254)) {
|
|
281
|
-
config.BROADCAST_TABLE_SIZE = DEFAULT_STACK_CONFIG.BROADCAST_TABLE_SIZE;
|
|
282
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid BROADCAST_TABLE_SIZE, using default.`, NS);
|
|
283
|
-
}
|
|
284
|
-
// min should always be enough to cover `multicastIds` in `FIXED_ENDPOINTS`
|
|
285
|
-
if (!inRange(config.MULTICAST_TABLE_SIZE, 5, 250)) {
|
|
286
|
-
config.MULTICAST_TABLE_SIZE = DEFAULT_STACK_CONFIG.MULTICAST_TABLE_SIZE;
|
|
287
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid MULTICAST_TABLE_SIZE, using default.`, NS);
|
|
288
|
-
}
|
|
289
|
-
if (![16, 26].includes(config.NEIGHBOR_TABLE_SIZE)) {
|
|
290
|
-
config.NEIGHBOR_TABLE_SIZE = DEFAULT_STACK_CONFIG.NEIGHBOR_TABLE_SIZE;
|
|
291
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid NEIGHBOR_TABLE_SIZE, using default.`, NS);
|
|
292
|
-
}
|
|
293
|
-
if (!inRange(config.SOURCE_ROUTE_TABLE_SIZE, 0, 254)) {
|
|
294
|
-
config.SOURCE_ROUTE_TABLE_SIZE = DEFAULT_STACK_CONFIG.SOURCE_ROUTE_TABLE_SIZE;
|
|
295
|
-
logger_1.logger.error(`[STACK CONFIG] Invalid SOURCE_ROUTE_TABLE_SIZE, using default.`, NS);
|
|
296
|
-
}
|
|
297
239
|
if (!inRange(config.TRANSIENT_DEVICE_TIMEOUT, 0, 65535)) {
|
|
298
240
|
config.TRANSIENT_DEVICE_TIMEOUT = DEFAULT_STACK_CONFIG.TRANSIENT_DEVICE_TIMEOUT;
|
|
299
241
|
logger_1.logger.error(`[STACK CONFIG] Invalid TRANSIENT_DEVICE_TIMEOUT, using default.`, NS);
|
|
@@ -321,27 +263,27 @@ class EmberAdapter extends __1.Adapter {
|
|
|
321
263
|
// to be extra careful, should clear network cache upon receiving this.
|
|
322
264
|
this.clearNetworkCache();
|
|
323
265
|
switch (status) {
|
|
324
|
-
case
|
|
266
|
+
case enums_2.SLStatus.NETWORK_UP: {
|
|
325
267
|
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP);
|
|
326
268
|
logger_1.logger.info(`[STACK STATUS] Network up.`, NS);
|
|
327
269
|
break;
|
|
328
270
|
}
|
|
329
|
-
case
|
|
271
|
+
case enums_2.SLStatus.NETWORK_DOWN: {
|
|
330
272
|
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN);
|
|
331
273
|
logger_1.logger.info(`[STACK STATUS] Network down.`, NS);
|
|
332
274
|
break;
|
|
333
275
|
}
|
|
334
|
-
case
|
|
276
|
+
case enums_2.SLStatus.ZIGBEE_NETWORK_OPENED: {
|
|
335
277
|
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_OPENED);
|
|
336
278
|
logger_1.logger.info(`[STACK STATUS] Network opened.`, NS);
|
|
337
279
|
break;
|
|
338
280
|
}
|
|
339
|
-
case
|
|
281
|
+
case enums_2.SLStatus.ZIGBEE_NETWORK_CLOSED: {
|
|
340
282
|
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_CLOSED);
|
|
341
283
|
logger_1.logger.info(`[STACK STATUS] Network closed.`, NS);
|
|
342
284
|
break;
|
|
343
285
|
}
|
|
344
|
-
case
|
|
286
|
+
case enums_2.SLStatus.ZIGBEE_CHANNEL_CHANGED: {
|
|
345
287
|
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED);
|
|
346
288
|
// invalidate cache
|
|
347
289
|
this.networkCache.parameters.radioChannel = consts_2.INVALID_RADIO_CHANNEL;
|
|
@@ -349,7 +291,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
349
291
|
break;
|
|
350
292
|
}
|
|
351
293
|
default: {
|
|
352
|
-
logger_1.logger.debug(`[STACK STATUS] ${
|
|
294
|
+
logger_1.logger.debug(`[STACK STATUS] ${enums_2.SLStatus[status]}.`, NS);
|
|
353
295
|
break;
|
|
354
296
|
}
|
|
355
297
|
}
|
|
@@ -364,16 +306,16 @@ class EmberAdapter extends __1.Adapter {
|
|
|
364
306
|
* @param messageTag
|
|
365
307
|
* @param status
|
|
366
308
|
*/
|
|
367
|
-
async onMessageSent(type, indexOrDestination, apsFrame, messageTag
|
|
368
|
-
if (status ===
|
|
309
|
+
async onMessageSent(status, type, indexOrDestination, apsFrame, messageTag) {
|
|
310
|
+
if (status === enums_2.SLStatus.ZIGBEE_DELIVERY_FAILED) {
|
|
369
311
|
// no ACK was received from the destination
|
|
370
312
|
switch (type) {
|
|
371
|
-
case
|
|
372
|
-
case
|
|
373
|
-
case
|
|
374
|
-
case
|
|
313
|
+
case enums_2.EmberOutgoingMessageType.BROADCAST:
|
|
314
|
+
case enums_2.EmberOutgoingMessageType.BROADCAST_WITH_ALIAS:
|
|
315
|
+
case enums_2.EmberOutgoingMessageType.MULTICAST:
|
|
316
|
+
case enums_2.EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
|
|
375
317
|
// BC/MC not checking for message sent, avoid unnecessary waitress lookups
|
|
376
|
-
logger_1.logger.error(`Delivery of ${
|
|
318
|
+
logger_1.logger.error(`Delivery of ${enums_2.EmberOutgoingMessageType[type]} failed for "${indexOrDestination}" `
|
|
377
319
|
+ `[apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
|
|
378
320
|
break;
|
|
379
321
|
}
|
|
@@ -384,8 +326,8 @@ class EmberAdapter extends __1.Adapter {
|
|
|
384
326
|
}
|
|
385
327
|
}
|
|
386
328
|
}
|
|
387
|
-
else if (status ===
|
|
388
|
-
if (type ===
|
|
329
|
+
else if (status === enums_2.SLStatus.OK) {
|
|
330
|
+
if (type === enums_2.EmberOutgoingMessageType.MULTICAST && apsFrame.destinationEndpoint === 0xFF &&
|
|
389
331
|
apsFrame.groupId < consts_2.EMBER_MIN_BROADCAST_ADDRESS && !this.multicastTable.includes(apsFrame.groupId)) {
|
|
390
332
|
// workaround for devices using multicast for state update (coordinator passthrough)
|
|
391
333
|
const tableIdx = this.multicastTable.length;
|
|
@@ -399,13 +341,13 @@ class EmberAdapter extends __1.Adapter {
|
|
|
399
341
|
await new Promise((resolve, reject) => {
|
|
400
342
|
this.requestQueue.enqueue(async () => {
|
|
401
343
|
const status = (await this.ezsp.ezspSetMulticastTableEntry(tableIdx, multicastEntry));
|
|
402
|
-
if (status !==
|
|
403
|
-
logger_1.logger.error(`Failed to register group "${multicastEntry.multicastId}" in multicast table with status=${
|
|
344
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
345
|
+
logger_1.logger.error(`Failed to register group "${multicastEntry.multicastId}" in multicast table with status=${enums_2.SLStatus[status]}.`, NS);
|
|
404
346
|
return status;
|
|
405
347
|
}
|
|
406
348
|
logger_1.logger.debug(`Registered multicast table entry (${tableIdx}): ${JSON.stringify(multicastEntry)}.`, NS);
|
|
407
349
|
resolve();
|
|
408
|
-
return
|
|
350
|
+
return enums_2.SLStatus.OK;
|
|
409
351
|
}, (reason) => {
|
|
410
352
|
// remove to allow retry on next occurrence
|
|
411
353
|
this.multicastTable.splice(tableIdx, 1);
|
|
@@ -419,26 +361,31 @@ class EmberAdapter extends __1.Adapter {
|
|
|
419
361
|
/**
|
|
420
362
|
* Emitted from @see Ezsp.ezspIncomingMessageHandler
|
|
421
363
|
*
|
|
422
|
-
* @param
|
|
364
|
+
* @param apsFrame The APS frame associated with the response.
|
|
423
365
|
* @param sender The sender of the response. Should match `payload.nodeId` in many responses.
|
|
424
|
-
* @param
|
|
366
|
+
* @param messageContents The content of the response.
|
|
425
367
|
*/
|
|
426
|
-
async onZDOResponse(
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
368
|
+
async onZDOResponse(apsFrame, sender, messageContents) {
|
|
369
|
+
try {
|
|
370
|
+
const payload = buffaloZdo_1.BuffaloZdo.readResponse(apsFrame.clusterId, messageContents);
|
|
371
|
+
logger_1.logger.debug(`<~~~ [ZDO ${Zdo.ClusterId[apsFrame.clusterId]} from=${sender} ${payload ? JSON.stringify(payload) : 'OK'}]`, NS);
|
|
372
|
+
this.oneWaitress.resolveZDO(sender, apsFrame, payload);
|
|
373
|
+
if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
|
|
374
|
+
this.emit(events_1.Events.networkAddress, {
|
|
375
|
+
networkAddress: payload.nwkAddress,
|
|
376
|
+
ieeeAddr: payload.eui64
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
else if (apsFrame.clusterId === Zdo.ClusterId.END_DEVICE_ANNOUNCE) {
|
|
380
|
+
this.emit(events_1.Events.deviceAnnounce, {
|
|
381
|
+
networkAddress: payload.nwkAddress,
|
|
382
|
+
ieeeAddr: payload.eui64
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
this.oneWaitress.resolveZDO(sender, apsFrame, error);
|
|
388
|
+
}
|
|
442
389
|
}
|
|
443
390
|
/**
|
|
444
391
|
* Emitted from @see Ezsp.ezspIncomingMessageHandler
|
|
@@ -458,7 +405,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
458
405
|
endpoint: apsFrame.sourceEndpoint,
|
|
459
406
|
linkquality: lastHopLqi,
|
|
460
407
|
groupID: apsFrame.groupId,
|
|
461
|
-
wasBroadcast: ((type ===
|
|
408
|
+
wasBroadcast: ((type === enums_2.EmberIncomingMessageType.BROADCAST) || (type === enums_2.EmberIncomingMessageType.BROADCAST_LOOPBACK)),
|
|
462
409
|
destinationEndpoint: apsFrame.destinationEndpoint,
|
|
463
410
|
};
|
|
464
411
|
this.oneWaitress.resolveZCL(payload);
|
|
@@ -543,7 +490,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
543
490
|
* @param parentOfNewNodeId
|
|
544
491
|
*/
|
|
545
492
|
async onTrustCenterJoin(newNodeId, newNodeEui64, status, policyDecision, parentOfNewNodeId) {
|
|
546
|
-
if (status ===
|
|
493
|
+
if (status === enums_2.EmberDeviceUpdate.DEVICE_LEFT) {
|
|
547
494
|
const payload = {
|
|
548
495
|
networkAddress: newNodeId,
|
|
549
496
|
ieeeAddr: newNodeEui64,
|
|
@@ -551,7 +498,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
551
498
|
this.emit(events_1.Events.deviceLeave, payload);
|
|
552
499
|
}
|
|
553
500
|
else {
|
|
554
|
-
if (policyDecision !==
|
|
501
|
+
if (policyDecision !== enums_2.EmberJoinDecision.DENY_JOIN) {
|
|
555
502
|
const payload = {
|
|
556
503
|
networkAddress: newNodeId,
|
|
557
504
|
ieeeAddr: newNodeEui64,
|
|
@@ -566,7 +513,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
566
513
|
this.manufacturerCode = joinManufCode;
|
|
567
514
|
this.emit(events_1.Events.deviceJoined, payload);
|
|
568
515
|
resolve();
|
|
569
|
-
return
|
|
516
|
+
return enums_2.SLStatus.OK;
|
|
570
517
|
}, reject, true);
|
|
571
518
|
});
|
|
572
519
|
}
|
|
@@ -588,14 +535,13 @@ class EmberAdapter extends __1.Adapter {
|
|
|
588
535
|
const ashCounters = this.ezsp.ash.readAndClearCounters();
|
|
589
536
|
logger_1.logger.info(`[ASH COUNTERS] ${ashCounters.join(',')}`, NS);
|
|
590
537
|
resolve();
|
|
591
|
-
return
|
|
538
|
+
return enums_2.SLStatus.OK;
|
|
592
539
|
}, reject);
|
|
593
540
|
});
|
|
594
541
|
}
|
|
595
542
|
initVariables() {
|
|
596
543
|
this.ezsp.removeAllListeners(ezsp_1.EzspEvents.NCP_NEEDS_RESET_AND_INIT);
|
|
597
544
|
clearInterval(this.watchdogCountersHandle);
|
|
598
|
-
this.zdoRequestBuffalo.setPosition(0);
|
|
599
545
|
this.zdoRequestSequence = 0; // start at 1
|
|
600
546
|
this.zdoRequestRadius = 255;
|
|
601
547
|
this.interpanLock = false;
|
|
@@ -612,25 +558,39 @@ class EmberAdapter extends __1.Adapter {
|
|
|
612
558
|
let result = "resumed";
|
|
613
559
|
// NOTE: something deep in this call can throw too
|
|
614
560
|
const startResult = (await this.ezsp.start());
|
|
615
|
-
if (startResult !==
|
|
616
|
-
throw new Error(`Failed to start EZSP layer with status=${
|
|
561
|
+
if (startResult !== enums_2.EzspStatus.SUCCESS) {
|
|
562
|
+
throw new Error(`Failed to start EZSP layer with status=${enums_2.EzspStatus[startResult]}.`);
|
|
617
563
|
}
|
|
618
564
|
// call before any other command, else fails
|
|
619
565
|
await this.emberVersion();
|
|
620
|
-
|
|
621
|
-
await this.
|
|
622
|
-
|
|
566
|
+
/** MAC indirect timeout should be 7.68 secs (STACK_PROFILE_ZIGBEE_PRO) */
|
|
567
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.INDIRECT_TRANSMISSION_TIMEOUT, 7680);
|
|
568
|
+
/** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 (STACK_PROFILE_ZIGBEE_PRO) */
|
|
569
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.MAX_HOPS, 30);
|
|
570
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.SUPPORTED_NETWORKS, 1);
|
|
571
|
+
// allow other devices to modify the binding table
|
|
572
|
+
await this.emberSetEzspPolicy(enums_1.EzspPolicyId.BINDING_MODIFICATION_POLICY, enums_1.EzspDecisionId.CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS);
|
|
573
|
+
// return message tag only in ezspMessageSentHandler()
|
|
574
|
+
await this.emberSetEzspPolicy(enums_1.EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, enums_1.EzspDecisionId.MESSAGE_TAG_ONLY_IN_CALLBACK);
|
|
575
|
+
await this.emberSetEzspValue(enums_1.EzspValueId.TRANSIENT_DEVICE_TIMEOUT, 2, (0, math_1.lowHighBytes)(this.stackConfig.TRANSIENT_DEVICE_TIMEOUT));
|
|
576
|
+
await this.ezsp.ezspSetManufacturerCode(this.manufacturerCode);
|
|
577
|
+
// network security init
|
|
578
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.STACK_PROFILE, consts_2.STACK_PROFILE_ZIGBEE_PRO);
|
|
579
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.SECURITY_LEVEL, consts_2.SECURITY_LEVEL_Z3);
|
|
580
|
+
// common configs
|
|
581
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.MAX_END_DEVICE_CHILDREN, this.stackConfig.MAX_END_DEVICE_CHILDREN);
|
|
582
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.END_DEVICE_POLL_TIMEOUT, this.stackConfig.END_DEVICE_POLL_TIMEOUT);
|
|
583
|
+
await this.emberSetEzspConfigValue(enums_1.EzspConfigId.TRANSIENT_KEY_TIMEOUT_S, this.stackConfig.TRANSIENT_KEY_TIMEOUT_S);
|
|
623
584
|
// WARNING: From here on EZSP commands that affect memory allocation on the NCP should no longer be called (like resizing tables)
|
|
624
585
|
await this.registerFixedEndpoints();
|
|
625
586
|
this.clearNetworkCache();
|
|
626
587
|
result = (await this.initTrustCenter());
|
|
627
588
|
// after network UP, as per SDK, ensures clean slate
|
|
628
589
|
await this.initNCPConcentrator();
|
|
629
|
-
// await (this.emberStartEnergyScan());// TODO: via config of some kind, better off waiting for UI supports though
|
|
630
590
|
// populate network cache info
|
|
631
591
|
const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
|
|
632
|
-
if (status !==
|
|
633
|
-
throw new Error(`Failed to get network parameters with status=${
|
|
592
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
593
|
+
throw new Error(`Failed to get network parameters with status=${enums_2.SLStatus[status]}.`);
|
|
634
594
|
}
|
|
635
595
|
this.networkCache.parameters = parameters;
|
|
636
596
|
this.networkCache.status = (await this.ezsp.ezspNetworkState());
|
|
@@ -640,66 +600,6 @@ class EmberAdapter extends __1.Adapter {
|
|
|
640
600
|
this.requestQueue.startDispatching();
|
|
641
601
|
return result;
|
|
642
602
|
}
|
|
643
|
-
/**
|
|
644
|
-
* NCP Config init. Should always be called first in the init stack (after version cmd).
|
|
645
|
-
* @returns
|
|
646
|
-
*/
|
|
647
|
-
async initNCPPreConfiguration() {
|
|
648
|
-
// this can only decrease, not increase, NCP-side value
|
|
649
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.ADDRESS_TABLE_SIZE, this.stackConfig.ADDRESS_TABLE_SIZE);
|
|
650
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE, this.stackConfig.TRUST_CENTER_ADDRESS_CACHE_SIZE);
|
|
651
|
-
// BUG 14222: If stack profile is 2 (ZigBee Pro), we need to enforce
|
|
652
|
-
// the standard stack configuration values for that feature set.
|
|
653
|
-
/** MAC indirect timeout should be 7.68 secs */
|
|
654
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.INDIRECT_TRANSMISSION_TIMEOUT, 7680);
|
|
655
|
-
/** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 */
|
|
656
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_HOPS, 30);
|
|
657
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TX_POWER_MODE, enums_3.EmberTXPowerMode.USE_TOKEN);
|
|
658
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SUPPORTED_NETWORKS, 1);
|
|
659
|
-
await this.emberSetEzspValue(enums_2.EzspValueId.END_DEVICE_KEEP_ALIVE_SUPPORT_MODE, 1, [enums_3.EmberKeepAliveMode.KEEP_ALIVE_SUPPORT_ALL]);
|
|
660
|
-
// allow other devices to modify the binding table
|
|
661
|
-
await this.emberSetEzspPolicy(enums_2.EzspPolicyId.BINDING_MODIFICATION_POLICY, enums_2.EzspDecisionId.CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS);
|
|
662
|
-
// return message tag and message contents in ezspMessageSentHandler()
|
|
663
|
-
await this.emberSetEzspPolicy(enums_2.EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, enums_2.EzspDecisionId.MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK);
|
|
664
|
-
await this.emberSetEzspValue(enums_2.EzspValueId.MAXIMUM_INCOMING_TRANSFER_SIZE, 2, (0, math_1.lowHighBytes)(consts_2.MAXIMUM_APS_PAYLOAD_LENGTH));
|
|
665
|
-
await this.emberSetEzspValue(enums_2.EzspValueId.MAXIMUM_OUTGOING_TRANSFER_SIZE, 2, (0, math_1.lowHighBytes)(consts_2.MAXIMUM_APS_PAYLOAD_LENGTH));
|
|
666
|
-
await this.emberSetEzspValue(enums_2.EzspValueId.TRANSIENT_DEVICE_TIMEOUT, 2, (0, math_1.lowHighBytes)(this.stackConfig.TRANSIENT_DEVICE_TIMEOUT));
|
|
667
|
-
await this.ezsp.ezspSetManufacturerCode(this.manufacturerCode);
|
|
668
|
-
// network security init
|
|
669
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.STACK_PROFILE, consts_2.STACK_PROFILE_ZIGBEE_PRO);
|
|
670
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SECURITY_LEVEL, consts_2.SECURITY_LEVEL_Z3);
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* NCP Address table init.
|
|
674
|
-
* @returns
|
|
675
|
-
*/
|
|
676
|
-
async initNCPAddressTable() {
|
|
677
|
-
const desiredTableSize = this.stackConfig.ADDRESS_TABLE_SIZE;
|
|
678
|
-
// If the host and the ncp disagree on the address table size, explode.
|
|
679
|
-
const [status, addressTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.ADDRESS_TABLE_SIZE));
|
|
680
|
-
// After the change of ncp memory model in UC, we can not increase the default NCP table sizes anymore.
|
|
681
|
-
// Therefore, checking for desiredTableSize == (ncp)addressTableSize might not be always true anymore
|
|
682
|
-
// assert(desiredTableSize <= addressTableSize);
|
|
683
|
-
if ((status !== enums_3.EzspStatus.SUCCESS) || (addressTableSize > desiredTableSize)) {
|
|
684
|
-
throw new Error(`[INIT] NCP (${addressTableSize}) disagrees with Host (min ${desiredTableSize}) on table size. status=${enums_3.EzspStatus[status]}`);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* NCP configuration init
|
|
689
|
-
*/
|
|
690
|
-
async initNCPConfiguration() {
|
|
691
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.BINDING_TABLE_SIZE, this.stackConfig.BINDING_TABLE_SIZE);
|
|
692
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.KEY_TABLE_SIZE, this.stackConfig.KEY_TABLE_SIZE);
|
|
693
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_END_DEVICE_CHILDREN, this.stackConfig.MAX_END_DEVICE_CHILDREN);
|
|
694
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.APS_UNICAST_MESSAGE_COUNT, this.stackConfig.APS_UNICAST_MESSAGE_COUNT);
|
|
695
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.BROADCAST_TABLE_SIZE, this.stackConfig.BROADCAST_TABLE_SIZE);
|
|
696
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.NEIGHBOR_TABLE_SIZE, this.stackConfig.NEIGHBOR_TABLE_SIZE);
|
|
697
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.END_DEVICE_POLL_TIMEOUT, this.stackConfig.END_DEVICE_POLL_TIMEOUT);
|
|
698
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRANSIENT_KEY_TIMEOUT_S, this.stackConfig.TRANSIENT_KEY_TIMEOUT_S);
|
|
699
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.RETRY_QUEUE_SIZE, this.stackConfig.RETRY_QUEUE_SIZE);
|
|
700
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SOURCE_ROUTE_TABLE_SIZE, this.stackConfig.SOURCE_ROUTE_TABLE_SIZE);
|
|
701
|
-
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MULTICAST_TABLE_SIZE, this.stackConfig.MULTICAST_TABLE_SIZE);
|
|
702
|
-
}
|
|
703
603
|
/**
|
|
704
604
|
* NCP concentrator init. Also enables source route discovery mode with RESCHEDULE.
|
|
705
605
|
*
|
|
@@ -716,10 +616,10 @@ class EmberAdapter extends __1.Adapter {
|
|
|
716
616
|
*/
|
|
717
617
|
async initNCPConcentrator() {
|
|
718
618
|
const status = (await this.ezsp.ezspSetConcentrator(true, (this.stackConfig.CONCENTRATOR_RAM_TYPE === 'low') ? consts_2.EMBER_LOW_RAM_CONCENTRATOR : consts_2.EMBER_HIGH_RAM_CONCENTRATOR, this.stackConfig.CONCENTRATOR_MIN_TIME, this.stackConfig.CONCENTRATOR_MAX_TIME, this.stackConfig.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, this.stackConfig.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, this.stackConfig.CONCENTRATOR_MAX_HOPS));
|
|
719
|
-
if (status !==
|
|
720
|
-
throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${status}.`);
|
|
619
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
620
|
+
throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${enums_2.SLStatus[status]}.`);
|
|
721
621
|
}
|
|
722
|
-
const remainTilMTORR = (await this.ezsp.ezspSetSourceRouteDiscoveryMode(
|
|
622
|
+
const remainTilMTORR = (await this.ezsp.ezspSetSourceRouteDiscoveryMode(enums_2.EmberSourceRouteDiscoveryMode.RESCHEDULE));
|
|
723
623
|
logger_1.logger.info(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`, NS);
|
|
724
624
|
}
|
|
725
625
|
/**
|
|
@@ -733,16 +633,16 @@ class EmberAdapter extends __1.Adapter {
|
|
|
733
633
|
}
|
|
734
634
|
const [epStatus,] = (await this.ezsp.ezspGetEndpointFlags(ep.endpoint));
|
|
735
635
|
// endpoint not already registered
|
|
736
|
-
if (epStatus !==
|
|
636
|
+
if (epStatus !== enums_2.SLStatus.OK) {
|
|
737
637
|
// check to see if ezspAddEndpoint needs to be called
|
|
738
638
|
// if ezspInit is called without NCP reset, ezspAddEndpoint is not necessary and will return an error
|
|
739
639
|
const status = (await this.ezsp.ezspAddEndpoint(ep.endpoint, ep.profileId, ep.deviceId, ep.deviceVersion, ep.inClusterList.slice(), // copy
|
|
740
640
|
ep.outClusterList.slice()));
|
|
741
|
-
if (status ===
|
|
742
|
-
logger_1.logger.debug(`Registered endpoint
|
|
641
|
+
if (status === enums_2.SLStatus.OK) {
|
|
642
|
+
logger_1.logger.debug(`Registered endpoint '${ep.endpoint}'.`, NS);
|
|
743
643
|
}
|
|
744
644
|
else {
|
|
745
|
-
throw new Error(`Failed to register endpoint "${ep.endpoint}" with status=${
|
|
645
|
+
throw new Error(`Failed to register endpoint "${ep.endpoint}" with status=${enums_2.SLStatus[status]}.`);
|
|
746
646
|
}
|
|
747
647
|
}
|
|
748
648
|
else {
|
|
@@ -755,8 +655,8 @@ class EmberAdapter extends __1.Adapter {
|
|
|
755
655
|
networkIndex: ep.networkIndex,
|
|
756
656
|
};
|
|
757
657
|
const status = (await this.ezsp.ezspSetMulticastTableEntry(this.multicastTable.length, multicastEntry));
|
|
758
|
-
if (status !==
|
|
759
|
-
throw new Error(`Failed to register group "${multicastId}" in multicast table with status=${
|
|
658
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
659
|
+
throw new Error(`Failed to register group "${multicastId}" in multicast table with status=${enums_2.SLStatus[status]}.`);
|
|
760
660
|
}
|
|
761
661
|
logger_1.logger.debug(`Registered multicast table entry (${this.multicastTable.length}): ${JSON.stringify(multicastEntry)}.`, NS);
|
|
762
662
|
this.multicastTable.push(multicastEntry.multicastId);
|
|
@@ -770,49 +670,47 @@ class EmberAdapter extends __1.Adapter {
|
|
|
770
670
|
async initTrustCenter() {
|
|
771
671
|
// init TC policies
|
|
772
672
|
{
|
|
773
|
-
let status = (await this.emberSetEzspPolicy(
|
|
774
|
-
if (status !==
|
|
673
|
+
let status = (await this.emberSetEzspPolicy(enums_1.EzspPolicyId.TC_KEY_REQUEST_POLICY, enums_1.EzspDecisionId.ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY));
|
|
674
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
775
675
|
throw new Error(`[INIT TC] Failed to set EzspPolicyId TC_KEY_REQUEST_POLICY to ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY `
|
|
776
|
-
+ `with status=${
|
|
676
|
+
+ `with status=${enums_2.SLStatus[status]}.`);
|
|
777
677
|
}
|
|
778
|
-
const
|
|
779
|
-
status =
|
|
780
|
-
if (status !==
|
|
781
|
-
throw new Error(`[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${
|
|
782
|
-
+ `with status=${
|
|
678
|
+
const appKeyRequestsPolicy = ALLOW_APP_KEY_REQUESTS ? enums_1.EzspDecisionId.ALLOW_APP_KEY_REQUESTS : enums_1.EzspDecisionId.DENY_APP_KEY_REQUESTS;
|
|
679
|
+
status = await this.emberSetEzspPolicy(enums_1.EzspPolicyId.APP_KEY_REQUEST_POLICY, appKeyRequestsPolicy);
|
|
680
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
681
|
+
throw new Error(`[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${enums_1.EzspDecisionId[appKeyRequestsPolicy]} `
|
|
682
|
+
+ `with status=${enums_2.SLStatus[status]}.`);
|
|
783
683
|
}
|
|
784
|
-
status = (await this.emberSetJoinPolicy(
|
|
785
|
-
if (status !==
|
|
786
|
-
throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${
|
|
684
|
+
status = (await this.emberSetJoinPolicy(enums_2.EmberJoinDecision.USE_PRECONFIGURED_KEY));
|
|
685
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
686
|
+
throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${enums_2.SLStatus[status]}.`);
|
|
787
687
|
}
|
|
788
688
|
}
|
|
789
689
|
const configNetworkKey = Buffer.from(this.networkOptions.networkKey);
|
|
790
690
|
const networkInitStruct = {
|
|
791
|
-
bitmask: (
|
|
691
|
+
bitmask: (enums_2.EmberNetworkInitBitmask.PARENT_INFO_IN_TOKEN | enums_2.EmberNetworkInitBitmask.END_DEVICE_REJOIN_ON_REBOOT)
|
|
792
692
|
};
|
|
793
693
|
const initStatus = (await this.ezsp.ezspNetworkInit(networkInitStruct));
|
|
794
|
-
logger_1.logger.debug(`[INIT TC] Network init status=${
|
|
795
|
-
if ((initStatus !==
|
|
796
|
-
throw new Error(`[INIT TC] Failed network init request with status=${
|
|
694
|
+
logger_1.logger.debug(`[INIT TC] Network init status=${enums_2.SLStatus[initStatus]}.`, NS);
|
|
695
|
+
if ((initStatus !== enums_2.SLStatus.OK) && (initStatus !== enums_2.SLStatus.NOT_JOINED)) {
|
|
696
|
+
throw new Error(`[INIT TC] Failed network init request with status=${enums_2.SLStatus[initStatus]}.`);
|
|
797
697
|
}
|
|
798
698
|
let action = NetworkInitAction.DONE;
|
|
799
|
-
if (initStatus ===
|
|
699
|
+
if (initStatus === enums_2.SLStatus.OK) {
|
|
800
700
|
// network
|
|
801
701
|
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT TC] Network init');
|
|
802
702
|
const [npStatus, nodeType, netParams] = (await this.ezsp.ezspGetNetworkParameters());
|
|
803
|
-
logger_1.logger.debug(`[INIT TC] Current network
|
|
804
|
-
|
|
805
|
-
if ((npStatus === enums_3.EmberStatus.SUCCESS) && (nodeType === enums_3.EmberNodeType.COORDINATOR) && (this.networkOptions.panID === netParams.panId)
|
|
703
|
+
logger_1.logger.debug(`[INIT TC] Current adapter network: nodeType=${enums_2.EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS);
|
|
704
|
+
if ((npStatus === enums_2.SLStatus.OK) && (nodeType === enums_2.EmberNodeType.COORDINATOR) && (this.networkOptions.panID === netParams.panId)
|
|
806
705
|
&& ((0, es6_1.default)(this.networkOptions.extendedPanID, netParams.extendedPanId))) {
|
|
807
706
|
// config matches adapter so far, no error, we can check the network key
|
|
808
707
|
const context = (0, initters_1.initSecurityManagerContext)();
|
|
809
|
-
context.coreKeyType =
|
|
708
|
+
context.coreKeyType = enums_2.SecManKeyType.NETWORK;
|
|
810
709
|
context.keyIndex = 0;
|
|
811
|
-
const [
|
|
812
|
-
if (nkStatus !==
|
|
813
|
-
throw new Error(`[BACKUP] Failed to export Network Key with status=${
|
|
710
|
+
const [nkStatus, networkKey] = (await this.ezsp.ezspExportKey(context));
|
|
711
|
+
if (nkStatus !== enums_2.SLStatus.OK) {
|
|
712
|
+
throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_2.SLStatus[nkStatus]}.`);
|
|
814
713
|
}
|
|
815
|
-
logger_1.logger.debug(`[INIT TC] Current NCP network: networkKey=${networkKey.contents.toString('hex')}`, NS);
|
|
816
714
|
// config doesn't match adapter anymore
|
|
817
715
|
if (!networkKey.contents.equals(configNetworkKey)) {
|
|
818
716
|
action = NetworkInitAction.LEAVE;
|
|
@@ -823,10 +721,10 @@ class EmberAdapter extends __1.Adapter {
|
|
|
823
721
|
action = NetworkInitAction.LEAVE;
|
|
824
722
|
}
|
|
825
723
|
if (action === NetworkInitAction.LEAVE) {
|
|
826
|
-
logger_1.logger.info(`[INIT TC]
|
|
724
|
+
logger_1.logger.info(`[INIT TC] Adapter network does not match config. Leaving network...`, NS);
|
|
827
725
|
const leaveStatus = (await this.ezsp.ezspLeaveNetwork());
|
|
828
|
-
if (leaveStatus !==
|
|
829
|
-
throw new Error(`[INIT TC] Failed leave network request with status=${
|
|
726
|
+
if (leaveStatus !== enums_2.SLStatus.OK) {
|
|
727
|
+
throw new Error(`[INIT TC] Failed leave network request with status=${enums_2.SLStatus[leaveStatus]}.`);
|
|
830
728
|
}
|
|
831
729
|
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT TC] Leave network');
|
|
832
730
|
await (0, utils_1.Wait)(200); // settle down
|
|
@@ -834,7 +732,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
834
732
|
}
|
|
835
733
|
}
|
|
836
734
|
const backup = this.getStoredBackup();
|
|
837
|
-
if ((initStatus ===
|
|
735
|
+
if ((initStatus === enums_2.SLStatus.NOT_JOINED) || (action === NetworkInitAction.LEFT)) {
|
|
838
736
|
// no network
|
|
839
737
|
if (backup != null) {
|
|
840
738
|
if ((this.networkOptions.panID === backup.networkOptions.panId)
|
|
@@ -863,14 +761,12 @@ class EmberAdapter extends __1.Adapter {
|
|
|
863
761
|
logger_1.logger.info(`[INIT TC] Forming from backup.`, NS);
|
|
864
762
|
const keyList = backup.devices.map((device) => {
|
|
865
763
|
const octets = Array.from(device.ieeeAddress.reverse());
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
deviceEui64,
|
|
764
|
+
return {
|
|
765
|
+
deviceEui64: `0x${octets.map(octet => octet.toString(16).padStart(2, '0')).join('')}`,
|
|
869
766
|
key: { contents: device.linkKey.key },
|
|
870
767
|
outgoingFrameCounter: device.linkKey.txCounter,
|
|
871
768
|
incomingFrameCounter: device.linkKey.rxCounter,
|
|
872
769
|
};
|
|
873
|
-
return key;
|
|
874
770
|
});
|
|
875
771
|
// before forming
|
|
876
772
|
await this.importLinkKeys(keyList);
|
|
@@ -885,7 +781,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
885
781
|
break;
|
|
886
782
|
}
|
|
887
783
|
case NetworkInitAction.DONE: {
|
|
888
|
-
logger_1.logger.info(`[INIT TC]
|
|
784
|
+
logger_1.logger.info(`[INIT TC] Adapter network matches config.`, NS);
|
|
889
785
|
break;
|
|
890
786
|
}
|
|
891
787
|
default: {
|
|
@@ -902,9 +798,9 @@ class EmberAdapter extends __1.Adapter {
|
|
|
902
798
|
// // XXX: no idea here on the proper timer value, but this will block the network for several seconds on exec
|
|
903
799
|
// // (probably have to take the behavior of sleepy-end devices into account to improve chances of reaching everyone right away?)
|
|
904
800
|
// setTimeout(async () => {
|
|
905
|
-
// this.requestQueue.enqueue(async (): Promise<
|
|
801
|
+
// this.requestQueue.enqueue(async (): Promise<SLStatus> => {
|
|
906
802
|
// await this.broadcastNetworkKeyUpdate();
|
|
907
|
-
// return
|
|
803
|
+
// return SLStatus.OK;
|
|
908
804
|
// }, logger.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected
|
|
909
805
|
// }, 300000);
|
|
910
806
|
logger_1.logger.warning(`[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.`, NS);
|
|
@@ -916,30 +812,30 @@ class EmberAdapter extends __1.Adapter {
|
|
|
916
812
|
*/
|
|
917
813
|
async formNetwork(fromBackup, networkKey, networkKeySequenceNumber, panId, extendedPanId, radioChannel, tcLinkKey) {
|
|
918
814
|
const state = {
|
|
919
|
-
bitmask: (
|
|
920
|
-
|
|
|
921
|
-
|
|
|
815
|
+
bitmask: (enums_2.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY | enums_2.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
|
|
816
|
+
| enums_2.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY | enums_2.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY
|
|
817
|
+
| enums_2.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY),
|
|
922
818
|
preconfiguredKey: { contents: tcLinkKey },
|
|
923
819
|
networkKey: { contents: networkKey },
|
|
924
820
|
networkKeySequenceNumber: networkKeySequenceNumber,
|
|
925
821
|
preconfiguredTrustCenterEui64: ZSpec.BLANK_EUI64,
|
|
926
822
|
};
|
|
927
823
|
if (fromBackup) {
|
|
928
|
-
state.bitmask |=
|
|
824
|
+
state.bitmask |= enums_2.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET;
|
|
929
825
|
}
|
|
930
|
-
let
|
|
931
|
-
if (
|
|
932
|
-
throw new Error(`[INIT FORM] Failed to set initial security state with status=${
|
|
826
|
+
let status = (await this.ezsp.ezspSetInitialSecurityState(state));
|
|
827
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
828
|
+
throw new Error(`[INIT FORM] Failed to set initial security state with status=${enums_2.SLStatus[status]}.`);
|
|
933
829
|
}
|
|
934
|
-
const extended = (
|
|
935
|
-
|
|
936
|
-
if (
|
|
937
|
-
throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${
|
|
830
|
+
const extended = (enums_2.EmberExtendedSecurityBitmask.JOINER_GLOBAL_LINK_KEY | enums_2.EmberExtendedSecurityBitmask.NWK_LEAVE_REQUEST_NOT_ALLOWED);
|
|
831
|
+
status = (await this.ezsp.ezspSetExtendedSecurityBitmask(extended));
|
|
832
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
833
|
+
throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${enums_2.SLStatus[status]}.`);
|
|
938
834
|
}
|
|
939
|
-
if (!fromBackup
|
|
940
|
-
|
|
941
|
-
if (
|
|
942
|
-
|
|
835
|
+
if (!fromBackup) {
|
|
836
|
+
status = await this.ezsp.ezspClearKeyTable();
|
|
837
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
838
|
+
logger_1.logger.error(`[INIT FORM] Failed to clear key table with status=${enums_2.SLStatus[status]}.`, NS);
|
|
943
839
|
}
|
|
944
840
|
}
|
|
945
841
|
const netParams = {
|
|
@@ -947,19 +843,19 @@ class EmberAdapter extends __1.Adapter {
|
|
|
947
843
|
extendedPanId,
|
|
948
844
|
radioTxPower: 5,
|
|
949
845
|
radioChannel,
|
|
950
|
-
joinMethod:
|
|
846
|
+
joinMethod: enums_2.EmberJoinMethod.MAC_ASSOCIATION,
|
|
951
847
|
nwkManagerId: ZSpec.COORDINATOR_ADDRESS,
|
|
952
848
|
nwkUpdateId: 0,
|
|
953
849
|
channels: consts_2.EMBER_ALL_802_15_4_CHANNELS_MASK,
|
|
954
850
|
};
|
|
955
851
|
logger_1.logger.info(`[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`, NS);
|
|
956
|
-
|
|
957
|
-
if (
|
|
958
|
-
throw new Error(`[INIT FORM] Failed form network request with status=${
|
|
852
|
+
status = (await this.ezsp.ezspFormNetwork(netParams));
|
|
853
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
854
|
+
throw new Error(`[INIT FORM] Failed form network request with status=${enums_2.SLStatus[status]}.`);
|
|
959
855
|
}
|
|
960
856
|
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT FORM] Form network');
|
|
961
|
-
|
|
962
|
-
logger_1.logger.debug(`[INIT FORM] Start writing stack tokens status=${
|
|
857
|
+
status = await this.ezsp.ezspStartWritingStackTokens();
|
|
858
|
+
logger_1.logger.debug(`[INIT FORM] Start writing stack tokens status=${enums_2.SLStatus[status]}.`, NS);
|
|
963
859
|
logger_1.logger.info(`[INIT FORM] New network formed!`, NS);
|
|
964
860
|
}
|
|
965
861
|
/**
|
|
@@ -1000,27 +896,27 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1000
896
|
* @return List of keys data with AES hashed keys
|
|
1001
897
|
*/
|
|
1002
898
|
async exportLinkKeys() {
|
|
1003
|
-
const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(
|
|
1004
|
-
if (confStatus !==
|
|
1005
|
-
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${
|
|
899
|
+
const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_1.EzspConfigId.KEY_TABLE_SIZE));
|
|
900
|
+
if (confStatus !== enums_2.SLStatus.OK) {
|
|
901
|
+
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_2.SLStatus[confStatus]}.`);
|
|
1006
902
|
}
|
|
1007
|
-
let
|
|
903
|
+
let context;
|
|
1008
904
|
let plaintextKey;
|
|
1009
905
|
let apsKeyMeta;
|
|
1010
906
|
let status;
|
|
1011
907
|
const keyList = [];
|
|
1012
908
|
for (let i = 0; i < keyTableSize; i++) {
|
|
1013
|
-
[
|
|
1014
|
-
logger_1.logger.debug(`[BACKUP] Export link key at index ${i}, status=${
|
|
909
|
+
[status, context, plaintextKey, apsKeyMeta] = (await this.ezsp.ezspExportLinkKeyByIndex(i));
|
|
910
|
+
logger_1.logger.debug(`[BACKUP] Export link key at index ${i}, status=${enums_2.SLStatus[status]}.`, NS);
|
|
1015
911
|
// only include key if we could retrieve one at index and hash it properly
|
|
1016
|
-
if (status ===
|
|
912
|
+
if (status === enums_2.SLStatus.OK) {
|
|
1017
913
|
// Rather than give the real link key, the backup contains a hashed version of the key.
|
|
1018
914
|
// This is done to prevent a compromise of the backup data from compromising the current link keys.
|
|
1019
915
|
// This is per the Smart Energy spec.
|
|
1020
916
|
const [hashStatus, hashedKey] = (await this.emberAesHashSimple(plaintextKey.contents));
|
|
1021
|
-
if (hashStatus ===
|
|
917
|
+
if (hashStatus === enums_2.SLStatus.OK) {
|
|
1022
918
|
keyList.push({
|
|
1023
|
-
deviceEui64,
|
|
919
|
+
deviceEui64: context.eui64,
|
|
1024
920
|
key: { contents: hashedKey },
|
|
1025
921
|
outgoingFrameCounter: apsKeyMeta.outgoingFrameCounter,
|
|
1026
922
|
incomingFrameCounter: apsKeyMeta.incomingFrameCounter,
|
|
@@ -1028,7 +924,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1028
924
|
}
|
|
1029
925
|
else {
|
|
1030
926
|
// this should never happen?
|
|
1031
|
-
logger_1.logger.error(`[BACKUP] Failed to hash link key at index ${i} with status=${
|
|
927
|
+
logger_1.logger.error(`[BACKUP] Failed to hash link key at index ${i} with status=${enums_2.SLStatus[hashStatus]}. Omitting from backup.`, NS);
|
|
1032
928
|
}
|
|
1033
929
|
}
|
|
1034
930
|
}
|
|
@@ -1044,30 +940,25 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1044
940
|
if (!backupData?.length) {
|
|
1045
941
|
return;
|
|
1046
942
|
}
|
|
1047
|
-
const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(
|
|
1048
|
-
if (confStatus !==
|
|
1049
|
-
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${
|
|
943
|
+
const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_1.EzspConfigId.KEY_TABLE_SIZE));
|
|
944
|
+
if (confStatus !== enums_2.SLStatus.OK) {
|
|
945
|
+
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_2.SLStatus[confStatus]}.`);
|
|
1050
946
|
}
|
|
1051
947
|
if (backupData.length > keyTableSize) {
|
|
1052
948
|
throw new Error(`[BACKUP] Current key table of ${keyTableSize} is too small to import backup of ${backupData.length}!`);
|
|
1053
949
|
}
|
|
1054
950
|
const networkStatus = (await this.emberNetworkState());
|
|
1055
|
-
if (networkStatus !==
|
|
1056
|
-
throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${
|
|
951
|
+
if (networkStatus !== enums_2.EmberNetworkStatus.NO_NETWORK) {
|
|
952
|
+
throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${enums_2.EmberNetworkStatus[networkStatus]}.`);
|
|
1057
953
|
}
|
|
1058
954
|
let status;
|
|
1059
955
|
for (let i = 0; i < keyTableSize; i++) {
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
else {
|
|
1065
|
-
const importStatus = (await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key));
|
|
1066
|
-
status = ((importStatus === enums_3.SLStatus.OK) ? enums_3.EmberStatus.SUCCESS : enums_3.EmberStatus.KEY_TABLE_INVALID_ADDRESS);
|
|
1067
|
-
}
|
|
1068
|
-
if (status !== enums_3.EmberStatus.SUCCESS) {
|
|
956
|
+
// erase any key index not present in backup but available on the NCP
|
|
957
|
+
status = (i >= backupData.length) ? await this.ezsp.ezspEraseKeyTableEntry(i) :
|
|
958
|
+
await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key);
|
|
959
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1069
960
|
throw new Error(`[BACKUP] Failed to ${((i >= backupData.length) ? "erase" : "set")} key table entry at index ${i} `
|
|
1070
|
-
+ `with status=${
|
|
961
|
+
+ `with status=${enums_2.SLStatus[status]}`);
|
|
1071
962
|
}
|
|
1072
963
|
}
|
|
1073
964
|
logger_1.logger.info(`[BACKUP] Imported ${backupData.length} keys.`, NS);
|
|
@@ -1084,17 +975,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1084
975
|
logger_1.logger.warning(`[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.`, NS);
|
|
1085
976
|
// zero-filled = let stack generate new random network key
|
|
1086
977
|
let status = await this.ezsp.ezspBroadcastNextNetworkKey({ contents: Buffer.alloc(consts_1.EMBER_ENCRYPTION_KEY_SIZE) });
|
|
1087
|
-
if (status !==
|
|
1088
|
-
logger_1.logger.error(`[TRUST CENTER] Failed to broadcast next network key with status=${
|
|
978
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
979
|
+
logger_1.logger.error(`[TRUST CENTER] Failed to broadcast next network key with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1089
980
|
return status;
|
|
1090
981
|
}
|
|
1091
982
|
// XXX: this will block other requests for a while, but should ensure the key propagates without interference?
|
|
1092
983
|
// could also stop dispatching entirely and do this outside the queue if necessary/better
|
|
1093
984
|
await (0, utils_1.Wait)(BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME);
|
|
1094
985
|
status = (await this.ezsp.ezspBroadcastNetworkKeySwitch());
|
|
1095
|
-
if (status !==
|
|
986
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1096
987
|
// XXX: Not sure how likely this is, but this is bad, probably should hard fail?
|
|
1097
|
-
logger_1.logger.error(`[TRUST CENTER] Failed to broadcast network key switch with status=${
|
|
988
|
+
logger_1.logger.error(`[TRUST CENTER] Failed to broadcast network key switch with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1098
989
|
return status;
|
|
1099
990
|
}
|
|
1100
991
|
resolve();
|
|
@@ -1107,16 +998,23 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1107
998
|
* @param status
|
|
1108
999
|
*/
|
|
1109
1000
|
async onNcpNeedsResetAndInit(status) {
|
|
1110
|
-
logger_1.logger.error(`!!!
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
await (0, utils_1.Wait)(500); // just because
|
|
1114
|
-
await this.start();
|
|
1115
|
-
}
|
|
1116
|
-
catch (err) {
|
|
1117
|
-
logger_1.logger.error(`Failed to reset and init NCP. ${err}`, NS);
|
|
1001
|
+
logger_1.logger.error(`!!! ADAPTER FATAL ERROR reason=${enums_2.EzspStatus[status]}. !!!`, NS);
|
|
1002
|
+
if (this.requestQueue.isHigh) {
|
|
1003
|
+
logger_1.logger.info(`Request queue is high (${this.requestQueue.totalQueued}), triggering full restart to prevent stressing the adapter.`, NS);
|
|
1118
1004
|
this.emit(events_1.Events.disconnected);
|
|
1119
1005
|
}
|
|
1006
|
+
else {
|
|
1007
|
+
logger_1.logger.info(`Attempting adapter reset...`, NS);
|
|
1008
|
+
try {
|
|
1009
|
+
await this.stop();
|
|
1010
|
+
await (0, utils_1.Wait)(500); // just because
|
|
1011
|
+
await this.start();
|
|
1012
|
+
}
|
|
1013
|
+
catch (err) {
|
|
1014
|
+
logger_1.logger.error(`Failed to reset and init adapter. ${err}`, NS);
|
|
1015
|
+
this.emit(events_1.Events.disconnected);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1120
1018
|
}
|
|
1121
1019
|
//---- START Events
|
|
1122
1020
|
//---- END Events
|
|
@@ -1158,11 +1056,11 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1158
1056
|
async emberGetPanId() {
|
|
1159
1057
|
if (this.networkCache.parameters.panId === ZSpec.INVALID_PAN_ID) {
|
|
1160
1058
|
const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
|
|
1161
|
-
if (status ===
|
|
1059
|
+
if (status === enums_2.SLStatus.OK) {
|
|
1162
1060
|
this.networkCache.parameters = parameters;
|
|
1163
1061
|
}
|
|
1164
1062
|
else {
|
|
1165
|
-
logger_1.logger.error(`Failed to get PAN ID (via network parameters) with status=${
|
|
1063
|
+
logger_1.logger.error(`Failed to get PAN ID (via network parameters) with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1166
1064
|
}
|
|
1167
1065
|
}
|
|
1168
1066
|
return this.networkCache.parameters.panId;
|
|
@@ -1175,11 +1073,11 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1175
1073
|
async emberGetExtendedPanId() {
|
|
1176
1074
|
if ((0, es6_1.default)(this.networkCache.parameters.extendedPanId, ZSpec.BLANK_EXTENDED_PAN_ID)) {
|
|
1177
1075
|
const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
|
|
1178
|
-
if (status ===
|
|
1076
|
+
if (status === enums_2.SLStatus.OK) {
|
|
1179
1077
|
this.networkCache.parameters = parameters;
|
|
1180
1078
|
}
|
|
1181
1079
|
else {
|
|
1182
|
-
logger_1.logger.error(`Failed to get Extended PAN ID (via network parameters) with status=${
|
|
1080
|
+
logger_1.logger.error(`Failed to get Extended PAN ID (via network parameters) with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1183
1081
|
}
|
|
1184
1082
|
}
|
|
1185
1083
|
return this.networkCache.parameters.extendedPanId;
|
|
@@ -1192,11 +1090,11 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1192
1090
|
async emberGetRadioChannel() {
|
|
1193
1091
|
if (this.networkCache.parameters.radioChannel === consts_2.INVALID_RADIO_CHANNEL) {
|
|
1194
1092
|
const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
|
|
1195
|
-
if (status ===
|
|
1093
|
+
if (status === enums_2.SLStatus.OK) {
|
|
1196
1094
|
this.networkCache.parameters = parameters;
|
|
1197
1095
|
}
|
|
1198
1096
|
else {
|
|
1199
|
-
logger_1.logger.error(`Failed to get radio channel (via network parameters) with status=${
|
|
1097
|
+
logger_1.logger.error(`Failed to get radio channel (via network parameters) with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1200
1098
|
}
|
|
1201
1099
|
}
|
|
1202
1100
|
return this.networkCache.parameters.radioChannel;
|
|
@@ -1205,14 +1103,14 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1205
1103
|
async emberStartEnergyScan() {
|
|
1206
1104
|
return new Promise((resolve, reject) => {
|
|
1207
1105
|
this.requestQueue.enqueue(async () => {
|
|
1208
|
-
const status = (await this.ezsp.ezspStartScan(
|
|
1209
|
-
if (status !==
|
|
1210
|
-
logger_1.logger.error(`Failed energy scan request with status=${
|
|
1211
|
-
return
|
|
1106
|
+
const status = (await this.ezsp.ezspStartScan(enums_2.EzspNetworkScanType.ENERGY_SCAN, consts_2.EMBER_ALL_802_15_4_CHANNELS_MASK, ENERGY_SCAN_DURATION));
|
|
1107
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1108
|
+
logger_1.logger.error(`Failed energy scan request with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1109
|
+
return enums_2.SLStatus.FAIL;
|
|
1212
1110
|
}
|
|
1213
1111
|
// TODO: result in logs only atm, since UI doesn't support it
|
|
1214
1112
|
resolve();
|
|
1215
|
-
return
|
|
1113
|
+
return enums_2.SLStatus.OK;
|
|
1216
1114
|
}, reject);
|
|
1217
1115
|
});
|
|
1218
1116
|
}
|
|
@@ -1227,35 +1125,40 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1227
1125
|
* Does nothing if ncpNeedsResetAndInit == true.
|
|
1228
1126
|
*/
|
|
1229
1127
|
async emberVersion() {
|
|
1230
|
-
// Note that NCP == Network Co-Processor
|
|
1231
|
-
// the EZSP protocol version that the Host is running, we are the host so we set this value
|
|
1232
|
-
const hostEzspProtocolVer = consts_1.EZSP_PROTOCOL_VERSION;
|
|
1233
1128
|
// send the Host version number to the NCP.
|
|
1234
1129
|
// The NCP returns the EZSP version that the NCP is running along with the stackType and stackVersion
|
|
1235
|
-
|
|
1130
|
+
let [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(consts_1.EZSP_PROTOCOL_VERSION);
|
|
1236
1131
|
// verify that the stack type is what is expected
|
|
1237
1132
|
if (ncpStackType !== consts_1.EZSP_STACK_TYPE_MESH) {
|
|
1238
1133
|
throw new Error(`Stack type ${ncpStackType} is not expected!`);
|
|
1239
1134
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
throw new Error(`NCP EZSP protocol version of ${ncpEzspProtocolVer} does not match Host version ${hostEzspProtocolVer}`);
|
|
1135
|
+
if (ncpEzspProtocolVer === consts_1.EZSP_PROTOCOL_VERSION) {
|
|
1136
|
+
logger_1.logger.debug(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) matches Host.`, NS);
|
|
1243
1137
|
}
|
|
1244
|
-
|
|
1138
|
+
else if (ncpEzspProtocolVer < consts_1.EZSP_PROTOCOL_VERSION && ncpEzspProtocolVer >= consts_1.EZSP_MIN_PROTOCOL_VERSION) {
|
|
1139
|
+
[ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(ncpEzspProtocolVer);
|
|
1140
|
+
logger_1.logger.info(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) lower than Host. Switched.`, NS);
|
|
1141
|
+
}
|
|
1142
|
+
else {
|
|
1143
|
+
throw new Error(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) is not supported `
|
|
1144
|
+
+ `by Host [${consts_1.EZSP_MIN_PROTOCOL_VERSION}-${consts_1.EZSP_PROTOCOL_VERSION}].`);
|
|
1145
|
+
}
|
|
1146
|
+
this.ezsp.setProtocolVersion(ncpEzspProtocolVer);
|
|
1147
|
+
logger_1.logger.debug(`Adapter info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS);
|
|
1245
1148
|
const [status, versionStruct] = (await this.ezsp.ezspGetVersionStruct());
|
|
1246
|
-
if (status !==
|
|
1149
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1247
1150
|
// Should never happen with support of only EZSP v13+
|
|
1248
1151
|
throw new Error(`NCP has old-style version number. Not supported.`);
|
|
1249
1152
|
}
|
|
1250
1153
|
this.version = {
|
|
1251
1154
|
ezsp: ncpEzspProtocolVer,
|
|
1252
|
-
revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${
|
|
1155
|
+
revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${enums_2.EmberVersionType[versionStruct.type]}]`,
|
|
1253
1156
|
...versionStruct,
|
|
1254
1157
|
};
|
|
1255
|
-
if (versionStruct.type !==
|
|
1256
|
-
logger_1.logger.warning(`
|
|
1158
|
+
if (versionStruct.type !== enums_2.EmberVersionType.GA) {
|
|
1159
|
+
logger_1.logger.warning(`Adapter is running a non-GA version (${enums_2.EmberVersionType[versionStruct.type]}).`, NS);
|
|
1257
1160
|
}
|
|
1258
|
-
logger_1.logger.
|
|
1161
|
+
logger_1.logger.info(`Adapter version info: ${JSON.stringify(this.version)}`, NS);
|
|
1259
1162
|
}
|
|
1260
1163
|
/**
|
|
1261
1164
|
* This function sets an EZSP config value.
|
|
@@ -1267,13 +1170,9 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1267
1170
|
*/
|
|
1268
1171
|
async emberSetEzspConfigValue(configId, value) {
|
|
1269
1172
|
const status = (await this.ezsp.ezspSetConfigurationValue(configId, value));
|
|
1270
|
-
logger_1.logger.debug(`[EzspConfigId] SET "${
|
|
1271
|
-
if (status
|
|
1272
|
-
|
|
1273
|
-
logger_1.logger.warning(`[EzspConfigId] Unsupported configuration ID ${enums_2.EzspConfigId[configId]} by NCP.`, NS);
|
|
1274
|
-
}
|
|
1275
|
-
else if (status !== enums_3.EzspStatus.SUCCESS) {
|
|
1276
|
-
logger_1.logger.warning(`[EzspConfigId] Failed to SET "${enums_2.EzspConfigId[configId]}" TO "${value}" with status=${enums_3.EzspStatus[status]}. `
|
|
1173
|
+
logger_1.logger.debug(`[EzspConfigId] SET "${enums_1.EzspConfigId[configId]}" TO "${value}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1174
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1175
|
+
logger_1.logger.info(`[EzspConfigId] Failed to SET "${enums_1.EzspConfigId[configId]}" TO "${value}" with status=${enums_2.SLStatus[status]}. `
|
|
1277
1176
|
+ `Firmware value will be used instead.`, NS);
|
|
1278
1177
|
}
|
|
1279
1178
|
return status;
|
|
@@ -1287,7 +1186,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1287
1186
|
*/
|
|
1288
1187
|
async emberSetEzspValue(valueId, valueLength, value) {
|
|
1289
1188
|
const status = (await this.ezsp.ezspSetValue(valueId, valueLength, value));
|
|
1290
|
-
logger_1.logger.debug(`[EzspValueId] SET "${
|
|
1189
|
+
logger_1.logger.debug(`[EzspValueId] SET "${enums_1.EzspValueId[valueId]}" TO "${value}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1291
1190
|
return status;
|
|
1292
1191
|
}
|
|
1293
1192
|
/**
|
|
@@ -1298,7 +1197,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1298
1197
|
*/
|
|
1299
1198
|
async emberSetEzspPolicy(policyId, decisionId) {
|
|
1300
1199
|
const status = (await this.ezsp.ezspSetPolicy(policyId, decisionId));
|
|
1301
|
-
logger_1.logger.debug(`[EzspPolicyId] SET "${
|
|
1200
|
+
logger_1.logger.debug(`[EzspPolicyId] SET "${enums_1.EzspPolicyId[policyId]}" TO "${decisionId}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1302
1201
|
return status;
|
|
1303
1202
|
}
|
|
1304
1203
|
/**
|
|
@@ -1314,7 +1213,8 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1314
1213
|
*/
|
|
1315
1214
|
async aesMmoHash(context, finalize, data) {
|
|
1316
1215
|
if (data.length > 255) {
|
|
1317
|
-
|
|
1216
|
+
// will be caught by request queue and rejected internally.
|
|
1217
|
+
throw new ezspError_1.EzspError(enums_2.EzspStatus.ERROR_INVALID_CALL);
|
|
1318
1218
|
}
|
|
1319
1219
|
const [status, reContext] = (await this.ezsp.ezspAesMmoHash(context, finalize, data));
|
|
1320
1220
|
return [status, reContext];
|
|
@@ -1327,7 +1227,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1327
1227
|
* @param context EmberAesMmoHashContext* A pointer to the location of the hash context to update.
|
|
1328
1228
|
* @param data const uint8_t* A pointer to the location of the data to hash.
|
|
1329
1229
|
*
|
|
1330
|
-
* @returns An ::
|
|
1230
|
+
* @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
|
|
1331
1231
|
* calculated successfully. EMBER_INVALID_CALL if the block size is not a
|
|
1332
1232
|
* multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
|
|
1333
1233
|
* data exceeds the maximum limits of the hash function.
|
|
@@ -1347,7 +1247,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1347
1247
|
* @param context EmberAesMmoHashContext * A pointer to the location of the hash context to finalize.
|
|
1348
1248
|
* @param data uint8_t * A pointer to the location of data to hash. May be NULL.
|
|
1349
1249
|
*
|
|
1350
|
-
* @returns An ::
|
|
1250
|
+
* @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
|
|
1351
1251
|
* calculated successfully. EMBER_INVALID_CALL if the block size is not a
|
|
1352
1252
|
* multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
|
|
1353
1253
|
* data exceeds the maximum limits of the hash function.
|
|
@@ -1362,7 +1262,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1362
1262
|
*
|
|
1363
1263
|
* @param data const uint8_t* The data to hash. Expected of valid length (as in, not larger alloc)
|
|
1364
1264
|
*
|
|
1365
|
-
* @returns An ::
|
|
1265
|
+
* @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
|
|
1366
1266
|
* calculated successfully. EMBER_INVALID_CALL if the block size is not a
|
|
1367
1267
|
* multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
|
|
1368
1268
|
* data exceeds the maximum limits of the hash function.
|
|
@@ -1393,7 +1293,9 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1393
1293
|
logger_1.logger.debug(`Permit joining for ${duration} sec. status=${[status]}`, NS);
|
|
1394
1294
|
if (broadcastMgmtPermitJoin) {
|
|
1395
1295
|
// `authentication`: TC significance always 1 (zb specs)
|
|
1396
|
-
|
|
1296
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildPermitJoining(duration, 1, []);
|
|
1297
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1298
|
+
[status, apsFrame, messageTag] = await this.sendZDORequest(ZSpec.BroadcastAddress.DEFAULT, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1397
1299
|
}
|
|
1398
1300
|
return [status, apsFrame, messageTag];
|
|
1399
1301
|
}
|
|
@@ -1403,92 +1305,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1403
1305
|
* @returns
|
|
1404
1306
|
*/
|
|
1405
1307
|
async emberSetJoinPolicy(decision) {
|
|
1406
|
-
let policy =
|
|
1407
|
-
if (decision ==
|
|
1408
|
-
policy = (
|
|
1308
|
+
let policy = enums_1.EzspDecisionBitmask.DEFAULT_CONFIGURATION;
|
|
1309
|
+
if (decision == enums_2.EmberJoinDecision.USE_PRECONFIGURED_KEY) {
|
|
1310
|
+
policy = (enums_1.EzspDecisionBitmask.ALLOW_JOINS | enums_1.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS);
|
|
1409
1311
|
}
|
|
1410
|
-
else if (decision ==
|
|
1411
|
-
policy = (
|
|
1312
|
+
else if (decision == enums_2.EmberJoinDecision.SEND_KEY_IN_THE_CLEAR) {
|
|
1313
|
+
policy = (enums_1.EzspDecisionBitmask.ALLOW_JOINS | enums_1.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS | enums_1.EzspDecisionBitmask.SEND_KEY_IN_CLEAR);
|
|
1412
1314
|
}
|
|
1413
|
-
else if (decision ==
|
|
1414
|
-
policy =
|
|
1415
|
-
}
|
|
1416
|
-
return this.emberSetEzspPolicy(enums_2.EzspPolicyId.TRUST_CENTER_POLICY, policy);
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* Get Source Route Overhead
|
|
1420
|
-
*
|
|
1421
|
-
* Returns the number of bytes needed in a packet for source routing.
|
|
1422
|
-
* Since each hop consumes 2 bytes in the packet, this routine calculates the
|
|
1423
|
-
* total number of bytes needed based on number of hops to reach the destination.
|
|
1424
|
-
*
|
|
1425
|
-
* This function is called by the framework to determine the overhead required
|
|
1426
|
-
* in the network frame for source routing to a particular destination.
|
|
1427
|
-
*
|
|
1428
|
-
* @param destination The node id of the destination Ver.: always
|
|
1429
|
-
* @returns int8u The number of bytes needed for source routing in a packet.
|
|
1430
|
-
*/
|
|
1431
|
-
async emberGetSourceRouteOverhead(destination) {
|
|
1432
|
-
const [status, value] = (await this.ezsp.ezspGetSourceRouteOverhead(destination));
|
|
1433
|
-
if (status === enums_3.EzspStatus.SUCCESS) {
|
|
1434
|
-
return value;
|
|
1435
|
-
}
|
|
1436
|
-
else {
|
|
1437
|
-
logger_1.logger.debug(`Failed to get source route overhead (via extended value), status=${enums_3.EzspStatus[status]}.`, NS);
|
|
1315
|
+
else if (decision == enums_2.EmberJoinDecision.ALLOW_REJOINS_ONLY) {
|
|
1316
|
+
policy = enums_1.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
|
|
1438
1317
|
}
|
|
1439
|
-
return
|
|
1440
|
-
}
|
|
1441
|
-
/**
|
|
1442
|
-
* Return the maximum size of the payload that the Application Support sub-layer will accept for
|
|
1443
|
-
* the given message type, destination, and APS frame.
|
|
1444
|
-
*
|
|
1445
|
-
* The size depends on multiple factors, including the security level in use and additional information
|
|
1446
|
-
* added to the message to support the various options.
|
|
1447
|
-
*
|
|
1448
|
-
* @param type The outgoing message type.
|
|
1449
|
-
* @param indexOrDestination uint16_t Depending on the message type, this is either the
|
|
1450
|
-
* EmberNodeId of the destination, an index into the address table, an index
|
|
1451
|
-
* into the binding table, the multicast identifier, or a broadcast address.
|
|
1452
|
-
* @param apsFrame EmberApsFrame *The APS frame for the message.
|
|
1453
|
-
* @return uint8_t The maximum APS payload length for the given message.
|
|
1454
|
-
*/
|
|
1455
|
-
async maximumApsPayloadLength(type, indexOrDestination, apsFrame) {
|
|
1456
|
-
let destination = consts_2.EMBER_UNKNOWN_NODE_ID;
|
|
1457
|
-
let max = consts_2.MAXIMUM_APS_PAYLOAD_LENGTH; // uint8_t
|
|
1458
|
-
if ((apsFrame.options & enums_3.EmberApsOption.ENCRYPTION) !== 0) {
|
|
1459
|
-
max -= consts_2.APS_ENCRYPTION_OVERHEAD;
|
|
1460
|
-
}
|
|
1461
|
-
if ((apsFrame.options & enums_3.EmberApsOption.SOURCE_EUI64) !== 0) {
|
|
1462
|
-
max -= consts_1.EUI64_SIZE;
|
|
1463
|
-
}
|
|
1464
|
-
if ((apsFrame.options & enums_3.EmberApsOption.DESTINATION_EUI64) !== 0) {
|
|
1465
|
-
max -= consts_1.EUI64_SIZE;
|
|
1466
|
-
}
|
|
1467
|
-
if ((apsFrame.options & enums_3.EmberApsOption.FRAGMENT) !== 0) {
|
|
1468
|
-
max -= consts_2.APS_FRAGMENTATION_OVERHEAD;
|
|
1469
|
-
}
|
|
1470
|
-
switch (type) {
|
|
1471
|
-
case enums_3.EmberOutgoingMessageType.DIRECT:
|
|
1472
|
-
destination = indexOrDestination;
|
|
1473
|
-
break;
|
|
1474
|
-
case enums_3.EmberOutgoingMessageType.VIA_ADDRESS_TABLE:
|
|
1475
|
-
destination = (await this.ezsp.ezspGetAddressTableRemoteNodeId(indexOrDestination));
|
|
1476
|
-
break;
|
|
1477
|
-
case enums_3.EmberOutgoingMessageType.VIA_BINDING:
|
|
1478
|
-
destination = (await this.ezsp.ezspGetBindingRemoteNodeId(indexOrDestination));
|
|
1479
|
-
break;
|
|
1480
|
-
case enums_3.EmberOutgoingMessageType.MULTICAST:
|
|
1481
|
-
// APS multicast messages include the two-byte group id and exclude the one-byte destination endpoint,
|
|
1482
|
-
// for a net loss of an extra byte.
|
|
1483
|
-
max--;
|
|
1484
|
-
break;
|
|
1485
|
-
case enums_3.EmberOutgoingMessageType.BROADCAST:
|
|
1486
|
-
break;
|
|
1487
|
-
default:
|
|
1488
|
-
break;
|
|
1489
|
-
}
|
|
1490
|
-
max -= (await this.emberGetSourceRouteOverhead(destination));
|
|
1491
|
-
return max;
|
|
1318
|
+
return this.emberSetEzspPolicy(enums_1.EzspPolicyId.TRUST_CENTER_POLICY, policy);
|
|
1492
1319
|
}
|
|
1493
1320
|
//---- END EZSP wrappers
|
|
1494
1321
|
//---- START Ember ZDO
|
|
@@ -1528,518 +1355,47 @@ class EmberAdapter extends __1.Adapter {
|
|
|
1528
1355
|
*
|
|
1529
1356
|
* @param destination
|
|
1530
1357
|
* @param clusterId uint16_t
|
|
1358
|
+
* @param messageContents Content of the ZDO request (sequence to be assigned at index zero)
|
|
1531
1359
|
* @param options
|
|
1532
|
-
* @param length uint8_t
|
|
1533
1360
|
* @returns status Indicates success or failure (with reason) of send
|
|
1534
1361
|
* @returns apsFrame The APS Frame resulting of the request being built and sent (`sequence` set from stack-given value).
|
|
1535
1362
|
* @returns messageTag The tag passed to ezspSend${x} function.
|
|
1536
1363
|
*/
|
|
1537
|
-
async
|
|
1538
|
-
if (
|
|
1539
|
-
return [
|
|
1364
|
+
async sendZDORequest(destination, clusterId, messageContents, options) {
|
|
1365
|
+
if (messageContents.length > consts_1.EZSP_MAX_FRAME_LENGTH) {
|
|
1366
|
+
return [enums_2.SLStatus.MESSAGE_TOO_LONG, null, null];
|
|
1540
1367
|
}
|
|
1541
1368
|
const messageTag = this.nextZDORequestSequence();
|
|
1542
|
-
|
|
1369
|
+
messageContents[0] = messageTag;
|
|
1543
1370
|
const apsFrame = {
|
|
1544
|
-
profileId:
|
|
1545
|
-
clusterId
|
|
1546
|
-
sourceEndpoint:
|
|
1547
|
-
destinationEndpoint:
|
|
1548
|
-
options
|
|
1371
|
+
profileId: Zdo.ZDO_PROFILE_ID,
|
|
1372
|
+
clusterId,
|
|
1373
|
+
sourceEndpoint: Zdo.ZDO_ENDPOINT,
|
|
1374
|
+
destinationEndpoint: Zdo.ZDO_ENDPOINT,
|
|
1375
|
+
options,
|
|
1549
1376
|
groupId: 0,
|
|
1550
1377
|
sequence: 0, // set by stack
|
|
1551
1378
|
};
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
const [status, apsSequence] =
|
|
1379
|
+
if (destination === ZSpec.BroadcastAddress.DEFAULT || destination === ZSpec.BroadcastAddress.RX_ON_WHEN_IDLE
|
|
1380
|
+
|| destination === ZSpec.BroadcastAddress.SLEEPY) {
|
|
1381
|
+
logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} BROADCAST to=${destination} messageTag=${messageTag} `
|
|
1382
|
+
+ `messageContents=${messageContents.toString('hex')}]`, NS);
|
|
1383
|
+
const [status, apsSequence] = await this.ezsp.ezspSendBroadcast(ZSpec.NULL_NODE_ID, // alias
|
|
1384
|
+
destination, 0, // nwkSequence
|
|
1385
|
+
apsFrame, this.getZDORequestRadius(), messageTag, messageContents);
|
|
1557
1386
|
apsFrame.sequence = apsSequence;
|
|
1558
|
-
logger_1.logger.debug(`~~~> [SENT ZDO type=BROADCAST
|
|
1387
|
+
logger_1.logger.debug(`~~~> [SENT ZDO type=BROADCAST apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_2.SLStatus[status]}`, NS);
|
|
1559
1388
|
return [status, apsFrame, messageTag];
|
|
1560
1389
|
}
|
|
1561
1390
|
else {
|
|
1562
|
-
logger_1.logger.debug(`~~~> [ZDO UNICAST
|
|
1563
|
-
|
|
1391
|
+
logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} UNICAST to=${destination} messageTag=${messageTag} `
|
|
1392
|
+
+ `messageContents=${messageContents.toString('hex')}]`, NS);
|
|
1393
|
+
const [status, apsSequence] = await this.ezsp.ezspSendUnicast(enums_2.EmberOutgoingMessageType.DIRECT, destination, apsFrame, messageTag, messageContents);
|
|
1564
1394
|
apsFrame.sequence = apsSequence;
|
|
1565
|
-
logger_1.logger.debug(`~~~> [SENT ZDO type=DIRECT
|
|
1395
|
+
logger_1.logger.debug(`~~~> [SENT ZDO type=DIRECT apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_2.SLStatus[status]}`, NS);
|
|
1566
1396
|
return [status, apsFrame, messageTag];
|
|
1567
1397
|
}
|
|
1568
1398
|
}
|
|
1569
|
-
/**
|
|
1570
|
-
* ZDO
|
|
1571
|
-
* Service Discovery Functions
|
|
1572
|
-
* Request the specified node to send a list of its endpoints that
|
|
1573
|
-
* match the specified application profile and, optionally, lists of input
|
|
1574
|
-
* and/or output clusters.
|
|
1575
|
-
* @param target The node whose matching endpoints are desired. The request can
|
|
1576
|
-
* be sent unicast or broadcast ONLY to the "RX-on-when-idle-address" (0xFFFD)
|
|
1577
|
-
* If sent as a broadcast, any node that has matching endpoints will send a
|
|
1578
|
-
* response.
|
|
1579
|
-
* @param profile uint16_t The application profile to match.
|
|
1580
|
-
* @param inCount uint8_t The number of input clusters. To not match any input
|
|
1581
|
-
* clusters, set this value to 0.
|
|
1582
|
-
* @param outCount uint8_t The number of output clusters. To not match any output
|
|
1583
|
-
* clusters, set this value to 0.
|
|
1584
|
-
* @param inClusters uint16_t * The list of input clusters.
|
|
1585
|
-
* @param outClusters uint16_t * The list of output clusters.
|
|
1586
|
-
* @param options The options to use when sending the unicast request. See
|
|
1587
|
-
* emberSendUnicast() for a description. This parameter is ignored if the target
|
|
1588
|
-
* is a broadcast address.
|
|
1589
|
-
* @returns An EmberStatus value. EMBER_SUCCESS, MESSAGE_TOO_LONG,
|
|
1590
|
-
* EMBER_NETWORK_DOWN or EMBER_NETWORK_BUSY.
|
|
1591
|
-
*/
|
|
1592
|
-
async emberMatchDescriptorsRequest(target, profile, inClusters, outClusters, options) {
|
|
1593
|
-
// 2 bytes for NWK Address + 2 bytes for Profile Id + 1 byte for in Cluster Count
|
|
1594
|
-
// + in times 2 for 2 byte Clusters + out Cluster Count + out times 2 for 2 byte Clusters
|
|
1595
|
-
const length = (zdo_1.ZDO_MESSAGE_OVERHEAD + 2 + 2 + 1 + (inClusters.length * 2) + 1 + (outClusters.length * 2));
|
|
1596
|
-
// sanity check
|
|
1597
|
-
if (length > consts_1.EZSP_MAX_FRAME_LENGTH) {
|
|
1598
|
-
return [enums_3.EmberStatus.MESSAGE_TOO_LONG, null, null];
|
|
1599
|
-
}
|
|
1600
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1601
|
-
this.zdoRequestBuffalo.writeUInt16(target);
|
|
1602
|
-
this.zdoRequestBuffalo.writeUInt16(profile);
|
|
1603
|
-
this.zdoRequestBuffalo.writeUInt8(inClusters.length);
|
|
1604
|
-
this.zdoRequestBuffalo.writeListUInt16(inClusters);
|
|
1605
|
-
this.zdoRequestBuffalo.writeUInt8(outClusters.length);
|
|
1606
|
-
this.zdoRequestBuffalo.writeListUInt16(outClusters);
|
|
1607
|
-
logger_1.logger.debug(`~~~> [ZDO MATCH_DESCRIPTORS_REQUEST target=${target} profile=${profile} inClusters=${inClusters} outClusters=${outClusters}]`, NS);
|
|
1608
|
-
return this.sendZDORequestBuffer(target, zdo_1.MATCH_DESCRIPTORS_REQUEST, options);
|
|
1609
|
-
}
|
|
1610
|
-
/**
|
|
1611
|
-
* ZDO
|
|
1612
|
-
* Device Discovery Functions
|
|
1613
|
-
* Request the 16 bit network address of a node whose EUI64 is known.
|
|
1614
|
-
*
|
|
1615
|
-
* @param target The EUI64 of the node.
|
|
1616
|
-
* @param reportKids true to request that the target list their children
|
|
1617
|
-
* in the response.
|
|
1618
|
-
* @param childStartIndex uint8_t The index of the first child to list in the response.
|
|
1619
|
-
* Ignored if @c reportKids is false.
|
|
1620
|
-
*
|
|
1621
|
-
* @return An ::EmberStatus value.
|
|
1622
|
-
* - ::EMBER_SUCCESS - The request was transmitted successfully.
|
|
1623
|
-
* - ::EMBER_NO_BUFFERS - Insufficient message buffers were available to construct the request.
|
|
1624
|
-
* - ::EMBER_NETWORK_DOWN - The node is not part of a network.
|
|
1625
|
-
* - ::EMBER_NETWORK_BUSY - Transmission of the request failed.
|
|
1626
|
-
*/
|
|
1627
|
-
async emberNetworkAddressRequest(target, reportKids, childStartIndex) {
|
|
1628
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1629
|
-
this.zdoRequestBuffalo.writeIeeeAddr(target);
|
|
1630
|
-
this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
|
|
1631
|
-
this.zdoRequestBuffalo.writeUInt8(childStartIndex);
|
|
1632
|
-
logger_1.logger.debug(`~~~> [ZDO NETWORK_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
|
|
1633
|
-
return this.sendZDORequestBuffer(enums_1.BroadcastAddress.RX_ON_WHEN_IDLE, zdo_1.NETWORK_ADDRESS_REQUEST, enums_3.EmberApsOption.SOURCE_EUI64);
|
|
1634
|
-
}
|
|
1635
|
-
/**
|
|
1636
|
-
* ZDO
|
|
1637
|
-
* Device Discovery Functions
|
|
1638
|
-
* @brief Request the EUI64 of a node whose 16 bit network address is known.
|
|
1639
|
-
*
|
|
1640
|
-
* @param target uint16_t The network address of the node.
|
|
1641
|
-
* @param reportKids uint8_t true to request that the target list their children
|
|
1642
|
-
* in the response.
|
|
1643
|
-
* @param childStartIndex uint8_t The index of the first child to list in the response.
|
|
1644
|
-
* Ignored if reportKids is false.
|
|
1645
|
-
* @param options The options to use when sending the request. See ::emberSendUnicast() for a description.
|
|
1646
|
-
*
|
|
1647
|
-
* @return An ::EmberStatus value.
|
|
1648
|
-
* - ::EMBER_SUCCESS
|
|
1649
|
-
* - ::EMBER_NO_BUFFERS
|
|
1650
|
-
* - ::EMBER_NETWORK_DOWN
|
|
1651
|
-
* - ::EMBER_NETWORK_BUSY
|
|
1652
|
-
*/
|
|
1653
|
-
async emberIeeeAddressRequest(target, reportKids, childStartIndex, options) {
|
|
1654
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1655
|
-
this.zdoRequestBuffalo.writeUInt16(target);
|
|
1656
|
-
this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
|
|
1657
|
-
this.zdoRequestBuffalo.writeUInt8(childStartIndex);
|
|
1658
|
-
logger_1.logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
|
|
1659
|
-
return this.sendZDORequestBuffer(target, zdo_1.IEEE_ADDRESS_REQUEST, options);
|
|
1660
|
-
}
|
|
1661
|
-
/**
|
|
1662
|
-
* ZDO
|
|
1663
|
-
* @param discoveryNodeId uint16_t
|
|
1664
|
-
* @param reportKids uint8_t
|
|
1665
|
-
* @param childStartIndex uint8_t
|
|
1666
|
-
* @param options
|
|
1667
|
-
* @param targetNodeIdOfRequest
|
|
1668
|
-
*/
|
|
1669
|
-
async emberIeeeAddressRequestToTarget(discoveryNodeId, reportKids, childStartIndex, options, targetNodeIdOfRequest) {
|
|
1670
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1671
|
-
this.zdoRequestBuffalo.writeUInt16(discoveryNodeId);
|
|
1672
|
-
this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
|
|
1673
|
-
this.zdoRequestBuffalo.writeUInt8(childStartIndex);
|
|
1674
|
-
logger_1.logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST targetNodeIdOfRequest=${targetNodeIdOfRequest} discoveryNodeId=${discoveryNodeId} `
|
|
1675
|
-
+ `reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
|
|
1676
|
-
return this.sendZDORequestBuffer(targetNodeIdOfRequest, zdo_1.IEEE_ADDRESS_REQUEST, options);
|
|
1677
|
-
}
|
|
1678
|
-
/**
|
|
1679
|
-
* ZDO
|
|
1680
|
-
*
|
|
1681
|
-
* @param target uint16_t
|
|
1682
|
-
* @param clusterId uint16_t
|
|
1683
|
-
* @param options
|
|
1684
|
-
* @returns
|
|
1685
|
-
*/
|
|
1686
|
-
async emberSendZigDevRequestTarget(target, clusterId, options) {
|
|
1687
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1688
|
-
this.zdoRequestBuffalo.writeUInt16(target);
|
|
1689
|
-
return this.sendZDORequestBuffer(target, clusterId, options);
|
|
1690
|
-
}
|
|
1691
|
-
/**
|
|
1692
|
-
* ZDO
|
|
1693
|
-
* @brief Request the specified node to send the simple descriptor for
|
|
1694
|
-
* the specified endpoint.
|
|
1695
|
-
* The simple descriptor contains information specific
|
|
1696
|
-
* to a single endpoint. It describes the application profile identifier,
|
|
1697
|
-
* application device identifier, application device version, application flags,
|
|
1698
|
-
* application input clusters and application output clusters. It is defined in
|
|
1699
|
-
* the ZigBee Application Framework Specification.
|
|
1700
|
-
*
|
|
1701
|
-
* @param target uint16_t The node of interest.
|
|
1702
|
-
* @param targetEndpoint uint8_t The endpoint on the target node whose simple
|
|
1703
|
-
* descriptor is desired.
|
|
1704
|
-
* @param options The options to use when sending the request. See
|
|
1705
|
-
* emberSendUnicast() for a description.
|
|
1706
|
-
*
|
|
1707
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1708
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1709
|
-
*/
|
|
1710
|
-
async emberSimpleDescriptorRequest(target, targetEndpoint, options) {
|
|
1711
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1712
|
-
this.zdoRequestBuffalo.writeUInt16(target);
|
|
1713
|
-
this.zdoRequestBuffalo.writeUInt8(targetEndpoint);
|
|
1714
|
-
logger_1.logger.debug(`~~~> [ZDO SIMPLE_DESCRIPTOR_REQUEST target=${target} targetEndpoint=${targetEndpoint}]`, NS);
|
|
1715
|
-
return this.sendZDORequestBuffer(target, zdo_1.SIMPLE_DESCRIPTOR_REQUEST, options);
|
|
1716
|
-
}
|
|
1717
|
-
/**
|
|
1718
|
-
* ZDO
|
|
1719
|
-
* Common logic used by `emberBindRequest` & `emberUnbindRequest`.
|
|
1720
|
-
*
|
|
1721
|
-
* @param target
|
|
1722
|
-
* @param bindClusterId
|
|
1723
|
-
* @param source
|
|
1724
|
-
* @param sourceEndpoint
|
|
1725
|
-
* @param clusterId
|
|
1726
|
-
* @param type
|
|
1727
|
-
* @param destination
|
|
1728
|
-
* @param groupAddress
|
|
1729
|
-
* @param destinationEndpoint
|
|
1730
|
-
* @param options
|
|
1731
|
-
*
|
|
1732
|
-
* @returns An ::EmberStatus value.
|
|
1733
|
-
* - ::EMBER_SUCCESS
|
|
1734
|
-
* - ::EMBER_NO_BUFFERS
|
|
1735
|
-
* - ::EMBER_NETWORK_DOWN
|
|
1736
|
-
* - ::EMBER_NETWORK_BUSY
|
|
1737
|
-
* @returns APS frame created for the request
|
|
1738
|
-
* @returns The tag used on the message.
|
|
1739
|
-
*/
|
|
1740
|
-
async emberSendZigDevBindRequest(target, bindClusterId, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
|
|
1741
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1742
|
-
this.zdoRequestBuffalo.writeIeeeAddr(source);
|
|
1743
|
-
this.zdoRequestBuffalo.writeUInt8(sourceEndpoint);
|
|
1744
|
-
this.zdoRequestBuffalo.writeUInt16(clusterId);
|
|
1745
|
-
this.zdoRequestBuffalo.writeUInt8(type);
|
|
1746
|
-
switch (type) {
|
|
1747
|
-
case zdo_1.UNICAST_BINDING:
|
|
1748
|
-
this.zdoRequestBuffalo.writeIeeeAddr(destination);
|
|
1749
|
-
this.zdoRequestBuffalo.writeUInt8(destinationEndpoint);
|
|
1750
|
-
break;
|
|
1751
|
-
case zdo_1.MULTICAST_BINDING:
|
|
1752
|
-
this.zdoRequestBuffalo.writeUInt16(groupAddress);
|
|
1753
|
-
break;
|
|
1754
|
-
default:
|
|
1755
|
-
return [enums_3.EmberStatus.ERR_FATAL, null, null];
|
|
1756
|
-
}
|
|
1757
|
-
return this.sendZDORequestBuffer(target, bindClusterId, options);
|
|
1758
|
-
}
|
|
1759
|
-
/**
|
|
1760
|
-
* ZDO
|
|
1761
|
-
* Send a request to create a binding entry with the specified
|
|
1762
|
-
* contents on the specified node.
|
|
1763
|
-
*
|
|
1764
|
-
* @param target The node on which the binding will be created.
|
|
1765
|
-
* @param source The source EUI64 in the binding entry.
|
|
1766
|
-
* @param sourceEndpoint The source endpoint in the binding entry.
|
|
1767
|
-
* @param clusterId The cluster ID in the binding entry.
|
|
1768
|
-
* @param type The type of binding, either ::UNICAST_BINDING,
|
|
1769
|
-
* ::MULTICAST_BINDING, or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1770
|
-
* ::UNICAST_MANY_TO_ONE_BINDING is an Ember-specific extension
|
|
1771
|
-
* and should be used only when the target is an Ember device.
|
|
1772
|
-
* @param destination The destination EUI64 in the binding entry for
|
|
1773
|
-
* ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1774
|
-
* @param groupAddress The group address for the ::MULTICAST_BINDING.
|
|
1775
|
-
* @param destinationEndpoint The destination endpoint in the binding entry for
|
|
1776
|
-
* the ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1777
|
-
* @param options The options to use when sending the request. See
|
|
1778
|
-
* emberSendUnicast() for a description.
|
|
1779
|
-
*
|
|
1780
|
-
* @returns An ::EmberStatus value.
|
|
1781
|
-
* - ::EMBER_SUCCESS
|
|
1782
|
-
* - ::EMBER_NO_BUFFERS
|
|
1783
|
-
* - ::EMBER_NETWORK_DOWN
|
|
1784
|
-
* - ::EMBER_NETWORK_BUSY
|
|
1785
|
-
* @returns APS frame created for the request
|
|
1786
|
-
* @returns The tag used on the message.
|
|
1787
|
-
*/
|
|
1788
|
-
async emberBindRequest(target, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
|
|
1789
|
-
logger_1.logger.debug(`~~~> [ZDO BIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} `
|
|
1790
|
-
+ `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, NS);
|
|
1791
|
-
return this.emberSendZigDevBindRequest(target, zdo_1.BIND_REQUEST, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options);
|
|
1792
|
-
}
|
|
1793
|
-
/**
|
|
1794
|
-
* ZDO
|
|
1795
|
-
* Send a request to remove a binding entry with the specified
|
|
1796
|
-
* contents from the specified node.
|
|
1797
|
-
*
|
|
1798
|
-
* @param target The node on which the binding will be removed.
|
|
1799
|
-
* @param source The source EUI64 in the binding entry.
|
|
1800
|
-
* @param sourceEndpoint uint8_t The source endpoint in the binding entry.
|
|
1801
|
-
* @param clusterId uint16_t The cluster ID in the binding entry.
|
|
1802
|
-
* @param type uint8_t The type of binding, either ::UNICAST_BINDING,
|
|
1803
|
-
* ::MULTICAST_BINDING, or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1804
|
-
* ::UNICAST_MANY_TO_ONE_BINDING is an Ember-specific extension
|
|
1805
|
-
* and should be used only when the target is an Ember device.
|
|
1806
|
-
* @param destination The destination EUI64 in the binding entry for the
|
|
1807
|
-
* ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1808
|
-
* @param groupAddress The group address for the ::MULTICAST_BINDING.
|
|
1809
|
-
* @param destinationEndpoint uint8_t The destination endpoint in the binding entry for
|
|
1810
|
-
* the ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
|
|
1811
|
-
* @param options The options to use when sending the request. See
|
|
1812
|
-
* emberSendUnicast() for a description.
|
|
1813
|
-
*
|
|
1814
|
-
* @returns An ::EmberStatus value.
|
|
1815
|
-
* - ::EMBER_SUCCESS
|
|
1816
|
-
* - ::EMBER_NO_BUFFERS
|
|
1817
|
-
* - ::EMBER_NETWORK_DOWN
|
|
1818
|
-
* - ::EMBER_NETWORK_BUSY
|
|
1819
|
-
* @returns APS frame created for the request
|
|
1820
|
-
* @returns The tag used on the message.
|
|
1821
|
-
*/
|
|
1822
|
-
async emberUnbindRequest(target, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
|
|
1823
|
-
logger_1.logger.debug(`~~~> [ZDO UNBIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} `
|
|
1824
|
-
+ `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, NS);
|
|
1825
|
-
return this.emberSendZigDevBindRequest(target, zdo_1.UNBIND_REQUEST, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options);
|
|
1826
|
-
}
|
|
1827
|
-
/**
|
|
1828
|
-
* ZDO
|
|
1829
|
-
* Request the specified node to send a list of its active
|
|
1830
|
-
* endpoints. An active endpoint is one for which a simple descriptor is
|
|
1831
|
-
* available.
|
|
1832
|
-
*
|
|
1833
|
-
* @param target The node whose active endpoints are desired.
|
|
1834
|
-
* @param options The options to use when sending the request. See
|
|
1835
|
-
* emberSendUnicast() for a description.
|
|
1836
|
-
*
|
|
1837
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1838
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1839
|
-
*/
|
|
1840
|
-
async emberActiveEndpointsRequest(target, options) {
|
|
1841
|
-
logger_1.logger.debug(`~~~> [ZDO ACTIVE_ENDPOINTS_REQUEST target=${target}]`, NS);
|
|
1842
|
-
return this.emberSendZigDevRequestTarget(target, zdo_1.ACTIVE_ENDPOINTS_REQUEST, options);
|
|
1843
|
-
}
|
|
1844
|
-
/**
|
|
1845
|
-
* ZDO
|
|
1846
|
-
* Request the specified node to send its power descriptor.
|
|
1847
|
-
* The power descriptor gives a dynamic indication of the power
|
|
1848
|
-
* status of the node. It describes current power mode,
|
|
1849
|
-
* available power sources, current power source and
|
|
1850
|
-
* current power source level. It is defined in the ZigBee
|
|
1851
|
-
* Application Framework Specification.
|
|
1852
|
-
*
|
|
1853
|
-
* @param target The node whose power descriptor is desired.
|
|
1854
|
-
* @param options The options to use when sending the request. See
|
|
1855
|
-
* emberSendUnicast() for a description.
|
|
1856
|
-
*
|
|
1857
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1858
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1859
|
-
*/
|
|
1860
|
-
async emberPowerDescriptorRequest(target, options) {
|
|
1861
|
-
logger_1.logger.debug(`~~~> [ZDO POWER_DESCRIPTOR_REQUEST target=${target}]`, NS);
|
|
1862
|
-
return this.emberSendZigDevRequestTarget(target, zdo_1.POWER_DESCRIPTOR_REQUEST, options);
|
|
1863
|
-
}
|
|
1864
|
-
/**
|
|
1865
|
-
* ZDO
|
|
1866
|
-
* Request the specified node to send its node descriptor.
|
|
1867
|
-
* The node descriptor contains information about the capabilities of the ZigBee
|
|
1868
|
-
* node. It describes logical type, APS flags, frequency band, MAC capabilities
|
|
1869
|
-
* flags, manufacturer code and maximum buffer size. It is defined in the ZigBee
|
|
1870
|
-
* Application Framework Specification.
|
|
1871
|
-
*
|
|
1872
|
-
* @param target The node whose node descriptor is desired.
|
|
1873
|
-
* @param options The options to use when sending the request. See
|
|
1874
|
-
* emberSendUnicast() for a description.
|
|
1875
|
-
*
|
|
1876
|
-
* @return An ::EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1877
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1878
|
-
*/
|
|
1879
|
-
async emberNodeDescriptorRequest(target, options) {
|
|
1880
|
-
logger_1.logger.debug(`~~~> [ZDO NODE_DESCRIPTOR_REQUEST target=${target}]`, NS);
|
|
1881
|
-
return this.emberSendZigDevRequestTarget(target, zdo_1.NODE_DESCRIPTOR_REQUEST, options);
|
|
1882
|
-
}
|
|
1883
|
-
/**
|
|
1884
|
-
* ZDO
|
|
1885
|
-
* Request the specified node to send its LQI (neighbor) table.
|
|
1886
|
-
* The response gives PAN ID, EUI64, node ID and cost for each neighbor. The
|
|
1887
|
-
* EUI64 is only available if security is enabled. The other fields in the
|
|
1888
|
-
* response are set to zero. The response format is defined in the ZigBee Device
|
|
1889
|
-
* Profile Specification.
|
|
1890
|
-
*
|
|
1891
|
-
* @param target The node whose LQI table is desired.
|
|
1892
|
-
* @param startIndex uint8_t The index of the first neighbor to include in the
|
|
1893
|
-
* response.
|
|
1894
|
-
* @param options The options to use when sending the request. See
|
|
1895
|
-
* emberSendUnicast() for a description.
|
|
1896
|
-
*
|
|
1897
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1898
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1899
|
-
*/
|
|
1900
|
-
async emberLqiTableRequest(target, startIndex, options) {
|
|
1901
|
-
logger_1.logger.debug(`~~~> [ZDO LQI_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
|
|
1902
|
-
return this.emberTableRequest(zdo_1.LQI_TABLE_REQUEST, target, startIndex, options);
|
|
1903
|
-
}
|
|
1904
|
-
/**
|
|
1905
|
-
* ZDO
|
|
1906
|
-
* Request the specified node to send its routing table.
|
|
1907
|
-
* The response gives destination node ID, status and many-to-one flags,
|
|
1908
|
-
* and the next hop node ID.
|
|
1909
|
-
* The response format is defined in the ZigBee Device
|
|
1910
|
-
* Profile Specification.
|
|
1911
|
-
*
|
|
1912
|
-
* @param target The node whose routing table is desired.
|
|
1913
|
-
* @param startIndex uint8_t The index of the first route entry to include in the
|
|
1914
|
-
* response.
|
|
1915
|
-
* @param options The options to use when sending the request. See
|
|
1916
|
-
* emberSendUnicast() for a description.
|
|
1917
|
-
*
|
|
1918
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1919
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1920
|
-
*/
|
|
1921
|
-
async emberRoutingTableRequest(target, startIndex, options) {
|
|
1922
|
-
logger_1.logger.debug(`~~~> [ZDO ROUTING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
|
|
1923
|
-
return this.emberTableRequest(zdo_1.ROUTING_TABLE_REQUEST, target, startIndex, options);
|
|
1924
|
-
}
|
|
1925
|
-
/**
|
|
1926
|
-
* ZDO
|
|
1927
|
-
* Request the specified node to send its nonvolatile bindings.
|
|
1928
|
-
* The response gives source address, source endpoint, cluster ID, destination
|
|
1929
|
-
* address and destination endpoint for each binding entry. The response format
|
|
1930
|
-
* is defined in the ZigBee Device Profile Specification.
|
|
1931
|
-
* Note that bindings that have the Ember-specific ::UNICAST_MANY_TO_ONE_BINDING
|
|
1932
|
-
* type are reported as having the standard ::UNICAST_BINDING type.
|
|
1933
|
-
*
|
|
1934
|
-
* @param target The node whose binding table is desired.
|
|
1935
|
-
* @param startIndex uint8_t The index of the first binding entry to include in the
|
|
1936
|
-
* response.
|
|
1937
|
-
* @param options The options to use when sending the request. See
|
|
1938
|
-
* emberSendUnicast() for a description.
|
|
1939
|
-
*
|
|
1940
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1941
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1942
|
-
*/
|
|
1943
|
-
async emberBindingTableRequest(target, startIndex, options) {
|
|
1944
|
-
logger_1.logger.debug(`~~~> [ZDO BINDING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
|
|
1945
|
-
return this.emberTableRequest(zdo_1.BINDING_TABLE_REQUEST, target, startIndex, options);
|
|
1946
|
-
}
|
|
1947
|
-
/**
|
|
1948
|
-
* ZDO
|
|
1949
|
-
*
|
|
1950
|
-
* @param clusterId uint16_t
|
|
1951
|
-
* @param target
|
|
1952
|
-
* @param startIndex uint8_t
|
|
1953
|
-
* @param options
|
|
1954
|
-
* @returns
|
|
1955
|
-
*/
|
|
1956
|
-
async emberTableRequest(clusterId, target, startIndex, options) {
|
|
1957
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1958
|
-
this.zdoRequestBuffalo.writeUInt8(startIndex);
|
|
1959
|
-
return this.sendZDORequestBuffer(target, clusterId, options);
|
|
1960
|
-
}
|
|
1961
|
-
/**
|
|
1962
|
-
* ZDO
|
|
1963
|
-
* Request the specified node to remove the specified device from
|
|
1964
|
-
* the network. The device to be removed must be the node to which the request
|
|
1965
|
-
* is sent or one of its children.
|
|
1966
|
-
*
|
|
1967
|
-
* @param target The node which will remove the device.
|
|
1968
|
-
* @param deviceAddress All zeros if the target is to remove itself from
|
|
1969
|
-
* the network or the EUI64 of a child of the target device to remove
|
|
1970
|
-
* that child.
|
|
1971
|
-
* @param leaveRequestFlags uint8_t A bitmask of leave options.
|
|
1972
|
-
* Include ::AND_REJOIN if the target is to rejoin the network immediately after leaving.
|
|
1973
|
-
* @param options The options to use when sending the request. See
|
|
1974
|
-
* emberSendUnicast() for a description.
|
|
1975
|
-
*
|
|
1976
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
1977
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
1978
|
-
*/
|
|
1979
|
-
async emberLeaveRequest(target, deviceAddress, leaveRequestFlags, options) {
|
|
1980
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
1981
|
-
this.zdoRequestBuffalo.writeIeeeAddr(deviceAddress);
|
|
1982
|
-
this.zdoRequestBuffalo.writeUInt8(leaveRequestFlags);
|
|
1983
|
-
logger_1.logger.debug(`~~~> [ZDO LEAVE_REQUEST target=${target} deviceAddress=${deviceAddress} leaveRequestFlags=${leaveRequestFlags}]`, NS);
|
|
1984
|
-
return this.sendZDORequestBuffer(target, zdo_1.LEAVE_REQUEST, options);
|
|
1985
|
-
}
|
|
1986
|
-
/**
|
|
1987
|
-
* ZDO
|
|
1988
|
-
* Request the specified node to allow or disallow association.
|
|
1989
|
-
*
|
|
1990
|
-
* @param target The node which will allow or disallow association. The request
|
|
1991
|
-
* can be broadcast by using a broadcast address (0xFFFC/0xFFFD/0xFFFF). No
|
|
1992
|
-
* response is sent if the request is broadcast.
|
|
1993
|
-
* @param duration uint8_t A value of 0x00 disables joining. A value of 0xFF enables
|
|
1994
|
-
* joining. Any other value enables joining for that number of seconds.
|
|
1995
|
-
* @param authentication uint8_t Controls Trust Center authentication behavior.
|
|
1996
|
-
* @param options The options to use when sending the request. See
|
|
1997
|
-
* emberSendUnicast() for a description. This parameter is ignored if the target
|
|
1998
|
-
* is a broadcast address.
|
|
1999
|
-
*
|
|
2000
|
-
* @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
|
|
2001
|
-
* ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
|
|
2002
|
-
*/
|
|
2003
|
-
async emberPermitJoiningRequest(target, duration, authentication, options) {
|
|
2004
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
2005
|
-
this.zdoRequestBuffalo.writeUInt8(duration);
|
|
2006
|
-
this.zdoRequestBuffalo.writeUInt8(authentication);
|
|
2007
|
-
logger_1.logger.debug(`~~~> [ZDO PERMIT_JOINING_REQUEST target=${target} duration=${duration} authentication=${authentication}]`, NS);
|
|
2008
|
-
return this.sendZDORequestBuffer(target, zdo_1.PERMIT_JOINING_REQUEST, options);
|
|
2009
|
-
}
|
|
2010
|
-
/**
|
|
2011
|
-
* ZDO
|
|
2012
|
-
*
|
|
2013
|
-
* @see NWK_UPDATE_REQUEST
|
|
2014
|
-
*
|
|
2015
|
-
* @param target
|
|
2016
|
-
* @param scanChannels uint8_t[]
|
|
2017
|
-
* @param duration uint8_t
|
|
2018
|
-
* @param count uint8_t
|
|
2019
|
-
* @param manager
|
|
2020
|
-
*/
|
|
2021
|
-
async emberNetworkUpdateRequest(target, scanChannels, duration, count, manager, options) {
|
|
2022
|
-
this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
|
|
2023
|
-
this.zdoRequestBuffalo.writeUInt32(scanChannels.reduce((a, c) => a + (1 << c), 0)); // to uint32_t
|
|
2024
|
-
this.zdoRequestBuffalo.writeUInt8(duration);
|
|
2025
|
-
if (count != null) {
|
|
2026
|
-
this.zdoRequestBuffalo.writeUInt8(count);
|
|
2027
|
-
}
|
|
2028
|
-
if (manager != null) {
|
|
2029
|
-
this.zdoRequestBuffalo.writeUInt16(manager);
|
|
2030
|
-
}
|
|
2031
|
-
logger_1.logger.debug(`~~~> [ZDO NWK_UPDATE_REQUEST target=${target} scanChannels=${scanChannels} duration=${duration} count=${count} manager=${manager}]`, NS);
|
|
2032
|
-
return this.sendZDORequestBuffer(target, zdo_1.NWK_UPDATE_REQUEST, options);
|
|
2033
|
-
}
|
|
2034
|
-
async emberScanChannelsRequest(target, scanChannels, duration, count, options) {
|
|
2035
|
-
return this.emberNetworkUpdateRequest(target, scanChannels, duration, count, null, options);
|
|
2036
|
-
}
|
|
2037
|
-
async emberChannelChangeRequest(target, channel, options) {
|
|
2038
|
-
return this.emberNetworkUpdateRequest(target, [channel], 0xFE, null, null, options);
|
|
2039
|
-
}
|
|
2040
|
-
async emberSetActiveChannelsAndNwkManagerIdRequest(target, scanChannels, manager, options) {
|
|
2041
|
-
return this.emberNetworkUpdateRequest(target, scanChannels, 0xFF, null, manager, options);
|
|
2042
|
-
}
|
|
2043
1399
|
//---- END Ember ZDO
|
|
2044
1400
|
//-- START Adapter implementation
|
|
2045
1401
|
static async isValidPath(path) {
|
|
@@ -2093,7 +1449,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2093
1449
|
};
|
|
2094
1450
|
}),
|
|
2095
1451
|
});
|
|
2096
|
-
return
|
|
1452
|
+
return enums_2.SLStatus.OK;
|
|
2097
1453
|
}, reject);
|
|
2098
1454
|
});
|
|
2099
1455
|
}
|
|
@@ -2118,43 +1474,34 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2118
1474
|
this.requestQueue.enqueue(async () => {
|
|
2119
1475
|
// grab fresh version here, bypass cache
|
|
2120
1476
|
const [netStatus, , netParams] = (await this.ezsp.ezspGetNetworkParameters());
|
|
2121
|
-
if (netStatus !==
|
|
2122
|
-
logger_1.logger.error(`[BACKUP] Failed to get network parameters.`, NS);
|
|
1477
|
+
if (netStatus !== enums_2.SLStatus.OK) {
|
|
1478
|
+
logger_1.logger.error(`[BACKUP] Failed to get network parameters with status=${enums_2.SLStatus[netStatus]}.`, NS);
|
|
2123
1479
|
return netStatus;
|
|
2124
1480
|
}
|
|
2125
1481
|
// update cache
|
|
2126
1482
|
this.networkCache.parameters = netParams;
|
|
2127
1483
|
this.networkCache.eui64 = (await this.ezsp.ezspGetEui64());
|
|
2128
1484
|
const [netKeyStatus, netKeyInfo] = (await this.ezsp.ezspGetNetworkKeyInfo());
|
|
2129
|
-
if (netKeyStatus !==
|
|
2130
|
-
logger_1.logger.error(`[BACKUP] Failed to get network keys info.`, NS);
|
|
2131
|
-
return
|
|
2132
|
-
? enums_3.EmberStatus.NETWORK_BUSY : enums_3.EmberStatus.ERR_FATAL; // allow retry on statuses that should be temporary
|
|
1485
|
+
if (netKeyStatus !== enums_2.SLStatus.OK) {
|
|
1486
|
+
logger_1.logger.error(`[BACKUP] Failed to get network keys info with status=${enums_2.SLStatus[netKeyStatus]}.`, NS);
|
|
1487
|
+
return netKeyStatus;
|
|
2133
1488
|
}
|
|
2134
1489
|
if (!netKeyInfo.networkKeySet) {
|
|
2135
1490
|
throw new Error(`[BACKUP] No network key set.`);
|
|
2136
1491
|
}
|
|
2137
|
-
|
|
2138
|
-
if (this.stackConfig.KEY_TABLE_SIZE > 0) {
|
|
2139
|
-
keyList = (await this.exportLinkKeys());
|
|
2140
|
-
}
|
|
2141
|
-
// XXX: this only makes sense on stop (if that), not hourly/on start, plus network needs to be at near-standstill @see AN1387
|
|
2142
|
-
// const tokensBuf = (await EmberTokensManager.saveTokens(
|
|
2143
|
-
// this.ezsp,
|
|
2144
|
-
// Buffer.from(this.networkCache.eui64.substring(2/*0x*/), 'hex').reverse()
|
|
2145
|
-
// ));
|
|
1492
|
+
const keyList = ALLOW_APP_KEY_REQUESTS ? await this.exportLinkKeys() : [];
|
|
2146
1493
|
let context = (0, initters_1.initSecurityManagerContext)();
|
|
2147
|
-
context.coreKeyType =
|
|
2148
|
-
const [
|
|
2149
|
-
if (tclkStatus !==
|
|
2150
|
-
throw new Error(`[BACKUP] Failed to export TC Link Key with status=${
|
|
1494
|
+
context.coreKeyType = enums_2.SecManKeyType.TC_LINK;
|
|
1495
|
+
const [tclkStatus, tcLinkKey] = (await this.ezsp.ezspExportKey(context));
|
|
1496
|
+
if (tclkStatus !== enums_2.SLStatus.OK) {
|
|
1497
|
+
throw new Error(`[BACKUP] Failed to export TC Link Key with status=${enums_2.SLStatus[tclkStatus]}.`);
|
|
2151
1498
|
}
|
|
2152
1499
|
context = (0, initters_1.initSecurityManagerContext)(); // make sure it's back to zeroes
|
|
2153
|
-
context.coreKeyType =
|
|
1500
|
+
context.coreKeyType = enums_2.SecManKeyType.NETWORK;
|
|
2154
1501
|
context.keyIndex = 0;
|
|
2155
|
-
const [
|
|
2156
|
-
if (nkStatus !==
|
|
2157
|
-
throw new Error(`[BACKUP] Failed to export Network Key with status=${
|
|
1502
|
+
const [nkStatus, networkKey] = (await this.ezsp.ezspExportKey(context));
|
|
1503
|
+
if (nkStatus !== enums_2.SLStatus.OK) {
|
|
1504
|
+
throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_2.SLStatus[nkStatus]}.`);
|
|
2158
1505
|
}
|
|
2159
1506
|
const zbChannels = Array.from(Array(consts_2.EMBER_NUM_802_15_4_CHANNELS), (e, i) => i + consts_2.EMBER_MIN_802_15_4_CHANNEL_NUMBER);
|
|
2160
1507
|
resolve({
|
|
@@ -2190,7 +1537,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2190
1537
|
// altNetworkKey: altNetworkKey.contents,
|
|
2191
1538
|
}
|
|
2192
1539
|
});
|
|
2193
|
-
return
|
|
1540
|
+
return enums_2.SLStatus.OK;
|
|
2194
1541
|
}, reject, true);
|
|
2195
1542
|
});
|
|
2196
1543
|
}
|
|
@@ -2209,7 +1556,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2209
1556
|
extendedPanID: parseInt(Buffer.from(extendedPanID).toString('hex'), 16),
|
|
2210
1557
|
channel,
|
|
2211
1558
|
});
|
|
2212
|
-
return
|
|
1559
|
+
return enums_2.SLStatus.OK;
|
|
2213
1560
|
}, reject);
|
|
2214
1561
|
});
|
|
2215
1562
|
}
|
|
@@ -2221,16 +1568,39 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2221
1568
|
return new Promise((resolve, reject) => {
|
|
2222
1569
|
this.requestQueue.enqueue(async () => {
|
|
2223
1570
|
this.checkInterpanLock();
|
|
1571
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildChannelChangeRequest(newChannel, null);
|
|
2224
1572
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2225
|
-
const [status, apsFrame, messageTag] =
|
|
2226
|
-
if (status !==
|
|
2227
|
-
logger_1.logger.error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${
|
|
1573
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(ZSpec.BroadcastAddress.SLEEPY, Zdo.ClusterId.NWK_UPDATE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1574
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1575
|
+
logger_1.logger.error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2228
1576
|
return status;
|
|
2229
1577
|
}
|
|
2230
1578
|
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED }, DEFAULT_NETWORK_REQUEST_TIMEOUT * 2, // observed to ~9sec
|
|
2231
1579
|
'[ZDO] Change Channel');
|
|
2232
1580
|
resolve();
|
|
2233
|
-
return
|
|
1581
|
+
return enums_2.SLStatus.OK;
|
|
1582
|
+
}, reject);
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
// queued
|
|
1586
|
+
async scanChannels(networkAddress, channels, duration, count) {
|
|
1587
|
+
return new Promise((resolve, reject) => {
|
|
1588
|
+
this.requestQueue.enqueue(async () => {
|
|
1589
|
+
this.checkInterpanLock();
|
|
1590
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildScanChannelsRequest(channels, duration, count);
|
|
1591
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1592
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.NWK_UPDATE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1593
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1594
|
+
logger_1.logger.error(`[ZDO] Failed to scan channels '${channels}' on '${networkAddress} with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1595
|
+
return status;
|
|
1596
|
+
}
|
|
1597
|
+
const result = await this.oneWaitress.startWaitingFor({
|
|
1598
|
+
target: networkAddress,
|
|
1599
|
+
apsFrame,
|
|
1600
|
+
responseClusterId: Zdo.ClusterId.NWK_UPDATE_RESPONSE,
|
|
1601
|
+
}, DEFAULT_ZDO_REQUEST_TIMEOUT + (((((2 ** duration) + 1) * (16 * 960)) / 1000) * count * channels.length)); // time for scan
|
|
1602
|
+
resolve(result);
|
|
1603
|
+
return enums_2.SLStatus.OK;
|
|
2234
1604
|
}, reject);
|
|
2235
1605
|
});
|
|
2236
1606
|
}
|
|
@@ -2243,12 +1613,12 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2243
1613
|
return new Promise((resolve, reject) => {
|
|
2244
1614
|
this.requestQueue.enqueue(async () => {
|
|
2245
1615
|
const status = await this.ezsp.ezspSetRadioPower(value);
|
|
2246
|
-
if (status !==
|
|
2247
|
-
logger_1.logger.error(`Failed to set transmit power to ${value} status=${
|
|
1616
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1617
|
+
logger_1.logger.error(`Failed to set transmit power to ${value} status=${enums_2.SLStatus[status]}.`, NS);
|
|
2248
1618
|
return status;
|
|
2249
1619
|
}
|
|
2250
1620
|
resolve();
|
|
2251
|
-
return
|
|
1621
|
+
return enums_2.SLStatus.OK;
|
|
2252
1622
|
}, reject);
|
|
2253
1623
|
});
|
|
2254
1624
|
}
|
|
@@ -2282,22 +1652,22 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2282
1652
|
this.requestQueue.enqueue(async () => {
|
|
2283
1653
|
// Compute the key from the install code and CRC.
|
|
2284
1654
|
const [aesStatus, keyContents] = (await this.emberAesHashSimple(key));
|
|
2285
|
-
if (aesStatus !==
|
|
2286
|
-
logger_1.logger.error(`[ADD INSTALL CODE] Failed AES hash for '${ieeeAddress}' with status=${
|
|
1655
|
+
if (aesStatus !== enums_2.SLStatus.OK) {
|
|
1656
|
+
logger_1.logger.error(`[ADD INSTALL CODE] Failed AES hash for '${ieeeAddress}' with status=${enums_2.SLStatus[aesStatus]}.`, NS);
|
|
2287
1657
|
return aesStatus;
|
|
2288
1658
|
}
|
|
2289
1659
|
// Add the key to the transient key table.
|
|
2290
1660
|
// This will be used while the DUT joins.
|
|
2291
|
-
const impStatus = (await this.ezsp.ezspImportTransientKey(ieeeAddress, { contents: keyContents }
|
|
2292
|
-
if (impStatus ==
|
|
1661
|
+
const impStatus = (await this.ezsp.ezspImportTransientKey(ieeeAddress, { contents: keyContents }));
|
|
1662
|
+
if (impStatus == enums_2.SLStatus.OK) {
|
|
2293
1663
|
logger_1.logger.debug(`[ADD INSTALL CODE] Success for '${ieeeAddress}'.`, NS);
|
|
2294
1664
|
}
|
|
2295
1665
|
else {
|
|
2296
|
-
logger_1.logger.error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${
|
|
2297
|
-
return
|
|
1666
|
+
logger_1.logger.error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${enums_2.SLStatus[impStatus]}.`, NS);
|
|
1667
|
+
return enums_2.SLStatus.FAIL;
|
|
2298
1668
|
}
|
|
2299
1669
|
resolve();
|
|
2300
|
-
return
|
|
1670
|
+
return enums_2.SLStatus.OK;
|
|
2301
1671
|
}, reject);
|
|
2302
1672
|
});
|
|
2303
1673
|
}
|
|
@@ -2313,7 +1683,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2313
1683
|
sourceEndpoint: sourceEndpointInfo.endpoint,
|
|
2314
1684
|
destinationEndpoint: endpoint,
|
|
2315
1685
|
groupId: 0,
|
|
2316
|
-
options:
|
|
1686
|
+
options: enums_2.EmberApsOption.NONE,
|
|
2317
1687
|
},
|
|
2318
1688
|
zclSequence: transactionSequenceNumber,
|
|
2319
1689
|
commandIdentifier,
|
|
@@ -2329,17 +1699,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2329
1699
|
const preJoining = async () => {
|
|
2330
1700
|
if (seconds) {
|
|
2331
1701
|
const plaintextKey = { contents: Buffer.from(consts_2.ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY) };
|
|
2332
|
-
const impKeyStatus = (await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey
|
|
2333
|
-
if (impKeyStatus !==
|
|
2334
|
-
logger_1.logger.error(`[ZDO] Failed import transient key with status=${
|
|
2335
|
-
return
|
|
1702
|
+
const impKeyStatus = (await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey));
|
|
1703
|
+
if (impKeyStatus !== enums_2.SLStatus.OK) {
|
|
1704
|
+
logger_1.logger.error(`[ZDO] Failed import transient key with status=${enums_2.SLStatus[impKeyStatus]}.`, NS);
|
|
1705
|
+
return enums_2.SLStatus.FAIL;
|
|
2336
1706
|
}
|
|
2337
|
-
const setJPstatus = (await this.emberSetJoinPolicy(
|
|
2338
|
-
if (setJPstatus !==
|
|
2339
|
-
logger_1.logger.error(`[ZDO] Failed set join policy with status=${
|
|
2340
|
-
return
|
|
1707
|
+
const setJPstatus = (await this.emberSetJoinPolicy(enums_2.EmberJoinDecision.USE_PRECONFIGURED_KEY));
|
|
1708
|
+
if (setJPstatus !== enums_2.SLStatus.OK) {
|
|
1709
|
+
logger_1.logger.error(`[ZDO] Failed set join policy with status=${enums_2.SLStatus[setJPstatus]}.`, NS);
|
|
1710
|
+
return enums_2.SLStatus.FAIL;
|
|
2341
1711
|
}
|
|
2342
|
-
return
|
|
1712
|
+
return enums_2.SLStatus.OK;
|
|
2343
1713
|
}
|
|
2344
1714
|
else {
|
|
2345
1715
|
if (this.manufacturerCode !== DEFAULT_MANUFACTURER_CODE) {
|
|
@@ -2348,12 +1718,12 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2348
1718
|
this.manufacturerCode = DEFAULT_MANUFACTURER_CODE;
|
|
2349
1719
|
}
|
|
2350
1720
|
await this.ezsp.ezspClearTransientLinkKeys();
|
|
2351
|
-
const setJPstatus = (await this.emberSetJoinPolicy(
|
|
2352
|
-
if (setJPstatus !==
|
|
2353
|
-
logger_1.logger.error(`[ZDO] Failed set join policy for with status=${
|
|
2354
|
-
return
|
|
1721
|
+
const setJPstatus = (await this.emberSetJoinPolicy(enums_2.EmberJoinDecision.ALLOW_REJOINS_ONLY));
|
|
1722
|
+
if (setJPstatus !== enums_2.SLStatus.OK) {
|
|
1723
|
+
logger_1.logger.error(`[ZDO] Failed set join policy for with status=${enums_2.SLStatus[setJPstatus]}.`, NS);
|
|
1724
|
+
return enums_2.SLStatus.FAIL;
|
|
2355
1725
|
}
|
|
2356
|
-
return
|
|
1726
|
+
return enums_2.SLStatus.OK;
|
|
2357
1727
|
}
|
|
2358
1728
|
};
|
|
2359
1729
|
if (networkAddress) {
|
|
@@ -2362,24 +1732,25 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2362
1732
|
this.requestQueue.enqueue(async () => {
|
|
2363
1733
|
this.checkInterpanLock();
|
|
2364
1734
|
const pjStatus = (await preJoining());
|
|
2365
|
-
if (pjStatus !==
|
|
2366
|
-
logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${
|
|
1735
|
+
if (pjStatus !== enums_2.SLStatus.OK) {
|
|
1736
|
+
logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${enums_2.SLStatus[pjStatus]}.`, NS);
|
|
2367
1737
|
return pjStatus;
|
|
2368
1738
|
}
|
|
2369
1739
|
// `authentication`: TC significance always 1 (zb specs)
|
|
1740
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildPermitJoining(seconds, 1, []);
|
|
2370
1741
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2371
|
-
const [status, apsFrame, messageTag] =
|
|
2372
|
-
if (status !==
|
|
2373
|
-
logger_1.logger.error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${
|
|
1742
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1743
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1744
|
+
logger_1.logger.error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2374
1745
|
return status;
|
|
2375
1746
|
}
|
|
2376
1747
|
(await this.oneWaitress.startWaitingFor({
|
|
2377
1748
|
target: networkAddress,
|
|
2378
1749
|
apsFrame,
|
|
2379
|
-
responseClusterId:
|
|
1750
|
+
responseClusterId: Zdo.ClusterId.PERMIT_JOINING_RESPONSE,
|
|
2380
1751
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2381
1752
|
resolve();
|
|
2382
|
-
return
|
|
1753
|
+
return enums_2.SLStatus.OK;
|
|
2383
1754
|
}, reject);
|
|
2384
1755
|
});
|
|
2385
1756
|
}
|
|
@@ -2389,15 +1760,15 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2389
1760
|
this.requestQueue.enqueue(async () => {
|
|
2390
1761
|
this.checkInterpanLock();
|
|
2391
1762
|
const pjStatus = (await preJoining());
|
|
2392
|
-
if (pjStatus !==
|
|
2393
|
-
logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${
|
|
1763
|
+
if (pjStatus !== enums_2.SLStatus.OK) {
|
|
1764
|
+
logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${enums_2.SLStatus[pjStatus]}.`, NS);
|
|
2394
1765
|
return pjStatus;
|
|
2395
1766
|
}
|
|
2396
1767
|
// local permit join if `Coordinator`-only requested, else local + broadcast
|
|
2397
1768
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2398
1769
|
const [status, apsFrame, messageTag] = (await this.emberPermitJoining(seconds, (networkAddress === ZSpec.COORDINATOR_ADDRESS) ? false : true));
|
|
2399
|
-
if (status !==
|
|
2400
|
-
logger_1.logger.error(`[ZDO] Failed permit joining request with status=${
|
|
1770
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1771
|
+
logger_1.logger.error(`[ZDO] Failed permit joining request with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2401
1772
|
return status;
|
|
2402
1773
|
}
|
|
2403
1774
|
// NOTE: because Z2M is refreshing the permit join duration early to prevent it from closing
|
|
@@ -2418,7 +1789,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2418
1789
|
// // same kind of problem as described above (upstream always tries to close after start, but EZSP already is)
|
|
2419
1790
|
// }
|
|
2420
1791
|
resolve();
|
|
2421
|
-
return
|
|
1792
|
+
return enums_2.SLStatus.OK;
|
|
2422
1793
|
}, reject);
|
|
2423
1794
|
});
|
|
2424
1795
|
}
|
|
@@ -2427,40 +1798,41 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2427
1798
|
async lqi(networkAddress) {
|
|
2428
1799
|
const neighbors = [];
|
|
2429
1800
|
const request = async (startIndex) => {
|
|
1801
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildLqiTableRequest(startIndex);
|
|
2430
1802
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2431
|
-
const [
|
|
2432
|
-
if (
|
|
2433
|
-
logger_1.logger.error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${
|
|
2434
|
-
return [
|
|
1803
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LQI_TABLE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1804
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1805
|
+
logger_1.logger.error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1806
|
+
return [status, null, null];
|
|
2435
1807
|
}
|
|
2436
1808
|
const result = (await this.oneWaitress.startWaitingFor({
|
|
2437
1809
|
target: networkAddress,
|
|
2438
1810
|
apsFrame,
|
|
2439
|
-
responseClusterId:
|
|
1811
|
+
responseClusterId: Zdo.ClusterId.LQI_TABLE_RESPONSE,
|
|
2440
1812
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2441
1813
|
for (const entry of result.entryList) {
|
|
2442
1814
|
neighbors.push({
|
|
2443
1815
|
ieeeAddr: entry.eui64,
|
|
2444
|
-
networkAddress: entry.
|
|
1816
|
+
networkAddress: entry.nwkAddress,
|
|
2445
1817
|
linkquality: entry.lqi,
|
|
2446
1818
|
relationship: entry.relationship,
|
|
2447
1819
|
depth: entry.depth,
|
|
2448
1820
|
});
|
|
2449
1821
|
}
|
|
2450
|
-
return [
|
|
1822
|
+
return [enums_2.SLStatus.OK, result.neighborTableEntries, result.entryList.length];
|
|
2451
1823
|
};
|
|
2452
1824
|
return new Promise((resolve, reject) => {
|
|
2453
1825
|
this.requestQueue.enqueue(async () => {
|
|
2454
1826
|
this.checkInterpanLock();
|
|
2455
1827
|
let [status, tableEntries, entryCount] = (await request(0));
|
|
2456
|
-
if (status !==
|
|
1828
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2457
1829
|
return status;
|
|
2458
1830
|
}
|
|
2459
1831
|
const size = tableEntries;
|
|
2460
1832
|
let nextStartIndex = entryCount;
|
|
2461
1833
|
while (neighbors.length < size) {
|
|
2462
1834
|
[status, tableEntries, entryCount] = (await request(nextStartIndex));
|
|
2463
|
-
if (status !==
|
|
1835
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2464
1836
|
return status;
|
|
2465
1837
|
}
|
|
2466
1838
|
nextStartIndex += entryCount;
|
|
@@ -2474,16 +1846,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2474
1846
|
async routingTable(networkAddress) {
|
|
2475
1847
|
const table = [];
|
|
2476
1848
|
const request = async (startIndex) => {
|
|
1849
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildRoutingTableRequest(startIndex);
|
|
2477
1850
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2478
|
-
const [
|
|
2479
|
-
if (
|
|
2480
|
-
logger_1.logger.error(`[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${
|
|
2481
|
-
return [
|
|
1851
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ROUTING_TABLE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1852
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1853
|
+
logger_1.logger.error(`[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${enums_2.SLStatus[status]}.`, NS);
|
|
1854
|
+
return [status, null, null];
|
|
2482
1855
|
}
|
|
2483
1856
|
const result = (await this.oneWaitress.startWaitingFor({
|
|
2484
1857
|
target: networkAddress,
|
|
2485
1858
|
apsFrame,
|
|
2486
|
-
responseClusterId:
|
|
1859
|
+
responseClusterId: Zdo.ClusterId.ROUTING_TABLE_RESPONSE,
|
|
2487
1860
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2488
1861
|
for (const entry of result.entryList) {
|
|
2489
1862
|
table.push({
|
|
@@ -2492,26 +1865,26 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2492
1865
|
nextHop: entry.nextHopAddress,
|
|
2493
1866
|
});
|
|
2494
1867
|
}
|
|
2495
|
-
return [
|
|
1868
|
+
return [enums_2.SLStatus.OK, result.routingTableEntries, result.entryList.length];
|
|
2496
1869
|
};
|
|
2497
1870
|
return new Promise((resolve, reject) => {
|
|
2498
1871
|
this.requestQueue.enqueue(async () => {
|
|
2499
1872
|
this.checkInterpanLock();
|
|
2500
1873
|
let [status, tableEntries, entryCount] = (await request(0));
|
|
2501
|
-
if (status !==
|
|
1874
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2502
1875
|
return status;
|
|
2503
1876
|
}
|
|
2504
1877
|
const size = tableEntries;
|
|
2505
1878
|
let nextStartIndex = entryCount;
|
|
2506
1879
|
while (table.length < size) {
|
|
2507
1880
|
[status, tableEntries, entryCount] = (await request(nextStartIndex));
|
|
2508
|
-
if (status !==
|
|
1881
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2509
1882
|
return status;
|
|
2510
1883
|
}
|
|
2511
1884
|
nextStartIndex += entryCount;
|
|
2512
1885
|
}
|
|
2513
1886
|
resolve({ table });
|
|
2514
|
-
return
|
|
1887
|
+
return enums_2.SLStatus.OK;
|
|
2515
1888
|
}, reject);
|
|
2516
1889
|
});
|
|
2517
1890
|
}
|
|
@@ -2520,16 +1893,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2520
1893
|
return new Promise((resolve, reject) => {
|
|
2521
1894
|
this.requestQueue.enqueue(async () => {
|
|
2522
1895
|
this.checkInterpanLock();
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
1896
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildNodeDescriptorRequest(networkAddress);
|
|
1897
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1898
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1899
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1900
|
+
logger_1.logger.error(`[ZDO] Failed node descriptor for "${networkAddress}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2527
1901
|
return status;
|
|
2528
1902
|
}
|
|
2529
1903
|
const result = (await this.oneWaitress.startWaitingFor({
|
|
2530
1904
|
target: networkAddress,
|
|
2531
1905
|
apsFrame,
|
|
2532
|
-
responseClusterId:
|
|
1906
|
+
responseClusterId: Zdo.ClusterId.NODE_DESCRIPTOR_RESPONSE,
|
|
2533
1907
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2534
1908
|
let type = 'Unknown';
|
|
2535
1909
|
switch (result.logicalType) {
|
|
@@ -2544,13 +1918,13 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2544
1918
|
break;
|
|
2545
1919
|
}
|
|
2546
1920
|
// always 0 before rev. 21 where field was added
|
|
2547
|
-
if (result.
|
|
2548
|
-
logger_1.logger.warning(`[ZDO] Node descriptor for
|
|
2549
|
-
+ `
|
|
2550
|
-
+ `(current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS);
|
|
1921
|
+
if (result.serverMask.stackComplianceResivion < CURRENT_ZIGBEE_SPEC_REVISION) {
|
|
1922
|
+
logger_1.logger.warning(`[ZDO] Node descriptor for '${networkAddress}' reports device is only compliant to revision `
|
|
1923
|
+
+ `'${(result.serverMask.stackComplianceResivion < 21) ? 'pre-21' : result.serverMask.stackComplianceResivion}' `
|
|
1924
|
+
+ `of the ZigBee specification (current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS);
|
|
2551
1925
|
}
|
|
2552
1926
|
resolve({ type, manufacturerCode: result.manufacturerCode });
|
|
2553
|
-
return
|
|
1927
|
+
return enums_2.SLStatus.OK;
|
|
2554
1928
|
}, reject);
|
|
2555
1929
|
});
|
|
2556
1930
|
}
|
|
@@ -2559,19 +1933,20 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2559
1933
|
return new Promise((resolve, reject) => {
|
|
2560
1934
|
this.requestQueue.enqueue(async () => {
|
|
2561
1935
|
this.checkInterpanLock();
|
|
1936
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildActiveEndpointsRequest(networkAddress);
|
|
2562
1937
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2563
|
-
const [status, apsFrame, messageTag] =
|
|
2564
|
-
if (status !==
|
|
2565
|
-
logger_1.logger.error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${
|
|
1938
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1939
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
1940
|
+
logger_1.logger.error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2566
1941
|
return status;
|
|
2567
1942
|
}
|
|
2568
1943
|
const result = (await this.oneWaitress.startWaitingFor({
|
|
2569
1944
|
target: networkAddress,
|
|
2570
1945
|
apsFrame,
|
|
2571
|
-
responseClusterId:
|
|
1946
|
+
responseClusterId: Zdo.ClusterId.ACTIVE_ENDPOINTS_RESPONSE,
|
|
2572
1947
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2573
1948
|
resolve({ endpoints: result.endpointList });
|
|
2574
|
-
return
|
|
1949
|
+
return enums_2.SLStatus.OK;
|
|
2575
1950
|
}, reject);
|
|
2576
1951
|
});
|
|
2577
1952
|
}
|
|
@@ -2580,17 +1955,18 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2580
1955
|
return new Promise((resolve, reject) => {
|
|
2581
1956
|
this.requestQueue.enqueue(async () => {
|
|
2582
1957
|
this.checkInterpanLock();
|
|
1958
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildSimpleDescriptorRequest(networkAddress, endpointID);
|
|
2583
1959
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2584
|
-
const [status, apsFrame, messageTag] =
|
|
2585
|
-
if (status !==
|
|
1960
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1961
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2586
1962
|
logger_1.logger.error(`[ZDO] Failed simple descriptor request for "${networkAddress}" endpoint "${endpointID}" `
|
|
2587
|
-
+ `with status=${
|
|
1963
|
+
+ `with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2588
1964
|
return status;
|
|
2589
1965
|
}
|
|
2590
1966
|
const result = (await this.oneWaitress.startWaitingFor({
|
|
2591
1967
|
target: networkAddress,
|
|
2592
1968
|
apsFrame,
|
|
2593
|
-
responseClusterId:
|
|
1969
|
+
responseClusterId: Zdo.ClusterId.SIMPLE_DESCRIPTOR_RESPONSE,
|
|
2594
1970
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT));
|
|
2595
1971
|
resolve({
|
|
2596
1972
|
profileID: result.profileId,
|
|
@@ -2599,7 +1975,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2599
1975
|
inputClusters: result.inClusterList,
|
|
2600
1976
|
outputClusters: result.outClusterList,
|
|
2601
1977
|
});
|
|
2602
|
-
return
|
|
1978
|
+
return enums_2.SLStatus.OK;
|
|
2603
1979
|
}, reject);
|
|
2604
1980
|
});
|
|
2605
1981
|
}
|
|
@@ -2610,21 +1986,22 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2610
1986
|
return new Promise((resolve, reject) => {
|
|
2611
1987
|
this.requestQueue.enqueue(async () => {
|
|
2612
1988
|
this.checkInterpanLock();
|
|
1989
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildBindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.UNICAST_BINDING, destinationAddressOrGroup, undefined, // not used with UNICAST_BINDING
|
|
1990
|
+
destinationEndpoint);
|
|
2613
1991
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2614
|
-
const [status, apsFrame, messageTag] =
|
|
2615
|
-
|
|
2616
|
-
if (status !== enums_3.EmberStatus.SUCCESS) {
|
|
1992
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.BIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
1993
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2617
1994
|
logger_1.logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" `
|
|
2618
|
-
+ `endpoint "${destinationEndpoint}" with status=${
|
|
1995
|
+
+ `endpoint "${destinationEndpoint}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2619
1996
|
return status;
|
|
2620
1997
|
}
|
|
2621
1998
|
await this.oneWaitress.startWaitingFor({
|
|
2622
1999
|
target: destinationNetworkAddress,
|
|
2623
2000
|
apsFrame,
|
|
2624
|
-
responseClusterId:
|
|
2001
|
+
responseClusterId: Zdo.ClusterId.BIND_RESPONSE,
|
|
2625
2002
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT);
|
|
2626
2003
|
resolve();
|
|
2627
|
-
return
|
|
2004
|
+
return enums_2.SLStatus.OK;
|
|
2628
2005
|
}, reject);
|
|
2629
2006
|
});
|
|
2630
2007
|
}
|
|
@@ -2633,22 +2010,23 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2633
2010
|
return new Promise((resolve, reject) => {
|
|
2634
2011
|
this.requestQueue.enqueue(async () => {
|
|
2635
2012
|
this.checkInterpanLock();
|
|
2013
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildBindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.MULTICAST_BINDING, undefined, // not used with MULTICAST_BINDING
|
|
2014
|
+
destinationAddressOrGroup, undefined // not used with MULTICAST_BINDING
|
|
2015
|
+
);
|
|
2636
2016
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2637
|
-
const [status, apsFrame, messageTag] =
|
|
2638
|
-
|
|
2639
|
-
DEFAULT_APS_OPTIONS));
|
|
2640
|
-
if (status !== enums_3.EmberStatus.SUCCESS) {
|
|
2017
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.BIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
2018
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2641
2019
|
logger_1.logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" `
|
|
2642
|
-
+ `with status=${
|
|
2020
|
+
+ `with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2643
2021
|
return status;
|
|
2644
2022
|
}
|
|
2645
2023
|
await this.oneWaitress.startWaitingFor({
|
|
2646
2024
|
target: destinationNetworkAddress,
|
|
2647
2025
|
apsFrame,
|
|
2648
|
-
responseClusterId:
|
|
2026
|
+
responseClusterId: Zdo.ClusterId.BIND_RESPONSE,
|
|
2649
2027
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT);
|
|
2650
2028
|
resolve();
|
|
2651
|
-
return
|
|
2029
|
+
return enums_2.SLStatus.OK;
|
|
2652
2030
|
}, reject);
|
|
2653
2031
|
});
|
|
2654
2032
|
}
|
|
@@ -2660,21 +2038,22 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2660
2038
|
return new Promise((resolve, reject) => {
|
|
2661
2039
|
this.requestQueue.enqueue(async () => {
|
|
2662
2040
|
this.checkInterpanLock();
|
|
2041
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildUnbindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.UNICAST_BINDING, destinationAddressOrGroup, undefined, // not used with UNICAST_BINDING
|
|
2042
|
+
destinationEndpoint);
|
|
2663
2043
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2664
|
-
const [status, apsFrame, messageTag] =
|
|
2665
|
-
|
|
2666
|
-
if (status !== enums_3.EmberStatus.SUCCESS) {
|
|
2044
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.UNBIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
2045
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2667
2046
|
logger_1.logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" `
|
|
2668
|
-
+ `endpoint "${destinationEndpoint}" with status=${
|
|
2047
|
+
+ `endpoint "${destinationEndpoint}" with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2669
2048
|
return status;
|
|
2670
2049
|
}
|
|
2671
2050
|
await this.oneWaitress.startWaitingFor({
|
|
2672
2051
|
target: destinationNetworkAddress,
|
|
2673
2052
|
apsFrame,
|
|
2674
|
-
responseClusterId:
|
|
2053
|
+
responseClusterId: Zdo.ClusterId.UNBIND_RESPONSE,
|
|
2675
2054
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT);
|
|
2676
2055
|
resolve();
|
|
2677
|
-
return
|
|
2056
|
+
return enums_2.SLStatus.OK;
|
|
2678
2057
|
}, reject);
|
|
2679
2058
|
});
|
|
2680
2059
|
}
|
|
@@ -2683,22 +2062,23 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2683
2062
|
return new Promise((resolve, reject) => {
|
|
2684
2063
|
this.requestQueue.enqueue(async () => {
|
|
2685
2064
|
this.checkInterpanLock();
|
|
2065
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildUnbindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.MULTICAST_BINDING, undefined, // not used with MULTICAST_BINDING
|
|
2066
|
+
destinationAddressOrGroup, undefined // not used with MULTICAST_BINDING
|
|
2067
|
+
);
|
|
2686
2068
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2687
|
-
const [status, apsFrame, messageTag] =
|
|
2688
|
-
|
|
2689
|
-
DEFAULT_APS_OPTIONS));
|
|
2690
|
-
if (status !== enums_3.EmberStatus.SUCCESS) {
|
|
2069
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.UNBIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
2070
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2691
2071
|
logger_1.logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" `
|
|
2692
|
-
+ `with status=${
|
|
2072
|
+
+ `with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2693
2073
|
return status;
|
|
2694
2074
|
}
|
|
2695
2075
|
await this.oneWaitress.startWaitingFor({
|
|
2696
2076
|
target: destinationNetworkAddress,
|
|
2697
2077
|
apsFrame,
|
|
2698
|
-
responseClusterId:
|
|
2078
|
+
responseClusterId: Zdo.ClusterId.UNBIND_RESPONSE,
|
|
2699
2079
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT);
|
|
2700
2080
|
resolve();
|
|
2701
|
-
return
|
|
2081
|
+
return enums_2.SLStatus.OK;
|
|
2702
2082
|
}, reject);
|
|
2703
2083
|
});
|
|
2704
2084
|
}
|
|
@@ -2708,20 +2088,21 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2708
2088
|
return new Promise((resolve, reject) => {
|
|
2709
2089
|
this.requestQueue.enqueue(async () => {
|
|
2710
2090
|
this.checkInterpanLock();
|
|
2091
|
+
const zdoPayload = buffaloZdo_1.BuffaloZdo.buildLeaveRequest(ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
|
|
2711
2092
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2712
|
-
const [status, apsFrame, messageTag] =
|
|
2713
|
-
if (status !==
|
|
2093
|
+
const [status, apsFrame, messageTag] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LEAVE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
|
|
2094
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2714
2095
|
logger_1.logger.error(`[ZDO] Failed remove device request for "${networkAddress}" target "${ieeeAddr}" `
|
|
2715
|
-
+ `with status=${
|
|
2096
|
+
+ `with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2716
2097
|
return status;
|
|
2717
2098
|
}
|
|
2718
2099
|
await this.oneWaitress.startWaitingFor({
|
|
2719
2100
|
target: networkAddress,
|
|
2720
2101
|
apsFrame,
|
|
2721
|
-
responseClusterId:
|
|
2102
|
+
responseClusterId: Zdo.ClusterId.LEAVE_RESPONSE,
|
|
2722
2103
|
}, DEFAULT_ZDO_REQUEST_TIMEOUT);
|
|
2723
2104
|
resolve();
|
|
2724
|
-
return
|
|
2105
|
+
return enums_2.SLStatus.OK;
|
|
2725
2106
|
}, reject);
|
|
2726
2107
|
});
|
|
2727
2108
|
}
|
|
@@ -2749,24 +2130,18 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2749
2130
|
};
|
|
2750
2131
|
// don't RETRY if no response expected
|
|
2751
2132
|
if (commandResponseId == null) {
|
|
2752
|
-
apsFrame.options &= ~
|
|
2133
|
+
apsFrame.options &= ~enums_2.EmberApsOption.RETRY;
|
|
2753
2134
|
}
|
|
2754
2135
|
const data = zclFrame.toBuffer();
|
|
2755
2136
|
return new Promise((resolve, reject) => {
|
|
2756
2137
|
this.requestQueue.enqueue(async () => {
|
|
2757
2138
|
this.checkInterpanLock();
|
|
2758
|
-
if (CHECK_APS_PAYLOAD_LENGTH) {
|
|
2759
|
-
const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame));
|
|
2760
|
-
if (data.length > maxPayloadLength) {
|
|
2761
|
-
return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
2139
|
logger_1.logger.debug(`~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
2765
2140
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2766
|
-
const [status, messageTag] = (await this.ezsp.send(
|
|
2141
|
+
const [status, messageTag] = (await this.ezsp.send(enums_2.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, data, 0, // alias
|
|
2767
2142
|
0));
|
|
2768
|
-
if (status !==
|
|
2769
|
-
logger_1.logger.error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${
|
|
2143
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2144
|
+
logger_1.logger.error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2770
2145
|
return status; // let queue handle retry based on status
|
|
2771
2146
|
}
|
|
2772
2147
|
if (commandResponseId != null) {
|
|
@@ -2781,7 +2156,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2781
2156
|
}
|
|
2782
2157
|
else {
|
|
2783
2158
|
resolve(null); // don't expect a response
|
|
2784
|
-
return
|
|
2159
|
+
return enums_2.SLStatus.OK;
|
|
2785
2160
|
}
|
|
2786
2161
|
}, reject);
|
|
2787
2162
|
});
|
|
@@ -2803,24 +2178,18 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2803
2178
|
return new Promise((resolve, reject) => {
|
|
2804
2179
|
this.requestQueue.enqueue(async () => {
|
|
2805
2180
|
this.checkInterpanLock();
|
|
2806
|
-
if (CHECK_APS_PAYLOAD_LENGTH) {
|
|
2807
|
-
const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.MULTICAST, groupID, apsFrame));
|
|
2808
|
-
if (data.length > maxPayloadLength) {
|
|
2809
|
-
return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
|
|
2810
|
-
}
|
|
2811
|
-
}
|
|
2812
2181
|
logger_1.logger.debug(`~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
2813
2182
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2814
|
-
const [status, messageTag] = (await this.ezsp.send(
|
|
2183
|
+
const [status, messageTag] = (await this.ezsp.send(enums_2.EmberOutgoingMessageType.MULTICAST, apsFrame.groupId, // not used with MULTICAST
|
|
2815
2184
|
apsFrame, data, 0, // alias
|
|
2816
2185
|
0));
|
|
2817
|
-
if (status !==
|
|
2818
|
-
logger_1.logger.error(`~x~> [ZCL GROUP] Failed to send with status=${
|
|
2186
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2187
|
+
logger_1.logger.error(`~x~> [ZCL GROUP] Failed to send with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2819
2188
|
return status; // let queue handle retry based on status
|
|
2820
2189
|
}
|
|
2821
2190
|
// NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
|
|
2822
2191
|
resolve();
|
|
2823
|
-
return
|
|
2192
|
+
return enums_2.SLStatus.OK;
|
|
2824
2193
|
}, reject);
|
|
2825
2194
|
});
|
|
2826
2195
|
}
|
|
@@ -2841,23 +2210,17 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2841
2210
|
return new Promise((resolve, reject) => {
|
|
2842
2211
|
this.requestQueue.enqueue(async () => {
|
|
2843
2212
|
this.checkInterpanLock();
|
|
2844
|
-
if (CHECK_APS_PAYLOAD_LENGTH) {
|
|
2845
|
-
const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.BROADCAST, destination, apsFrame));
|
|
2846
|
-
if (data.length > maxPayloadLength) {
|
|
2847
|
-
return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
|
|
2848
|
-
}
|
|
2849
|
-
}
|
|
2850
2213
|
logger_1.logger.debug(`~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
2851
2214
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2852
|
-
const [status, messageTag] = (await this.ezsp.send(
|
|
2215
|
+
const [status, messageTag] = (await this.ezsp.send(enums_2.EmberOutgoingMessageType.BROADCAST, destination, apsFrame, data, 0, // alias
|
|
2853
2216
|
0));
|
|
2854
|
-
if (status !==
|
|
2855
|
-
logger_1.logger.error(`~x~> [ZCL BROADCAST] Failed to send with status=${
|
|
2217
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2218
|
+
logger_1.logger.error(`~x~> [ZCL BROADCAST] Failed to send with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2856
2219
|
return status; // let queue handle retry based on status
|
|
2857
2220
|
}
|
|
2858
2221
|
// NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
|
|
2859
2222
|
resolve();
|
|
2860
|
-
return
|
|
2223
|
+
return enums_2.SLStatus.OK;
|
|
2861
2224
|
}, reject);
|
|
2862
2225
|
});
|
|
2863
2226
|
}
|
|
@@ -2874,9 +2237,9 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2874
2237
|
this.requestQueue.enqueue(async () => {
|
|
2875
2238
|
this.interpanLock = true;
|
|
2876
2239
|
const status = (await this.ezsp.ezspSetLogicalAndRadioChannel(channel));
|
|
2877
|
-
if (status !==
|
|
2240
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2878
2241
|
this.interpanLock = false; // XXX: ok?
|
|
2879
|
-
logger_1.logger.error(`Failed to set InterPAN channel to ${channel} with status=${
|
|
2242
|
+
logger_1.logger.error(`Failed to set InterPAN channel to ${channel} with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2880
2243
|
return status;
|
|
2881
2244
|
}
|
|
2882
2245
|
resolve();
|
|
@@ -2899,13 +2262,13 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2899
2262
|
msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
|
|
2900
2263
|
msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
|
|
2901
2264
|
msgBuffalo.writeUInt16(consts_2.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
|
|
2902
|
-
msgBuffalo.writeUInt8((
|
|
2265
|
+
msgBuffalo.writeUInt8((enums_2.EmberInterpanMessageType.UNICAST | consts_2.INTERPAN_APS_FRAME_TYPE)); // apsFrameControl
|
|
2903
2266
|
msgBuffalo.writeUInt16(zclFrame.cluster.ID);
|
|
2904
2267
|
msgBuffalo.writeUInt16(ZSpec.TOUCHLINK_PROFILE_ID);
|
|
2905
2268
|
logger_1.logger.debug(`~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
2906
|
-
const status =
|
|
2907
|
-
if (status !==
|
|
2908
|
-
logger_1.logger.error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${
|
|
2269
|
+
const status = await this.ezsp.ezspSendRawMessage(Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]), enums_2.EmberTransmitPriority.NORMAL, true);
|
|
2270
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2271
|
+
logger_1.logger.error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2909
2272
|
return status;
|
|
2910
2273
|
}
|
|
2911
2274
|
// NOTE: can use ezspRawTransmitCompleteHandler if needed here
|
|
@@ -2926,8 +2289,8 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2926
2289
|
clusterId: zclFrame.cluster.ID,
|
|
2927
2290
|
sourceEndpoint: 0,
|
|
2928
2291
|
destinationEndpoint: 0,
|
|
2929
|
-
options:
|
|
2930
|
-
groupId:
|
|
2292
|
+
options: enums_2.EmberApsOption.NONE,
|
|
2293
|
+
groupId: ZSpec.BroadcastAddress.SLEEPY,
|
|
2931
2294
|
sequence: 0, // set by stack
|
|
2932
2295
|
};
|
|
2933
2296
|
return new Promise((resolve, reject) => {
|
|
@@ -2943,14 +2306,14 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2943
2306
|
msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
|
|
2944
2307
|
msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
|
|
2945
2308
|
msgBuffalo.writeUInt16(consts_2.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
|
|
2946
|
-
msgBuffalo.writeUInt8((
|
|
2309
|
+
msgBuffalo.writeUInt8((enums_2.EmberInterpanMessageType.BROADCAST | consts_2.INTERPAN_APS_FRAME_TYPE)); // apsFrameControl
|
|
2947
2310
|
msgBuffalo.writeUInt16(apsFrame.clusterId);
|
|
2948
2311
|
msgBuffalo.writeUInt16(apsFrame.profileId);
|
|
2949
2312
|
const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]);
|
|
2950
2313
|
logger_1.logger.debug(`~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
2951
|
-
const status = (await this.ezsp.ezspSendRawMessage(data));
|
|
2952
|
-
if (status !==
|
|
2953
|
-
logger_1.logger.error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${
|
|
2314
|
+
const status = (await this.ezsp.ezspSendRawMessage(data, enums_2.EmberTransmitPriority.NORMAL, true));
|
|
2315
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2316
|
+
logger_1.logger.error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2954
2317
|
return status;
|
|
2955
2318
|
}
|
|
2956
2319
|
// NOTE: can use ezspRawTransmitCompleteHandler if needed here
|
|
@@ -2961,7 +2324,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2961
2324
|
commandIdentifier: command.response,
|
|
2962
2325
|
}, timeout || DEFAULT_ZCL_REQUEST_TIMEOUT * 2)); // XXX: touchlink timeout?
|
|
2963
2326
|
resolve(result);
|
|
2964
|
-
return
|
|
2327
|
+
return enums_2.SLStatus.OK;
|
|
2965
2328
|
}, reject);
|
|
2966
2329
|
});
|
|
2967
2330
|
}
|
|
@@ -2970,8 +2333,8 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2970
2333
|
return new Promise((resolve, reject) => {
|
|
2971
2334
|
this.requestQueue.enqueue(async () => {
|
|
2972
2335
|
const status = (await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0]));
|
|
2973
|
-
if (status !==
|
|
2974
|
-
logger_1.logger.error(`Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${
|
|
2336
|
+
if (status !== enums_2.SLStatus.OK) {
|
|
2337
|
+
logger_1.logger.error(`Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${enums_2.SLStatus[status]}.`, NS);
|
|
2975
2338
|
return status;
|
|
2976
2339
|
}
|
|
2977
2340
|
// let adapter settle down
|
|
@@ -2987,7 +2350,7 @@ class EmberAdapter extends __1.Adapter {
|
|
|
2987
2350
|
if (this.interpanLock) {
|
|
2988
2351
|
logger_1.logger.error(`[INTERPAN MODE] Cannot execute non-InterPAN commands.`, NS);
|
|
2989
2352
|
// will be caught by request queue and rejected internally.
|
|
2990
|
-
throw new
|
|
2353
|
+
throw new ezspError_1.EzspError(enums_2.EzspStatus.ERROR_INVALID_CALL);
|
|
2991
2354
|
}
|
|
2992
2355
|
}
|
|
2993
2356
|
}
|