zigbee-herdsman 6.0.2 → 6.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +12 -3
- package/.github/ISSUE_TEMPLATE/config.yml +0 -5
- package/.github/dependabot.yml +0 -22
- package/.github/workflows/ci.yml +0 -69
- package/.github/workflows/release-please.yml +0 -18
- package/.github/workflows/stale.yml +0 -20
- package/.github/workflows/typedoc.yaml +0 -47
- package/.release-please-manifest.json +0 -3
- package/.vscode/extensions.json +0 -3
- package/.vscode/settings.json +0 -11
- package/biome.json +0 -98
- package/examples/join-and-log.js +0 -24
- package/release-please-config.json +0 -9
- package/src/adapter/adapter.ts +0 -189
- package/src/adapter/adapterDiscovery.ts +0 -666
- package/src/adapter/const.ts +0 -12
- package/src/adapter/deconz/adapter/deconzAdapter.ts +0 -877
- package/src/adapter/deconz/driver/constants.ts +0 -246
- package/src/adapter/deconz/driver/driver.ts +0 -1540
- package/src/adapter/deconz/driver/frame.ts +0 -11
- package/src/adapter/deconz/driver/frameParser.ts +0 -753
- package/src/adapter/deconz/driver/parser.ts +0 -45
- package/src/adapter/deconz/driver/writer.ts +0 -22
- package/src/adapter/deconz/types.d.ts +0 -13
- package/src/adapter/ember/adapter/emberAdapter.ts +0 -2265
- package/src/adapter/ember/adapter/endpoints.ts +0 -86
- package/src/adapter/ember/adapter/oneWaitress.ts +0 -324
- package/src/adapter/ember/adapter/tokensManager.ts +0 -782
- package/src/adapter/ember/consts.ts +0 -178
- package/src/adapter/ember/enums.ts +0 -1746
- package/src/adapter/ember/ezsp/buffalo.ts +0 -1392
- package/src/adapter/ember/ezsp/consts.ts +0 -148
- package/src/adapter/ember/ezsp/enums.ts +0 -1114
- package/src/adapter/ember/ezsp/ezsp.ts +0 -9061
- package/src/adapter/ember/ezspError.ts +0 -10
- package/src/adapter/ember/types.ts +0 -866
- package/src/adapter/ember/uart/ash.ts +0 -1960
- package/src/adapter/ember/uart/consts.ts +0 -109
- package/src/adapter/ember/uart/enums.ts +0 -192
- package/src/adapter/ember/uart/parser.ts +0 -48
- package/src/adapter/ember/uart/queues.ts +0 -247
- package/src/adapter/ember/uart/writer.ts +0 -53
- package/src/adapter/ember/utils/initters.ts +0 -58
- package/src/adapter/ember/utils/math.ts +0 -73
- package/src/adapter/events.ts +0 -21
- package/src/adapter/ezsp/adapter/backup.ts +0 -109
- package/src/adapter/ezsp/adapter/ezspAdapter.ts +0 -614
- package/src/adapter/ezsp/driver/commands.ts +0 -2497
- package/src/adapter/ezsp/driver/consts.ts +0 -11
- package/src/adapter/ezsp/driver/driver.ts +0 -1002
- package/src/adapter/ezsp/driver/ezsp.ts +0 -802
- package/src/adapter/ezsp/driver/frame.ts +0 -101
- package/src/adapter/ezsp/driver/index.ts +0 -4
- package/src/adapter/ezsp/driver/multicast.ts +0 -78
- package/src/adapter/ezsp/driver/parser.ts +0 -81
- package/src/adapter/ezsp/driver/types/basic.ts +0 -201
- package/src/adapter/ezsp/driver/types/index.ts +0 -239
- package/src/adapter/ezsp/driver/types/named.ts +0 -2330
- package/src/adapter/ezsp/driver/types/struct.ts +0 -844
- package/src/adapter/ezsp/driver/uart.ts +0 -460
- package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +0 -44
- package/src/adapter/ezsp/driver/utils/index.ts +0 -32
- package/src/adapter/ezsp/driver/writer.ts +0 -64
- package/src/adapter/index.ts +0 -3
- package/src/adapter/serialPort.ts +0 -58
- package/src/adapter/socketPortUtils.ts +0 -16
- package/src/adapter/tstype.ts +0 -78
- package/src/adapter/z-stack/adapter/adapter-backup.ts +0 -519
- package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +0 -457
- package/src/adapter/z-stack/adapter/endpoints.ts +0 -57
- package/src/adapter/z-stack/adapter/manager.ts +0 -543
- package/src/adapter/z-stack/adapter/tstype.ts +0 -6
- package/src/adapter/z-stack/adapter/zStackAdapter.ts +0 -1190
- package/src/adapter/z-stack/constants/af.ts +0 -27
- package/src/adapter/z-stack/constants/common.ts +0 -285
- package/src/adapter/z-stack/constants/dbg.ts +0 -23
- package/src/adapter/z-stack/constants/index.ts +0 -11
- package/src/adapter/z-stack/constants/mac.ts +0 -128
- package/src/adapter/z-stack/constants/sapi.ts +0 -25
- package/src/adapter/z-stack/constants/sys.ts +0 -72
- package/src/adapter/z-stack/constants/util.ts +0 -82
- package/src/adapter/z-stack/constants/utils.ts +0 -14
- package/src/adapter/z-stack/constants/zdo.ts +0 -103
- package/src/adapter/z-stack/models/startup-options.ts +0 -13
- package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +0 -44
- package/src/adapter/z-stack/structs/entries/address-manager-table.ts +0 -19
- package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +0 -12
- package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +0 -21
- package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +0 -19
- package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +0 -21
- package/src/adapter/z-stack/structs/entries/channel-list.ts +0 -8
- package/src/adapter/z-stack/structs/entries/has-configured.ts +0 -16
- package/src/adapter/z-stack/structs/entries/index.ts +0 -16
- package/src/adapter/z-stack/structs/entries/nib.ts +0 -66
- package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +0 -15
- package/src/adapter/z-stack/structs/entries/nwk-key.ts +0 -13
- package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +0 -8
- package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +0 -20
- package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +0 -19
- package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +0 -33
- package/src/adapter/z-stack/structs/entries/security-manager-table.ts +0 -22
- package/src/adapter/z-stack/structs/index.ts +0 -4
- package/src/adapter/z-stack/structs/serializable-memory-object.ts +0 -14
- package/src/adapter/z-stack/structs/struct.ts +0 -367
- package/src/adapter/z-stack/structs/table.ts +0 -198
- package/src/adapter/z-stack/unpi/constants.ts +0 -33
- package/src/adapter/z-stack/unpi/frame.ts +0 -62
- package/src/adapter/z-stack/unpi/index.ts +0 -4
- package/src/adapter/z-stack/unpi/parser.ts +0 -56
- package/src/adapter/z-stack/unpi/writer.ts +0 -21
- package/src/adapter/z-stack/utils/channel-list.ts +0 -40
- package/src/adapter/z-stack/utils/index.ts +0 -2
- package/src/adapter/z-stack/utils/network-options.ts +0 -26
- package/src/adapter/z-stack/znp/buffaloZnp.ts +0 -175
- package/src/adapter/z-stack/znp/definition.ts +0 -2713
- package/src/adapter/z-stack/znp/index.ts +0 -2
- package/src/adapter/z-stack/znp/parameterType.ts +0 -22
- package/src/adapter/z-stack/znp/tstype.ts +0 -44
- package/src/adapter/z-stack/znp/utils.ts +0 -10
- package/src/adapter/z-stack/znp/znp.ts +0 -342
- package/src/adapter/z-stack/znp/zpiObject.ts +0 -148
- package/src/adapter/zboss/adapter/zbossAdapter.ts +0 -526
- package/src/adapter/zboss/commands.ts +0 -1184
- package/src/adapter/zboss/consts.ts +0 -9
- package/src/adapter/zboss/driver.ts +0 -422
- package/src/adapter/zboss/enums.ts +0 -360
- package/src/adapter/zboss/frame.ts +0 -227
- package/src/adapter/zboss/reader.ts +0 -65
- package/src/adapter/zboss/types.ts +0 -0
- package/src/adapter/zboss/uart.ts +0 -428
- package/src/adapter/zboss/utils.ts +0 -58
- package/src/adapter/zboss/writer.ts +0 -49
- package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +0 -27
- package/src/adapter/zigate/adapter/zigateAdapter.ts +0 -618
- package/src/adapter/zigate/driver/LICENSE +0 -17
- package/src/adapter/zigate/driver/buffaloZiGate.ts +0 -212
- package/src/adapter/zigate/driver/commandType.ts +0 -418
- package/src/adapter/zigate/driver/constants.ts +0 -150
- package/src/adapter/zigate/driver/frame.ts +0 -197
- package/src/adapter/zigate/driver/messageType.ts +0 -287
- package/src/adapter/zigate/driver/parameterType.ts +0 -32
- package/src/adapter/zigate/driver/ziGateObject.ts +0 -146
- package/src/adapter/zigate/driver/zigate.ts +0 -423
- package/src/adapter/zoh/adapter/utils.ts +0 -27
- package/src/adapter/zoh/adapter/zohAdapter.ts +0 -838
- package/src/buffalo/buffalo.ts +0 -342
- package/src/buffalo/index.ts +0 -1
- package/src/controller/controller.ts +0 -1022
- package/src/controller/database.ts +0 -124
- package/src/controller/events.ts +0 -52
- package/src/controller/greenPower.ts +0 -603
- package/src/controller/helpers/index.ts +0 -1
- package/src/controller/helpers/installCodes.ts +0 -107
- package/src/controller/helpers/request.ts +0 -96
- package/src/controller/helpers/requestQueue.ts +0 -125
- package/src/controller/helpers/zclFrameConverter.ts +0 -47
- package/src/controller/helpers/zclTransactionSequenceNumber.ts +0 -19
- package/src/controller/index.ts +0 -6
- package/src/controller/model/device.ts +0 -1249
- package/src/controller/model/endpoint.ts +0 -1105
- package/src/controller/model/entity.ts +0 -23
- package/src/controller/model/group.ts +0 -424
- package/src/controller/model/index.ts +0 -5
- package/src/controller/model/zigbeeEntity.ts +0 -30
- package/src/controller/touchlink.ts +0 -189
- package/src/controller/tstype.ts +0 -274
- package/src/index.ts +0 -12
- package/src/models/backup-storage-legacy.ts +0 -48
- package/src/models/backup-storage-unified.ts +0 -47
- package/src/models/backup.ts +0 -37
- package/src/models/index.ts +0 -5
- package/src/models/network-options.ts +0 -11
- package/src/utils/backup.ts +0 -152
- package/src/utils/index.ts +0 -5
- package/src/utils/logger.ts +0 -20
- package/src/utils/patchBigIntSerialization.ts +0 -8
- package/src/utils/queue.ts +0 -76
- package/src/utils/types.d.ts +0 -3
- package/src/utils/utils.ts +0 -19
- package/src/utils/wait.ts +0 -5
- package/src/utils/waitress.ts +0 -96
- package/src/zspec/consts.ts +0 -84
- package/src/zspec/enums.ts +0 -22
- package/src/zspec/index.ts +0 -3
- package/src/zspec/tstypes.ts +0 -18
- package/src/zspec/utils.ts +0 -247
- package/src/zspec/zcl/buffaloZcl.ts +0 -1220
- package/src/zspec/zcl/definition/cluster.ts +0 -5915
- package/src/zspec/zcl/definition/clusters-typegen.ts +0 -588
- package/src/zspec/zcl/definition/clusters-types.ts +0 -7331
- package/src/zspec/zcl/definition/consts.ts +0 -24
- package/src/zspec/zcl/definition/enums.ts +0 -203
- package/src/zspec/zcl/definition/foundation.ts +0 -329
- package/src/zspec/zcl/definition/manufacturerCode.ts +0 -729
- package/src/zspec/zcl/definition/status.ts +0 -69
- package/src/zspec/zcl/definition/tstype.ts +0 -377
- package/src/zspec/zcl/index.ts +0 -11
- package/src/zspec/zcl/utils.ts +0 -321
- package/src/zspec/zcl/zclFrame.ts +0 -356
- package/src/zspec/zcl/zclHeader.ts +0 -102
- package/src/zspec/zcl/zclStatusError.ts +0 -10
- package/src/zspec/zdo/buffaloZdo.ts +0 -2336
- package/src/zspec/zdo/definition/clusters.ts +0 -722
- package/src/zspec/zdo/definition/consts.ts +0 -16
- package/src/zspec/zdo/definition/enums.ts +0 -99
- package/src/zspec/zdo/definition/status.ts +0 -105
- package/src/zspec/zdo/definition/tstypes.ts +0 -1062
- package/src/zspec/zdo/index.ts +0 -7
- package/src/zspec/zdo/utils.ts +0 -76
- package/src/zspec/zdo/zdoStatusError.ts +0 -10
- package/test/adapter/adapter.test.ts +0 -1062
- package/test/adapter/ember/ash.test.ts +0 -337
- package/test/adapter/ember/consts.ts +0 -131
- package/test/adapter/ember/emberAdapter.test.ts +0 -3449
- package/test/adapter/ember/ezsp.test.ts +0 -385
- package/test/adapter/ember/ezspBuffalo.test.ts +0 -93
- package/test/adapter/ember/ezspError.test.ts +0 -12
- package/test/adapter/ember/math.test.ts +0 -206
- package/test/adapter/ezsp/frame.test.ts +0 -30
- package/test/adapter/ezsp/uart.test.ts +0 -181
- package/test/adapter/z-stack/adapter.test.ts +0 -3984
- package/test/adapter/z-stack/constants.test.ts +0 -33
- package/test/adapter/z-stack/structs.test.ts +0 -115
- package/test/adapter/z-stack/unpi.test.ts +0 -213
- package/test/adapter/z-stack/znp.test.ts +0 -1284
- package/test/adapter/zboss/fixZdoResponse.test.ts +0 -179
- package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +0 -81
- package/test/adapter/zigate/zdo.test.ts +0 -187
- package/test/adapter/zoh/utils.test.ts +0 -36
- package/test/adapter/zoh/zohAdapter.test.ts +0 -1307
- package/test/benchOptions.ts +0 -14
- package/test/buffalo.test.ts +0 -431
- package/test/controller.bench.ts +0 -214
- package/test/controller.test.ts +0 -8702
- package/test/greenpower.test.ts +0 -1408
- package/test/mockAdapters.ts +0 -65
- package/test/mockDevices.ts +0 -598
- package/test/requests.bench.ts +0 -229
- package/test/testUtils.ts +0 -20
- package/test/tsconfig.json +0 -9
- package/test/utils/math.ts +0 -19
- package/test/utils.test.ts +0 -279
- package/test/vitest.config.mts +0 -26
- package/test/zcl.test.ts +0 -2831
- package/test/zspec/utils.test.ts +0 -68
- package/test/zspec/zcl/buffalo.test.ts +0 -1374
- package/test/zspec/zcl/frame.test.ts +0 -960
- package/test/zspec/zcl/utils.test.ts +0 -273
- package/test/zspec/zdo/buffalo.test.ts +0 -1850
- package/test/zspec/zdo/utils.test.ts +0 -241
- package/tsconfig.json +0 -24
|
@@ -1,3984 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import equals from "fast-deep-equal/es6";
|
|
4
|
-
import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
|
5
|
-
import type {ZclPayload} from "../../../src/adapter/events";
|
|
6
|
-
import {ZnpVersion} from "../../../src/adapter/z-stack/adapter/tstype";
|
|
7
|
-
import {ZStackAdapter} from "../../../src/adapter/z-stack/adapter/zStackAdapter";
|
|
8
|
-
import * as Constants from "../../../src/adapter/z-stack/constants";
|
|
9
|
-
import {AddressMode, DevStates, NvItemsIds, NvSystemIds, type ZnpCommandStatus} from "../../../src/adapter/z-stack/constants/common";
|
|
10
|
-
import * as Structs from "../../../src/adapter/z-stack/structs";
|
|
11
|
-
import {Subsystem, Type} from "../../../src/adapter/z-stack/unpi/constants";
|
|
12
|
-
import {Znp, type ZpiObject} from "../../../src/adapter/z-stack/znp";
|
|
13
|
-
import Definition from "../../../src/adapter/z-stack/znp/definition";
|
|
14
|
-
import type {ZpiObjectPayload} from "../../../src/adapter/z-stack/znp/tstype";
|
|
15
|
-
import type {UnifiedBackupStorage} from "../../../src/models";
|
|
16
|
-
import {setLogger} from "../../../src/utils/logger";
|
|
17
|
-
import * as ZSpec from "../../../src/zspec";
|
|
18
|
-
import {BroadcastAddress} from "../../../src/zspec/enums";
|
|
19
|
-
import * as Zcl from "../../../src/zspec/zcl";
|
|
20
|
-
import * as Zdo from "../../../src/zspec/zdo";
|
|
21
|
-
import type {
|
|
22
|
-
ActiveEndpointsResponse,
|
|
23
|
-
EndDeviceAnnounce,
|
|
24
|
-
LQITableResponse,
|
|
25
|
-
NetworkAddressResponse,
|
|
26
|
-
NodeDescriptorResponse,
|
|
27
|
-
RoutingTableResponse,
|
|
28
|
-
SimpleDescriptorResponse,
|
|
29
|
-
} from "../../../src/zspec/zdo/definition/tstypes";
|
|
30
|
-
|
|
31
|
-
const DUMMY_NODE_DESC_RSP_CAPABILITIES = {
|
|
32
|
-
allocateAddress: 0,
|
|
33
|
-
alternatePANCoordinator: 0,
|
|
34
|
-
deviceType: 2,
|
|
35
|
-
powerSource: 0,
|
|
36
|
-
reserved1: 0,
|
|
37
|
-
reserved2: 0,
|
|
38
|
-
rxOnWhenIdle: 0,
|
|
39
|
-
securityCapability: 0,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const mockLogger = {
|
|
43
|
-
debug: vi.fn(),
|
|
44
|
-
info: vi.fn(),
|
|
45
|
-
warning: vi.fn(),
|
|
46
|
-
error: vi.fn(),
|
|
47
|
-
};
|
|
48
|
-
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
|
|
49
|
-
const mockSetTimeout = () => {
|
|
50
|
-
return vi.spyOn(globalThis, "setTimeout").mockImplementation(
|
|
51
|
-
// @ts-expect-error mock
|
|
52
|
-
(cb) => cb(),
|
|
53
|
-
);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
vi.mock("../../../src/utils/wait", () => ({
|
|
57
|
-
wait: vi.fn(() => {
|
|
58
|
-
return new Promise<void>((resolve) => resolve());
|
|
59
|
-
}),
|
|
60
|
-
}));
|
|
61
|
-
|
|
62
|
-
const waitForResult = (payloadOrPromise: Promise<unknown> | ZpiObjectPayload, id?: number) => {
|
|
63
|
-
id = id || 1;
|
|
64
|
-
if (payloadOrPromise instanceof Promise) {
|
|
65
|
-
return {
|
|
66
|
-
start: () => {
|
|
67
|
-
return {promise: payloadOrPromise, ID: id};
|
|
68
|
-
},
|
|
69
|
-
ID: id,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
start: () => {
|
|
75
|
-
return {promise: new Promise((r) => r(payloadOrPromise)), ID: id};
|
|
76
|
-
},
|
|
77
|
-
ID: id,
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const networkOptions = {
|
|
82
|
-
panID: 123,
|
|
83
|
-
extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
|
|
84
|
-
channelList: [21],
|
|
85
|
-
networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
86
|
-
networkKeyDistribute: false,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const networkOptionsDefaultExtendedPanId = {
|
|
90
|
-
panID: 123,
|
|
91
|
-
extendedPanID: [0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd],
|
|
92
|
-
channelList: [21],
|
|
93
|
-
networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
94
|
-
networkKeyDistribute: false,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const networkOptionsMismatched = {
|
|
98
|
-
panID: 124,
|
|
99
|
-
extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
|
|
100
|
-
channelList: [21],
|
|
101
|
-
networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
102
|
-
networkKeyDistribute: false,
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const networkOptionsInvalidPanId = {
|
|
106
|
-
panID: 65535,
|
|
107
|
-
extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
|
|
108
|
-
channelList: [21],
|
|
109
|
-
networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
110
|
-
networkKeyDistribute: false,
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const serialPortOptions = {
|
|
114
|
-
baudRate: 800,
|
|
115
|
-
rtscts: false,
|
|
116
|
-
path: "dummy",
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const backupMatchingConfig = {
|
|
120
|
-
metadata: {
|
|
121
|
-
format: "zigpy/open-coordinator-backup",
|
|
122
|
-
version: 1,
|
|
123
|
-
source: "zigbee-herdsman@0.13.65",
|
|
124
|
-
internal: {
|
|
125
|
-
date: "2021-03-03T19:15:40.524Z",
|
|
126
|
-
znpVersion: 2,
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
stack_specific: {
|
|
130
|
-
zstack: {
|
|
131
|
-
tclk_seed: "928a2c479e72a9a53e3b5133fc55021f",
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
coordinator_ieee: "00124b0009d80ba7",
|
|
135
|
-
pan_id: "007b",
|
|
136
|
-
extended_pan_id: "00124b0009d69f77",
|
|
137
|
-
nwk_update_id: 0,
|
|
138
|
-
security_level: 5,
|
|
139
|
-
channel: 21,
|
|
140
|
-
channel_mask: [21],
|
|
141
|
-
network_key: {
|
|
142
|
-
key: "01030507090b0d0f00020406080a0c0d",
|
|
143
|
-
sequence_number: 0,
|
|
144
|
-
frame_counter: 16754,
|
|
145
|
-
},
|
|
146
|
-
devices: [
|
|
147
|
-
{
|
|
148
|
-
nwk_address: "ddf6",
|
|
149
|
-
ieee_address: "00124b002226ef87",
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
nwk_address: "c2dc",
|
|
153
|
-
ieee_address: "04cf8cdf3c79455f",
|
|
154
|
-
link_key: {
|
|
155
|
-
key: "0e768569dd935d8e7302e74e7629f13f",
|
|
156
|
-
rx_counter: 0,
|
|
157
|
-
tx_counter: 275,
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
nwk_address: "740a",
|
|
162
|
-
ieee_address: "680ae2fffeae5647",
|
|
163
|
-
link_key: {
|
|
164
|
-
key: "7c079d02aae015facd7ae9608d4baf56",
|
|
165
|
-
rx_counter: 0,
|
|
166
|
-
tx_counter: 275,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
nwk_address: "19fa",
|
|
171
|
-
ieee_address: "00158d00024fa79b",
|
|
172
|
-
link_key: {
|
|
173
|
-
key: "cea550908aa1529ee90eea3c3bdc26fc",
|
|
174
|
-
rx_counter: 0,
|
|
175
|
-
tx_counter: 44,
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
nwk_address: "6182",
|
|
180
|
-
ieee_address: "00158d00024f4518",
|
|
181
|
-
link_key: {
|
|
182
|
-
key: "267e1e31fcd8171f8acf63459effbca5",
|
|
183
|
-
rx_counter: 0,
|
|
184
|
-
tx_counter: 44,
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
nwk_address: "4285",
|
|
189
|
-
ieee_address: "00158d00024f810d",
|
|
190
|
-
is_child: false,
|
|
191
|
-
link_key: {
|
|
192
|
-
key: "55ba1e31fcd8171f9f0b63459effbca5",
|
|
193
|
-
rx_counter: 0,
|
|
194
|
-
tx_counter: 44,
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
// "nwk_address": "4286", commented because `nwk_address` is optional in the backup
|
|
199
|
-
ieee_address: "00158d00024f810e",
|
|
200
|
-
is_child: true,
|
|
201
|
-
link_key: {
|
|
202
|
-
key: "55ba1e31fcd8171fee0b63459effeea5",
|
|
203
|
-
rx_counter: 24,
|
|
204
|
-
tx_counter: 91,
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const backupMatchingConfig12 = {
|
|
211
|
-
metadata: {
|
|
212
|
-
format: "zigpy/open-coordinator-backup",
|
|
213
|
-
version: 1,
|
|
214
|
-
source: "zigbee-herdsman@0.13.65",
|
|
215
|
-
internal: {
|
|
216
|
-
date: "2021-03-03T19:15:40.524Z",
|
|
217
|
-
znpVersion: 0,
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
stack_specific: {
|
|
221
|
-
zstack: {},
|
|
222
|
-
},
|
|
223
|
-
coordinator_ieee: "00124b0009d80ba7",
|
|
224
|
-
pan_id: "007b",
|
|
225
|
-
extended_pan_id: "00124b0009d69f77",
|
|
226
|
-
nwk_update_id: 0,
|
|
227
|
-
security_level: 5,
|
|
228
|
-
channel: 21,
|
|
229
|
-
channel_mask: [21],
|
|
230
|
-
network_key: {
|
|
231
|
-
key: "01030507090b0d0f00020406080a0c0d",
|
|
232
|
-
sequence_number: 0,
|
|
233
|
-
frame_counter: 0,
|
|
234
|
-
},
|
|
235
|
-
devices: [
|
|
236
|
-
{
|
|
237
|
-
nwk_address: "ddf6",
|
|
238
|
-
ieee_address: "00124b002226ef87",
|
|
239
|
-
},
|
|
240
|
-
],
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const backupNotMatchingConfig = {
|
|
244
|
-
metadata: {
|
|
245
|
-
format: "zigpy/open-coordinator-backup",
|
|
246
|
-
version: 1,
|
|
247
|
-
source: "zigbee-herdsman@0.13.65",
|
|
248
|
-
internal: {
|
|
249
|
-
date: "2021-03-03T19:15:40.524Z",
|
|
250
|
-
znpVersion: 2,
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
stack_specific: {
|
|
254
|
-
zstack: {
|
|
255
|
-
tclk_seed: "928a2c479e72a9a53e3b5133fc55021f",
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
coordinator_ieee: "00124b0009d80ba7",
|
|
259
|
-
pan_id: "007c",
|
|
260
|
-
extended_pan_id: "00124b0009d69f77",
|
|
261
|
-
nwk_update_id: 0,
|
|
262
|
-
security_level: 5,
|
|
263
|
-
channel: 21,
|
|
264
|
-
channel_mask: [21],
|
|
265
|
-
network_key: {
|
|
266
|
-
key: "01030507090b0d0f00020406080a0c0d",
|
|
267
|
-
sequence_number: 0,
|
|
268
|
-
frame_counter: 16754,
|
|
269
|
-
},
|
|
270
|
-
devices: [
|
|
271
|
-
{
|
|
272
|
-
nwk_address: "ddf6",
|
|
273
|
-
ieee_address: "00124b002226ef87",
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
nwk_address: "c2dc",
|
|
277
|
-
ieee_address: "04cf8cdf3c79455f",
|
|
278
|
-
link_key: {
|
|
279
|
-
key: "0e768569dd935d8e7302e74e7629f13f",
|
|
280
|
-
rx_counter: 0,
|
|
281
|
-
tx_counter: 275,
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
nwk_address: "740a",
|
|
286
|
-
ieee_address: "680ae2fffeae5647",
|
|
287
|
-
link_key: {
|
|
288
|
-
key: "7c079d02aae015facd7ae9608d4baf56",
|
|
289
|
-
rx_counter: 0,
|
|
290
|
-
tx_counter: 275,
|
|
291
|
-
},
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
nwk_address: "19fa",
|
|
295
|
-
ieee_address: "00158d00024fa79b",
|
|
296
|
-
link_key: {
|
|
297
|
-
key: "cea550908aa1529ee90eea3c3bdc26fc",
|
|
298
|
-
rx_counter: 0,
|
|
299
|
-
tx_counter: 44,
|
|
300
|
-
},
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
nwk_address: "6182",
|
|
304
|
-
ieee_address: "00158d00024f4518",
|
|
305
|
-
link_key: {
|
|
306
|
-
key: "267e1e31fcd8171f8acf63459effbca5",
|
|
307
|
-
rx_counter: 0,
|
|
308
|
-
tx_counter: 44,
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
nwk_address: "4285",
|
|
313
|
-
ieee_address: "00158d00024f810d",
|
|
314
|
-
link_key: {
|
|
315
|
-
key: "55ba1e31fcd8171f9f0b63459effbca5",
|
|
316
|
-
rx_counter: 0,
|
|
317
|
-
tx_counter: 44,
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
],
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const legacyBackup = {
|
|
324
|
-
adapterType: "zStack",
|
|
325
|
-
time: "Thu, 04 Mar 2021 10:55:12 GMT",
|
|
326
|
-
meta: {
|
|
327
|
-
product: 2,
|
|
328
|
-
},
|
|
329
|
-
data: {
|
|
330
|
-
ZCD_NV_EXTADDR: {
|
|
331
|
-
id: 1,
|
|
332
|
-
offset: 0,
|
|
333
|
-
osal: true,
|
|
334
|
-
product: -1,
|
|
335
|
-
value: [167, 11, 216, 9, 0, 75, 18, 0],
|
|
336
|
-
len: 8,
|
|
337
|
-
},
|
|
338
|
-
ZCD_NV_NIB: {
|
|
339
|
-
id: 33,
|
|
340
|
-
offset: 0,
|
|
341
|
-
osal: true,
|
|
342
|
-
product: -1,
|
|
343
|
-
value: [
|
|
344
|
-
145, 5, 2, 16, 20, 16, 0, 20, 0, 0, 0, 1, 5, 1, 143, 7, 0, 2, 5, 30, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 8, 0, 0, 32, 0,
|
|
345
|
-
15, 15, 4, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 119, 159, 214, 9, 0, 75, 18, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
346
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 3, 0, 1, 120, 10, 1, 0, 0, 146, 235, 0,
|
|
347
|
-
],
|
|
348
|
-
len: 110,
|
|
349
|
-
},
|
|
350
|
-
ZCD_NV_PANID: {
|
|
351
|
-
id: 131,
|
|
352
|
-
offset: 0,
|
|
353
|
-
osal: true,
|
|
354
|
-
product: -1,
|
|
355
|
-
value: [123, 0],
|
|
356
|
-
len: 2,
|
|
357
|
-
},
|
|
358
|
-
ZCD_NV_EXTENDED_PAN_ID: {
|
|
359
|
-
id: 45,
|
|
360
|
-
offset: 0,
|
|
361
|
-
osal: true,
|
|
362
|
-
product: -1,
|
|
363
|
-
value: [221, 221, 221, 221, 221, 221, 221, 221],
|
|
364
|
-
len: 8,
|
|
365
|
-
},
|
|
366
|
-
ZCD_NV_NWK_ACTIVE_KEY_INFO: {
|
|
367
|
-
id: 58,
|
|
368
|
-
offset: 0,
|
|
369
|
-
osal: true,
|
|
370
|
-
product: -1,
|
|
371
|
-
value: [0, 1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
372
|
-
len: 17,
|
|
373
|
-
},
|
|
374
|
-
ZCD_NV_NWK_ALTERN_KEY_INFO: {
|
|
375
|
-
id: 59,
|
|
376
|
-
offset: 0,
|
|
377
|
-
osal: true,
|
|
378
|
-
product: -1,
|
|
379
|
-
value: [0, 1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
380
|
-
len: 17,
|
|
381
|
-
},
|
|
382
|
-
ZCD_NV_APS_USE_EXT_PANID: {
|
|
383
|
-
id: 71,
|
|
384
|
-
offset: 0,
|
|
385
|
-
osal: true,
|
|
386
|
-
product: -1,
|
|
387
|
-
value: [0, 0, 0, 0, 0, 0, 0, 0],
|
|
388
|
-
len: 8,
|
|
389
|
-
},
|
|
390
|
-
ZCD_NV_PRECFGKEY: {
|
|
391
|
-
id: 98,
|
|
392
|
-
offset: 0,
|
|
393
|
-
osal: true,
|
|
394
|
-
product: -1,
|
|
395
|
-
value: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
|
|
396
|
-
len: 16,
|
|
397
|
-
},
|
|
398
|
-
ZCD_NV_PRECFGKEY_ENABLE: {
|
|
399
|
-
id: 99,
|
|
400
|
-
offset: 0,
|
|
401
|
-
osal: true,
|
|
402
|
-
product: -1,
|
|
403
|
-
value: [0],
|
|
404
|
-
len: 1,
|
|
405
|
-
},
|
|
406
|
-
ZCD_NV_CHANLIST: {
|
|
407
|
-
id: 132,
|
|
408
|
-
offset: 0,
|
|
409
|
-
osal: true,
|
|
410
|
-
product: -1,
|
|
411
|
-
value: [0, 20, 0, 0],
|
|
412
|
-
len: 4,
|
|
413
|
-
},
|
|
414
|
-
ZCD_NV_LEGACY_TCLK_TABLE_START: {
|
|
415
|
-
id: 273,
|
|
416
|
-
product: 2,
|
|
417
|
-
offset: 0,
|
|
418
|
-
osal: true,
|
|
419
|
-
value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0],
|
|
420
|
-
len: 19,
|
|
421
|
-
},
|
|
422
|
-
ZCD_NV_LEGACY_NWK_SEC_MATERIAL_TABLE_START: {
|
|
423
|
-
id: 117,
|
|
424
|
-
product: 2,
|
|
425
|
-
offset: 0,
|
|
426
|
-
osal: true,
|
|
427
|
-
value: [83, 144, 14, 0, 134, 114, 56, 25, 0, 75, 18, 0],
|
|
428
|
-
len: 12,
|
|
429
|
-
},
|
|
430
|
-
},
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
class ZnpRequestMockBuilder {
|
|
434
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
435
|
-
public responders: {subsystem: Subsystem; command: string; exec: (payload: any, handler?: ZnpRequestMockBuilder) => any}[] = [];
|
|
436
|
-
public nvItems: {id: NvItemsIds; value?: Buffer}[] = [];
|
|
437
|
-
public nvExtendedItems: {sysId: NvSystemIds; id: NvItemsIds; subId: number; value?: Buffer}[] = [];
|
|
438
|
-
|
|
439
|
-
constructor() {
|
|
440
|
-
const handleOsalNvRead = (payload, handler) => {
|
|
441
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
442
|
-
throw new Error("osalNvLength offset not supported");
|
|
443
|
-
}
|
|
444
|
-
const item = handler.nvItems.find((e) => e.id === payload.id);
|
|
445
|
-
return {payload: {status: item?.value ? 0 : 1, value: item?.value ? item.value : undefined}};
|
|
446
|
-
};
|
|
447
|
-
this.handle(Subsystem.SYS, "osalNvRead", handleOsalNvRead);
|
|
448
|
-
this.handle(Subsystem.SYS, "osalNvReadExt", handleOsalNvRead);
|
|
449
|
-
|
|
450
|
-
const handleOsalNvWrite = (payload, handler) => {
|
|
451
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
452
|
-
throw new Error("osalNvLength offset not supported");
|
|
453
|
-
}
|
|
454
|
-
const item = handler.nvItems.find((e) => e.id === payload.id);
|
|
455
|
-
if (item) {
|
|
456
|
-
item.value = payload.value;
|
|
457
|
-
return {payload: {status: 0}};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
return {payload: {status: 1}};
|
|
461
|
-
};
|
|
462
|
-
this.handle(Subsystem.SYS, "osalNvWrite", handleOsalNvWrite);
|
|
463
|
-
this.handle(Subsystem.SYS, "osalNvWriteExt", handleOsalNvWrite);
|
|
464
|
-
|
|
465
|
-
this.handle(Subsystem.SYS, "osalNvItemInit", (payload, handler) => {
|
|
466
|
-
let item = handler.nvItems.find((e) => e.id === payload.id);
|
|
467
|
-
if (item) {
|
|
468
|
-
if (item.value && item.value.length !== payload.len) {
|
|
469
|
-
return {payload: {status: 0x0a}};
|
|
470
|
-
}
|
|
471
|
-
return {payload: {status: 0x00}};
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
item = {
|
|
475
|
-
id: payload.id,
|
|
476
|
-
value: payload.initvalue || null,
|
|
477
|
-
};
|
|
478
|
-
handler.nvItems.push(item);
|
|
479
|
-
return {payload: {status: 0x09}};
|
|
480
|
-
});
|
|
481
|
-
this.handle(Subsystem.SYS, "osalNvLength", (payload, handler) => {
|
|
482
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
483
|
-
throw new Error("osalNvLength offset not supported");
|
|
484
|
-
}
|
|
485
|
-
const item = handler.nvItems.find((e) => e.id === payload.id);
|
|
486
|
-
return {payload: {length: item?.value ? item.value.length : 0}};
|
|
487
|
-
});
|
|
488
|
-
this.handle(Subsystem.SYS, "osalNvDelete", (payload, handler) => {
|
|
489
|
-
const item = handler.nvItems.find((e) => e.id === payload.id);
|
|
490
|
-
if (item) {
|
|
491
|
-
if (item.value && item.value.length !== payload.len) {
|
|
492
|
-
return {payload: {status: 0x0a}};
|
|
493
|
-
}
|
|
494
|
-
const itemIndex = handler.nvItems.indexOf(item);
|
|
495
|
-
handler.nvItems.splice(itemIndex, 1);
|
|
496
|
-
return {payload: {status: 0x00}};
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
return {payload: {status: 0x09}};
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
this.handle(Subsystem.SYS, "nvRead", (payload, handler: ZnpRequestMockBuilder) => {
|
|
503
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
504
|
-
throw new Error("nvRead offset not supported");
|
|
505
|
-
}
|
|
506
|
-
const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
|
|
507
|
-
return {
|
|
508
|
-
payload: {
|
|
509
|
-
status: item?.value ? 0 : 1,
|
|
510
|
-
value: item?.value ? item.value : undefined,
|
|
511
|
-
len: item?.value?.length || undefined,
|
|
512
|
-
},
|
|
513
|
-
};
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
this.handle(Subsystem.SYS, "nvWrite", (payload, handler: ZnpRequestMockBuilder) => {
|
|
517
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
518
|
-
throw new Error("nwWrite offset not supported");
|
|
519
|
-
}
|
|
520
|
-
const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
|
|
521
|
-
if (item) {
|
|
522
|
-
item.value = payload.value;
|
|
523
|
-
return {payload: {status: 0}};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return {payload: {status: 1}};
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
this.handle(Subsystem.SYS, "nvCreate", (payload, handler: ZnpRequestMockBuilder) => {
|
|
530
|
-
let item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
|
|
531
|
-
if (item) {
|
|
532
|
-
if (item.value && item.value.length !== payload.len) {
|
|
533
|
-
return {payload: {status: 0x0a}};
|
|
534
|
-
}
|
|
535
|
-
return {payload: {status: 0x00}};
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
item = {
|
|
539
|
-
sysId: payload.sysid,
|
|
540
|
-
id: payload.itemid,
|
|
541
|
-
subId: payload.subid,
|
|
542
|
-
value: null,
|
|
543
|
-
};
|
|
544
|
-
handler.nvExtendedItems.push(item);
|
|
545
|
-
return {payload: {status: 0x09}};
|
|
546
|
-
});
|
|
547
|
-
this.handle(Subsystem.SYS, "nvLength", (payload, handler) => {
|
|
548
|
-
if (payload.offset !== undefined && payload.offset !== 0) {
|
|
549
|
-
throw new Error("nvLength offset not supported");
|
|
550
|
-
}
|
|
551
|
-
const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
|
|
552
|
-
return {payload: {len: item?.value ? item.value.length : 0}};
|
|
553
|
-
});
|
|
554
|
-
this.handle(Subsystem.SYS, "nvDelete", (payload, handler) => {
|
|
555
|
-
const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
|
|
556
|
-
if (item) {
|
|
557
|
-
if (item.value && item.value.length !== payload.len) {
|
|
558
|
-
return {payload: {status: 0x0a}};
|
|
559
|
-
}
|
|
560
|
-
const itemIndex = handler.nvItems.indexOf(item);
|
|
561
|
-
handler.nvItems.splice(itemIndex, 1);
|
|
562
|
-
return {payload: {status: 0x00}};
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
return {payload: {status: 0x09}};
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
570
|
-
public handle(subsystem: Subsystem, command: string, exec?: (payload: any, handler?: ZnpRequestMockBuilder) => any) {
|
|
571
|
-
const index = this.responders.findIndex((r) => r.subsystem === subsystem && r.command === command);
|
|
572
|
-
if (index > -1) {
|
|
573
|
-
this.responders.splice(index, 1);
|
|
574
|
-
}
|
|
575
|
-
this.responders.push({subsystem, command, exec: exec || (() => ({}))});
|
|
576
|
-
return this;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
public nv(id: NvItemsIds, value?: Buffer) {
|
|
580
|
-
const index = this.nvItems.findIndex((e) => e.id === id);
|
|
581
|
-
if (index > -1) {
|
|
582
|
-
this.nvItems.splice(index, 1);
|
|
583
|
-
}
|
|
584
|
-
if (value) {
|
|
585
|
-
this.nvItems.push({id, value: value || null});
|
|
586
|
-
}
|
|
587
|
-
return this;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
public nvExtended(sysId: NvSystemIds, id: NvItemsIds, subId: number, value?: Buffer) {
|
|
591
|
-
const index = this.nvExtendedItems.findIndex((e) => e.sysId === sysId && e.id === id && e.subId === subId);
|
|
592
|
-
if (index > -1) {
|
|
593
|
-
this.nvExtendedItems.splice(index, 1);
|
|
594
|
-
}
|
|
595
|
-
if (value) {
|
|
596
|
-
this.nvExtendedItems.push({sysId, id, subId, value: value || null});
|
|
597
|
-
}
|
|
598
|
-
return this;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
602
|
-
public execute(message: {subsystem: Subsystem; command: string; payload: any}) {
|
|
603
|
-
const responder = this.responders.find((r) => r.subsystem === message.subsystem && r.command === message.command);
|
|
604
|
-
if (!responder) {
|
|
605
|
-
const msg = `Not implemented - ${Subsystem[message.subsystem]} - ${message.command} - ${JSON.stringify(message.payload)}`;
|
|
606
|
-
console.log(msg);
|
|
607
|
-
throw new Error(msg);
|
|
608
|
-
}
|
|
609
|
-
const response = responder.exec(message.payload, this);
|
|
610
|
-
return response;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
public clone(): ZnpRequestMockBuilder {
|
|
614
|
-
const newBuilder = new ZnpRequestMockBuilder();
|
|
615
|
-
newBuilder.responders = this.responders.map((responder) => ({...responder}));
|
|
616
|
-
newBuilder.nvItems = this.nvItems.map((item) => ({...item, value: Buffer.from(item.value)}));
|
|
617
|
-
newBuilder.nvExtendedItems = this.nvExtendedItems.map((item) => ({...item, value: Buffer.from(item.value)}));
|
|
618
|
-
return newBuilder;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
const baseZnpRequestMock = new ZnpRequestMockBuilder()
|
|
623
|
-
.handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack30x, revision: 20201026}} : undefined))
|
|
624
|
-
.handle(Subsystem.SYS, "ping", () => ({}))
|
|
625
|
-
.handle(Subsystem.SYS, "resetReq", () => ({}))
|
|
626
|
-
.handle(Subsystem.SYS, "getExtAddr", () => ({payload: {extaddress: "0x00124b0009d69f77"}}))
|
|
627
|
-
.handle(Subsystem.SYS, "stackTune", () => ({}))
|
|
628
|
-
.handle(Subsystem.ZDO, "extFindGroup", () => ({payload: {status: 0}}))
|
|
629
|
-
.handle(Subsystem.ZDO, "extAddGroup", () => ({payload: {status: 0}}))
|
|
630
|
-
.handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: 0x00, ieeeaddr: "0x00124b0009d80ba7"}}))
|
|
631
|
-
.handle(Subsystem.ZDO, "activeEpReq", () => ({}))
|
|
632
|
-
.handle(Subsystem.ZDO, "simpleDescReq", () => ({}))
|
|
633
|
-
.handle(Subsystem.ZDO, "mgmtPermitJoinReq", () => ({}))
|
|
634
|
-
.handle(Subsystem.ZDO, "nodeDescReq", () => ({}))
|
|
635
|
-
.handle(Subsystem.ZDO, "bindReq", () => ({}))
|
|
636
|
-
.handle(Subsystem.ZDO, "unbindReq", () => ({}))
|
|
637
|
-
.handle(Subsystem.ZDO, "mgmtLeaveReq", () => ({}))
|
|
638
|
-
.handle(Subsystem.ZDO, "mgmtLqiReq", () => ({}))
|
|
639
|
-
.handle(Subsystem.ZDO, "mgmtRtgReq", () => ({}))
|
|
640
|
-
.handle(Subsystem.ZDO, "mgmtNwkUpdateReq", () => ({}))
|
|
641
|
-
.handle(Subsystem.AF, "interPanCtl", () => ({}))
|
|
642
|
-
.handle(Subsystem.ZDO, "extRouteDisc", () => ({}))
|
|
643
|
-
.handle(Subsystem.ZDO, "nwkAddrReq", () => ({}))
|
|
644
|
-
.handle(Subsystem.UTIL, "assocRemove", () => ({payload: {}}))
|
|
645
|
-
.handle(Subsystem.UTIL, "assocGetWithAddress", () => ({payload: {noderelation: assocGetWithAddressNodeRelation}}))
|
|
646
|
-
.handle(Subsystem.UTIL, "assocAdd", () => ({payload: {}}))
|
|
647
|
-
.handle(Subsystem.UTIL, "ledControl", () => ({}))
|
|
648
|
-
.handle(Subsystem.APP_CNF, "bdbAddInstallCode", () => ({}))
|
|
649
|
-
.handle(Subsystem.AF, "register", () => ({}))
|
|
650
|
-
.handle(Subsystem.AF, "dataRequest", () => {
|
|
651
|
-
if (dataRequestCode !== 0) {
|
|
652
|
-
throw new Error(`Data request failed with code '${dataRequestCode}'`);
|
|
653
|
-
}
|
|
654
|
-
return {};
|
|
655
|
-
})
|
|
656
|
-
.handle(Subsystem.AF, "dataRequestExt", () => {
|
|
657
|
-
if (dataRequestExtCode !== 0) {
|
|
658
|
-
throw new Error(`Data request failed with code '${dataRequestExtCode}'`);
|
|
659
|
-
}
|
|
660
|
-
return {};
|
|
661
|
-
})
|
|
662
|
-
.handle(Subsystem.SYS, "resetReq", () => ({}))
|
|
663
|
-
.handle(Subsystem.APP_CNF, "bdbSetChannel", () => ({}))
|
|
664
|
-
.handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
|
|
665
|
-
const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
|
|
666
|
-
if (nibIndex > -1) {
|
|
667
|
-
handler.nvItems.splice(nibIndex, 1);
|
|
668
|
-
}
|
|
669
|
-
handler.nvItems.push({
|
|
670
|
-
id: NvItemsIds.NIB,
|
|
671
|
-
value: Buffer.from(
|
|
672
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
673
|
-
"hex",
|
|
674
|
-
),
|
|
675
|
-
});
|
|
676
|
-
return {};
|
|
677
|
-
})
|
|
678
|
-
.handle(Subsystem.ZDO, "extNwkInfo", (_, handler) => {
|
|
679
|
-
const nib = Structs.nib(handler.nvItems.find((item) => item.id === NvItemsIds.NIB).value);
|
|
680
|
-
return {payload: {panid: nib.nwkPanId, extendedpanid: `0x${nib.extendedPANID.toString("hex")}`, channel: nib.nwkLogicalChannel}};
|
|
681
|
-
})
|
|
682
|
-
.handle(Subsystem.ZDO, "startupFromApp", () => ({}))
|
|
683
|
-
.nv(NvItemsIds.CHANLIST, Buffer.from([0, 8, 0, 0]))
|
|
684
|
-
.nv(NvItemsIds.PRECFGKEY, Buffer.alloc(16, 0))
|
|
685
|
-
.nv(NvItemsIds.PRECFGKEYS_ENABLE, Buffer.from([0]))
|
|
686
|
-
.nv(NvItemsIds.NWKKEY, Buffer.alloc(24, 0))
|
|
687
|
-
.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("000000000000000000000000000000000000", "hex"))
|
|
688
|
-
.nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("000000000000000000000000000000000000", "hex"))
|
|
689
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
|
|
690
|
-
.nv(
|
|
691
|
-
NvItemsIds.NIB,
|
|
692
|
-
Buffer.from(
|
|
693
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000000bcd0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
694
|
-
"hex",
|
|
695
|
-
),
|
|
696
|
-
);
|
|
697
|
-
|
|
698
|
-
const empty3UnalignedRequestMock = baseZnpRequestMock
|
|
699
|
-
.clone()
|
|
700
|
-
.handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
|
|
701
|
-
const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
|
|
702
|
-
if (nibIndex > -1) {
|
|
703
|
-
handler.nvItems.splice(nibIndex, 1);
|
|
704
|
-
}
|
|
705
|
-
handler.nvItems.push({
|
|
706
|
-
id: NvItemsIds.NIB,
|
|
707
|
-
value: Buffer.from(
|
|
708
|
-
"fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
|
|
709
|
-
"hex",
|
|
710
|
-
),
|
|
711
|
-
});
|
|
712
|
-
return {};
|
|
713
|
-
})
|
|
714
|
-
.nv(NvItemsIds.NWKKEY, Buffer.alloc(21, 0))
|
|
715
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
|
|
716
|
-
.nv(
|
|
717
|
-
NvItemsIds.NIB,
|
|
718
|
-
Buffer.from(
|
|
719
|
-
"fb050279147900640000000105018f0700020d1e00001500000000000000000000ffff08000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
|
|
720
|
-
"hex",
|
|
721
|
-
),
|
|
722
|
-
)
|
|
723
|
-
.nv(
|
|
724
|
-
NvItemsIds.ADDRMGR,
|
|
725
|
-
Buffer.from(
|
|
726
|
-
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
727
|
-
"hex",
|
|
728
|
-
),
|
|
729
|
-
)
|
|
730
|
-
.nv(
|
|
731
|
-
NvItemsIds.APS_LINK_KEY_TABLE,
|
|
732
|
-
Buffer.from(
|
|
733
|
-
"0000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000",
|
|
734
|
-
"hex",
|
|
735
|
-
),
|
|
736
|
-
);
|
|
737
|
-
for (let i = 0; i < 4; i++) {
|
|
738
|
-
empty3UnalignedRequestMock.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
|
|
739
|
-
}
|
|
740
|
-
for (let i = 0; i < 16; i++) {
|
|
741
|
-
empty3UnalignedRequestMock.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, Buffer.from("00000000000000000000000000000000000000", "hex"));
|
|
742
|
-
}
|
|
743
|
-
for (let i = 0; i < 16; i++) {
|
|
744
|
-
empty3UnalignedRequestMock.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
const empty3AlignedRequestMock = baseZnpRequestMock
|
|
748
|
-
.clone()
|
|
749
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
|
|
750
|
-
.nv(
|
|
751
|
-
NvItemsIds.NIB,
|
|
752
|
-
Buffer.from(
|
|
753
|
-
"fb050279147900640000000105018f000700020d1e000000150000000000000000000000ffff0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
754
|
-
"hex",
|
|
755
|
-
),
|
|
756
|
-
)
|
|
757
|
-
.nv(
|
|
758
|
-
NvItemsIds.ADDRMGR,
|
|
759
|
-
Buffer.from(
|
|
760
|
-
"00ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff00000000000000000000",
|
|
761
|
-
"hex",
|
|
762
|
-
),
|
|
763
|
-
)
|
|
764
|
-
.nv(
|
|
765
|
-
NvItemsIds.APS_LINK_KEY_TABLE,
|
|
766
|
-
Buffer.from(
|
|
767
|
-
"0000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000",
|
|
768
|
-
"hex",
|
|
769
|
-
),
|
|
770
|
-
);
|
|
771
|
-
for (let i = 0; i < 4; i++) {
|
|
772
|
-
empty3AlignedRequestMock.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
|
|
773
|
-
}
|
|
774
|
-
for (let i = 0; i < 16; i++) {
|
|
775
|
-
empty3AlignedRequestMock.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, Buffer.from("0000000000000000000000000000000000000000", "hex"));
|
|
776
|
-
}
|
|
777
|
-
for (let i = 0; i < 16; i++) {
|
|
778
|
-
empty3AlignedRequestMock.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
const commissioned3AlignedRequestMock = empty3AlignedRequestMock
|
|
782
|
-
.clone()
|
|
783
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x55]))
|
|
784
|
-
.nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
|
|
785
|
-
.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
786
|
-
.nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
787
|
-
.nv(
|
|
788
|
-
NvItemsIds.NIB,
|
|
789
|
-
Buffer.from(
|
|
790
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
791
|
-
"hex",
|
|
792
|
-
),
|
|
793
|
-
)
|
|
794
|
-
.nv(
|
|
795
|
-
NvItemsIds.ADDRMGR,
|
|
796
|
-
Buffer.from(
|
|
797
|
-
"01ff4f3a080000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff00000000000000000000",
|
|
798
|
-
"hex",
|
|
799
|
-
),
|
|
800
|
-
);
|
|
801
|
-
|
|
802
|
-
const commissioned3AlignedConfigMistmachRequestMock = commissioned3AlignedRequestMock
|
|
803
|
-
.clone()
|
|
804
|
-
.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
805
|
-
.nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
806
|
-
.nv(
|
|
807
|
-
NvItemsIds.NIB,
|
|
808
|
-
Buffer.from(
|
|
809
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000007e000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
810
|
-
"hex",
|
|
811
|
-
),
|
|
812
|
-
);
|
|
813
|
-
|
|
814
|
-
const empty3x0AlignedRequestMock = baseZnpRequestMock
|
|
815
|
-
.clone()
|
|
816
|
-
.handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack3x0, revision: 20210430}} : undefined))
|
|
817
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
|
|
818
|
-
.nv(
|
|
819
|
-
NvItemsIds.NIB,
|
|
820
|
-
Buffer.from(
|
|
821
|
-
"fb050279147900640000000105018f000700020d1e000000150000000000000000000000ffff0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
822
|
-
"hex",
|
|
823
|
-
),
|
|
824
|
-
)
|
|
825
|
-
.nv(
|
|
826
|
-
NvItemsIds.APS_LINK_KEY_TABLE,
|
|
827
|
-
Buffer.from(
|
|
828
|
-
"0000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000",
|
|
829
|
-
"hex",
|
|
830
|
-
),
|
|
831
|
-
);
|
|
832
|
-
for (let i = 0; i < 16; i++) {
|
|
833
|
-
empty3x0AlignedRequestMock.nvExtended(NvSystemIds.ZSTACK, NvItemsIds.ZCD_NV_EX_ADDRMGR, i, Buffer.from("00ff00000000000000000000", "hex"));
|
|
834
|
-
}
|
|
835
|
-
for (let i = 0; i < 4; i++) {
|
|
836
|
-
empty3x0AlignedRequestMock.nvExtended(
|
|
837
|
-
NvSystemIds.ZSTACK,
|
|
838
|
-
NvItemsIds.EX_NWK_SEC_MATERIAL_TABLE,
|
|
839
|
-
i,
|
|
840
|
-
Buffer.from("000000000000000000000000", "hex"),
|
|
841
|
-
);
|
|
842
|
-
}
|
|
843
|
-
for (let i = 0; i < 16; i++) {
|
|
844
|
-
empty3x0AlignedRequestMock.nvExtended(
|
|
845
|
-
NvSystemIds.ZSTACK,
|
|
846
|
-
NvItemsIds.EX_TCLK_TABLE,
|
|
847
|
-
i,
|
|
848
|
-
Buffer.from("0000000000000000000000000000000000000000", "hex"),
|
|
849
|
-
);
|
|
850
|
-
}
|
|
851
|
-
for (let i = 0; i < 16; i++) {
|
|
852
|
-
empty3x0AlignedRequestMock.nvExtended(
|
|
853
|
-
NvSystemIds.ZSTACK,
|
|
854
|
-
NvItemsIds.ZCD_NV_EX_APS_KEY_DATA_TABLE,
|
|
855
|
-
i,
|
|
856
|
-
Buffer.from("000000000000000000000000000000000000000000000000", "hex"),
|
|
857
|
-
);
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
const commissioned3x0AlignedRequestMock = empty3x0AlignedRequestMock
|
|
861
|
-
.clone()
|
|
862
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x55]))
|
|
863
|
-
.nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
|
|
864
|
-
.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
865
|
-
.nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
|
|
866
|
-
.nv(
|
|
867
|
-
NvItemsIds.NIB,
|
|
868
|
-
Buffer.from(
|
|
869
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
870
|
-
"hex",
|
|
871
|
-
),
|
|
872
|
-
)
|
|
873
|
-
.nvExtended(NvSystemIds.ZSTACK, NvItemsIds.ZCD_NV_EX_ADDRMGR, 0, Buffer.from("01ff4f3a0800000000000000", "hex"));
|
|
874
|
-
|
|
875
|
-
const empty12UnalignedRequestMock = baseZnpRequestMock
|
|
876
|
-
.clone()
|
|
877
|
-
.handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack12}} : undefined))
|
|
878
|
-
.handle(Subsystem.SAPI, "readConfiguration", (payload, handler) => {
|
|
879
|
-
if (payload.configid !== NvItemsIds.PRECFGKEY) {
|
|
880
|
-
throw new Error("Only pre-configured key should be read/written using SAPI layer");
|
|
881
|
-
}
|
|
882
|
-
const item = handler.nvItems.find((item) => item.id === payload.configid);
|
|
883
|
-
if (item) {
|
|
884
|
-
return {payload: {status: 0, configid: item.id, len: item.value?.length || 0, value: item.value}};
|
|
885
|
-
}
|
|
886
|
-
return {payload: {status: 1}};
|
|
887
|
-
})
|
|
888
|
-
.handle(Subsystem.SAPI, "writeConfiguration", (payload, handler) => {
|
|
889
|
-
if (payload.configid !== NvItemsIds.PRECFGKEY) {
|
|
890
|
-
throw new Error("Only pre-configured key should be read/written using SAPI layer");
|
|
891
|
-
}
|
|
892
|
-
const item = handler.nvItems.find((item) => item.id === payload.configid);
|
|
893
|
-
if (item) {
|
|
894
|
-
item.value = payload.value;
|
|
895
|
-
} else {
|
|
896
|
-
handler.nvItems.push({id: payload.configid, value: payload.value});
|
|
897
|
-
}
|
|
898
|
-
handler.nv(
|
|
899
|
-
NvItemsIds.NIB,
|
|
900
|
-
Buffer.from(
|
|
901
|
-
"fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
|
|
902
|
-
"hex",
|
|
903
|
-
),
|
|
904
|
-
);
|
|
905
|
-
return {payload: {status: 0}};
|
|
906
|
-
})
|
|
907
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1, Buffer.from([0x00]));
|
|
908
|
-
|
|
909
|
-
const commissioned12UnalignedRequestMock = empty12UnalignedRequestMock
|
|
910
|
-
.clone()
|
|
911
|
-
.nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1, Buffer.from([0x55]))
|
|
912
|
-
.nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
|
|
913
|
-
.nv(
|
|
914
|
-
NvItemsIds.NIB,
|
|
915
|
-
Buffer.from(
|
|
916
|
-
"fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
|
|
917
|
-
"hex",
|
|
918
|
-
),
|
|
919
|
-
);
|
|
920
|
-
|
|
921
|
-
const commissioned12UnalignedMismatchRequestMock = commissioned12UnalignedRequestMock
|
|
922
|
-
.clone()
|
|
923
|
-
.nv(NvItemsIds.PRECFGKEY, Buffer.from("aabb0507090b0d0f00020406080a0c0d", "hex"));
|
|
924
|
-
|
|
925
|
-
const mockZnpRequest = vi
|
|
926
|
-
.fn()
|
|
927
|
-
.mockReturnValue(new Promise((resolve) => resolve({payload: {}})))
|
|
928
|
-
.mockImplementation(
|
|
929
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
930
|
-
(subsystem: Subsystem, command: string, payload: any, _expectedStatus: ZnpCommandStatus) =>
|
|
931
|
-
new Promise((resolve) => resolve(baseZnpRequestMock.execute({subsystem, command, payload}))),
|
|
932
|
-
);
|
|
933
|
-
const mockZnpRequestZdo = vi.fn();
|
|
934
|
-
const mockZnpWaitFor = vi.fn();
|
|
935
|
-
const mockZnpOpen = vi.fn();
|
|
936
|
-
const mockZnpClose = vi.fn();
|
|
937
|
-
const mockQueueExecute = vi.fn().mockImplementation(async (func) => await func());
|
|
938
|
-
const mocks = [mockZnpOpen, mockZnpRequest, mockZnpClose];
|
|
939
|
-
|
|
940
|
-
const mockZnpRequestWith = (builder: ZnpRequestMockBuilder) => {
|
|
941
|
-
builder = builder.clone();
|
|
942
|
-
mockZnpRequest.mockImplementation(
|
|
943
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
944
|
-
(subsystem: Subsystem, command: string, payload: any, _expectedStatus: ZnpCommandStatus) =>
|
|
945
|
-
new Promise((resolve) => resolve(builder.execute({subsystem, command, payload}))),
|
|
946
|
-
);
|
|
947
|
-
};
|
|
948
|
-
|
|
949
|
-
const mockZnpWaitForDefault = () => {
|
|
950
|
-
mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
|
|
951
|
-
const missing = () => {
|
|
952
|
-
const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
|
|
953
|
-
console.log(msg);
|
|
954
|
-
throw new Error(msg);
|
|
955
|
-
};
|
|
956
|
-
|
|
957
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
|
|
958
|
-
return waitForResult(
|
|
959
|
-
mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
|
|
960
|
-
Zdo.Status.SUCCESS,
|
|
961
|
-
{
|
|
962
|
-
nwkAddress: 0,
|
|
963
|
-
endpointList: [],
|
|
964
|
-
},
|
|
965
|
-
]),
|
|
966
|
-
);
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtPermitJoinRsp") {
|
|
970
|
-
return waitForResult(mockZdoZpiObject("mgmtPermitJoinRsp", target, [Zdo.Status.SUCCESS, undefined]));
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
|
|
974
|
-
return waitForResult({payload: {state: 9}});
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
missing();
|
|
978
|
-
});
|
|
979
|
-
};
|
|
980
|
-
|
|
981
|
-
const mockZnpWaitForStateChangeIndTimeout = () => {
|
|
982
|
-
mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
|
|
983
|
-
const missing = () => {
|
|
984
|
-
const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
|
|
985
|
-
console.log(msg);
|
|
986
|
-
throw new Error(msg);
|
|
987
|
-
};
|
|
988
|
-
|
|
989
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
|
|
990
|
-
return waitForResult(
|
|
991
|
-
mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
|
|
992
|
-
Zdo.Status.SUCCESS,
|
|
993
|
-
{
|
|
994
|
-
nwkAddress: 0,
|
|
995
|
-
endpointList: [],
|
|
996
|
-
},
|
|
997
|
-
]),
|
|
998
|
-
);
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
missing();
|
|
1006
|
-
});
|
|
1007
|
-
};
|
|
1008
|
-
|
|
1009
|
-
let bindStatusResponse = 0;
|
|
1010
|
-
|
|
1011
|
-
const mockZdoZpiObject = <T>(commandName: string, srcaddr: number | undefined, payload: [Zdo.Status, T | undefined]): ZpiObject => {
|
|
1012
|
-
const subsystem = Subsystem.ZDO;
|
|
1013
|
-
const command = Definition[subsystem].find((c) => c.name === commandName)!;
|
|
1014
|
-
return {
|
|
1015
|
-
type: Type.AREQ,
|
|
1016
|
-
subsystem,
|
|
1017
|
-
command,
|
|
1018
|
-
payload: {srcaddr, zdo: payload},
|
|
1019
|
-
};
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
const mockZpiObject = (type: Type, subsystem: Subsystem, commandName: string, payload: {[s: string]: unknown}) => {
|
|
1023
|
-
const command = Definition[subsystem].find((c) => c.name === commandName);
|
|
1024
|
-
return {type, subsystem, payload, command};
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
const basicMocks = () => {
|
|
1028
|
-
mockZnpRequestWith(commissioned3x0AlignedRequestMock);
|
|
1029
|
-
mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
|
|
1030
|
-
const missing = () => {
|
|
1031
|
-
const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
|
|
1032
|
-
console.log(msg);
|
|
1033
|
-
throw new Error(msg);
|
|
1034
|
-
};
|
|
1035
|
-
|
|
1036
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
|
|
1037
|
-
return waitForResult(
|
|
1038
|
-
mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
|
|
1039
|
-
Zdo.Status.SUCCESS,
|
|
1040
|
-
{
|
|
1041
|
-
nwkAddress: 0,
|
|
1042
|
-
endpointList: [1, 2, 3, 4, 5, 6, 8, 10, 11, 110, 12, 13, 47, 242],
|
|
1043
|
-
},
|
|
1044
|
-
]),
|
|
1045
|
-
);
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
|
|
1049
|
-
return waitForResult({payload: {}});
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtPermitJoinRsp") {
|
|
1053
|
-
return waitForResult(mockZdoZpiObject("mgmtPermitJoinRsp", target, [Zdo.Status.SUCCESS, undefined]));
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "simpleDescRsp") {
|
|
1057
|
-
let responsePayload: SimpleDescriptorResponse;
|
|
1058
|
-
if (simpleDescriptorEndpoint === 1) {
|
|
1059
|
-
responsePayload = {
|
|
1060
|
-
length: 1, // bogus
|
|
1061
|
-
endpoint: 1,
|
|
1062
|
-
profileId: 123,
|
|
1063
|
-
deviceId: 5,
|
|
1064
|
-
inClusterList: [1],
|
|
1065
|
-
outClusterList: [2],
|
|
1066
|
-
nwkAddress: target,
|
|
1067
|
-
deviceVersion: 0,
|
|
1068
|
-
};
|
|
1069
|
-
} else if (simpleDescriptorEndpoint === 99) {
|
|
1070
|
-
responsePayload = {
|
|
1071
|
-
length: 1, // bogus
|
|
1072
|
-
endpoint: 99,
|
|
1073
|
-
profileId: 123,
|
|
1074
|
-
deviceId: 5,
|
|
1075
|
-
inClusterList: [1],
|
|
1076
|
-
outClusterList: [2],
|
|
1077
|
-
nwkAddress: target,
|
|
1078
|
-
deviceVersion: 0,
|
|
1079
|
-
};
|
|
1080
|
-
} else {
|
|
1081
|
-
responsePayload = {
|
|
1082
|
-
length: 1, // bogus
|
|
1083
|
-
endpoint: simpleDescriptorEndpoint,
|
|
1084
|
-
profileId: 124,
|
|
1085
|
-
deviceId: 7,
|
|
1086
|
-
inClusterList: [8],
|
|
1087
|
-
outClusterList: [9],
|
|
1088
|
-
nwkAddress: target,
|
|
1089
|
-
deviceVersion: 0,
|
|
1090
|
-
};
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
return waitForResult(mockZdoZpiObject<SimpleDescriptorResponse>("simpleDescRsp", target, [Zdo.Status.SUCCESS, responsePayload]));
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nodeDescRsp") {
|
|
1097
|
-
if (nodeDescRspErrorOnce) {
|
|
1098
|
-
nodeDescRspErrorOnce = false;
|
|
1099
|
-
return {
|
|
1100
|
-
start: () => {
|
|
1101
|
-
return {
|
|
1102
|
-
promise: new Promise((_resolve, reject) => {
|
|
1103
|
-
reject("timeout after xx");
|
|
1104
|
-
}),
|
|
1105
|
-
};
|
|
1106
|
-
},
|
|
1107
|
-
ID: 89,
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
return waitForResult(
|
|
1112
|
-
mockZdoZpiObject<NodeDescriptorResponse>("nodeDescRsp", target, [
|
|
1113
|
-
Zdo.Status.SUCCESS,
|
|
1114
|
-
{
|
|
1115
|
-
manufacturerCode: target * 2,
|
|
1116
|
-
apsFlags: 0,
|
|
1117
|
-
capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES,
|
|
1118
|
-
deprecated1: 0,
|
|
1119
|
-
fragmentationSupported: true,
|
|
1120
|
-
frequencyBand: 0,
|
|
1121
|
-
logicalType: target - 1,
|
|
1122
|
-
maxBufSize: 0,
|
|
1123
|
-
maxIncTxSize: 0,
|
|
1124
|
-
maxOutTxSize: 0,
|
|
1125
|
-
nwkAddress: target,
|
|
1126
|
-
serverMask: {
|
|
1127
|
-
backupTrustCenter: 0,
|
|
1128
|
-
deprecated1: 0,
|
|
1129
|
-
deprecated2: 0,
|
|
1130
|
-
deprecated3: 0,
|
|
1131
|
-
deprecated4: 0,
|
|
1132
|
-
networkManager: 0,
|
|
1133
|
-
primaryTrustCenter: 0,
|
|
1134
|
-
reserved1: 0,
|
|
1135
|
-
reserved2: 0,
|
|
1136
|
-
stackComplianceRevision: 0,
|
|
1137
|
-
},
|
|
1138
|
-
tlvs: [],
|
|
1139
|
-
},
|
|
1140
|
-
]),
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
if (type === Type.AREQ && subsystem === Subsystem.AF && command === "dataConfirm") {
|
|
1145
|
-
const status = dataConfirmCode;
|
|
1146
|
-
if (dataConfirmCodeReset) {
|
|
1147
|
-
dataConfirmCode = 0;
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
if (status === 9999) {
|
|
1151
|
-
return {
|
|
1152
|
-
start: () => {
|
|
1153
|
-
return {
|
|
1154
|
-
promise: new Promise((_resolve, reject) => {
|
|
1155
|
-
reject("timeout after xx");
|
|
1156
|
-
}),
|
|
1157
|
-
};
|
|
1158
|
-
},
|
|
1159
|
-
ID: 99,
|
|
1160
|
-
};
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
return waitForResult({payload: {status}}, 99);
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLqiRsp" && target === 203) {
|
|
1167
|
-
const defaults = {deviceType: 0, extendedPanId: [0], permitJoining: 0, reserved1: 0, reserved2: 0, rxOnWhenIdle: 0};
|
|
1168
|
-
|
|
1169
|
-
if (lastStartIndex === 0) {
|
|
1170
|
-
lastStartIndex += 2;
|
|
1171
|
-
return waitForResult(
|
|
1172
|
-
mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
|
|
1173
|
-
Zdo.Status.SUCCESS,
|
|
1174
|
-
{
|
|
1175
|
-
neighborTableEntries: 5,
|
|
1176
|
-
startIndex: 0,
|
|
1177
|
-
entryList: [
|
|
1178
|
-
{lqi: 10, nwkAddress: 2, eui64: "0x3", relationship: 3, depth: 1, ...defaults},
|
|
1179
|
-
{lqi: 15, nwkAddress: 3, eui64: "0x4", relationship: 2, depth: 5, ...defaults},
|
|
1180
|
-
],
|
|
1181
|
-
},
|
|
1182
|
-
]),
|
|
1183
|
-
);
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
if (lastStartIndex === 2) {
|
|
1187
|
-
lastStartIndex += 2;
|
|
1188
|
-
return waitForResult(
|
|
1189
|
-
mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
|
|
1190
|
-
Zdo.Status.SUCCESS,
|
|
1191
|
-
{
|
|
1192
|
-
neighborTableEntries: 5,
|
|
1193
|
-
startIndex: 0,
|
|
1194
|
-
entryList: [
|
|
1195
|
-
{lqi: 10, nwkAddress: 5, eui64: "0x6", relationship: 3, depth: 1, ...defaults},
|
|
1196
|
-
{lqi: 15, nwkAddress: 7, eui64: "0x8", relationship: 2, depth: 5, ...defaults},
|
|
1197
|
-
],
|
|
1198
|
-
},
|
|
1199
|
-
]),
|
|
1200
|
-
);
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
if (lastStartIndex === 4) {
|
|
1204
|
-
return waitForResult(
|
|
1205
|
-
mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
|
|
1206
|
-
Zdo.Status.SUCCESS,
|
|
1207
|
-
{
|
|
1208
|
-
neighborTableEntries: 5,
|
|
1209
|
-
startIndex: 0,
|
|
1210
|
-
entryList: [{lqi: 10, nwkAddress: 9, eui64: "0x10", relationship: 3, depth: 1, ...defaults}],
|
|
1211
|
-
},
|
|
1212
|
-
]),
|
|
1213
|
-
);
|
|
1214
|
-
}
|
|
1215
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLqiRsp" && target === 204) {
|
|
1216
|
-
return waitForResult(mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [Zdo.Status.NOT_AUTHORIZED, undefined]));
|
|
1217
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtRtgRsp" && target === 205) {
|
|
1218
|
-
const defaultEntryList = {
|
|
1219
|
-
manyToOne: 0,
|
|
1220
|
-
memoryConstrained: 0,
|
|
1221
|
-
reserved1: 0,
|
|
1222
|
-
routeRecordRequired: 0,
|
|
1223
|
-
status: Zdo.RoutingTableStatus[0] as keyof typeof Zdo.RoutingTableStatus,
|
|
1224
|
-
};
|
|
1225
|
-
if (lastStartIndex === 0) {
|
|
1226
|
-
lastStartIndex += 2;
|
|
1227
|
-
return waitForResult(
|
|
1228
|
-
mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
|
|
1229
|
-
Zdo.Status.SUCCESS,
|
|
1230
|
-
{
|
|
1231
|
-
startIndex: 0,
|
|
1232
|
-
routingTableEntries: 5,
|
|
1233
|
-
entryList: [
|
|
1234
|
-
{destinationAddress: 10, nextHopAddress: 3, ...defaultEntryList},
|
|
1235
|
-
{destinationAddress: 11, nextHopAddress: 3, ...defaultEntryList},
|
|
1236
|
-
],
|
|
1237
|
-
},
|
|
1238
|
-
]),
|
|
1239
|
-
);
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
if (lastStartIndex === 2) {
|
|
1243
|
-
lastStartIndex += 2;
|
|
1244
|
-
return waitForResult(
|
|
1245
|
-
mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
|
|
1246
|
-
Zdo.Status.SUCCESS,
|
|
1247
|
-
{
|
|
1248
|
-
startIndex: 0,
|
|
1249
|
-
routingTableEntries: 5,
|
|
1250
|
-
entryList: [
|
|
1251
|
-
{destinationAddress: 12, nextHopAddress: 3, ...defaultEntryList},
|
|
1252
|
-
{destinationAddress: 13, nextHopAddress: 3, ...defaultEntryList},
|
|
1253
|
-
],
|
|
1254
|
-
},
|
|
1255
|
-
]),
|
|
1256
|
-
);
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
if (lastStartIndex === 4) {
|
|
1260
|
-
return waitForResult(
|
|
1261
|
-
mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
|
|
1262
|
-
Zdo.Status.SUCCESS,
|
|
1263
|
-
{
|
|
1264
|
-
startIndex: 0,
|
|
1265
|
-
routingTableEntries: 5,
|
|
1266
|
-
entryList: [{destinationAddress: 14, nextHopAddress: 3, ...defaultEntryList}],
|
|
1267
|
-
},
|
|
1268
|
-
]),
|
|
1269
|
-
);
|
|
1270
|
-
}
|
|
1271
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtRtgRsp" && target === 206) {
|
|
1272
|
-
return waitForResult(mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [Zdo.Status.INSUFFICIENT_SPACE, undefined]));
|
|
1273
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "bindRsp" && target === 301) {
|
|
1274
|
-
return waitForResult(mockZdoZpiObject("bindRsp", target, [bindStatusResponse, undefined]));
|
|
1275
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "unbindRsp" && target === 301) {
|
|
1276
|
-
return waitForResult(mockZdoZpiObject("unbindRsp", target, [bindStatusResponse, undefined]));
|
|
1277
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLeaveRsp" && target === 401) {
|
|
1278
|
-
return waitForResult(mockZdoZpiObject("mgmtLeaveRsp", target, [Zdo.Status.SUCCESS, undefined]));
|
|
1279
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nwkAddrRsp" && target === "0x03") {
|
|
1280
|
-
return waitForResult(
|
|
1281
|
-
mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", target, [
|
|
1282
|
-
Zdo.Status.SUCCESS,
|
|
1283
|
-
{
|
|
1284
|
-
nwkAddress: 3,
|
|
1285
|
-
eui64: "0x03",
|
|
1286
|
-
assocDevList: [],
|
|
1287
|
-
startIndex: 0,
|
|
1288
|
-
},
|
|
1289
|
-
]),
|
|
1290
|
-
);
|
|
1291
|
-
} else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nwkAddrRsp" && target === "0x02") {
|
|
1292
|
-
return waitForResult(
|
|
1293
|
-
mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", target, [
|
|
1294
|
-
Zdo.Status.SUCCESS,
|
|
1295
|
-
{
|
|
1296
|
-
nwkAddress: 2,
|
|
1297
|
-
eui64: "0x02",
|
|
1298
|
-
assocDevList: [],
|
|
1299
|
-
startIndex: 0,
|
|
1300
|
-
},
|
|
1301
|
-
]),
|
|
1302
|
-
);
|
|
1303
|
-
} else {
|
|
1304
|
-
missing();
|
|
1305
|
-
}
|
|
1306
|
-
});
|
|
1307
|
-
};
|
|
1308
|
-
|
|
1309
|
-
const touchlinkScanRequest = Zcl.Frame.create(
|
|
1310
|
-
Zcl.FrameType.SPECIFIC,
|
|
1311
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
1312
|
-
false,
|
|
1313
|
-
undefined,
|
|
1314
|
-
12,
|
|
1315
|
-
"scanRequest",
|
|
1316
|
-
Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
|
|
1317
|
-
{transactionID: 1, zigbeeInformation: 4, touchlinkInformation: 18},
|
|
1318
|
-
{},
|
|
1319
|
-
);
|
|
1320
|
-
|
|
1321
|
-
const touchlinkScanResponse = Zcl.Frame.create(
|
|
1322
|
-
Zcl.FrameType.SPECIFIC,
|
|
1323
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
1324
|
-
false,
|
|
1325
|
-
undefined,
|
|
1326
|
-
12,
|
|
1327
|
-
"scanResponse",
|
|
1328
|
-
Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
|
|
1329
|
-
{
|
|
1330
|
-
transactionID: 1,
|
|
1331
|
-
rssiCorrection: 10,
|
|
1332
|
-
zigbeeInformation: 5,
|
|
1333
|
-
touchlinkInformation: 6,
|
|
1334
|
-
keyBitmask: 12,
|
|
1335
|
-
responseID: 11,
|
|
1336
|
-
extendedPanID: "0x0017210104d9cd33",
|
|
1337
|
-
networkUpdateID: 1,
|
|
1338
|
-
logicalChannel: 12,
|
|
1339
|
-
panID: 13,
|
|
1340
|
-
networkAddress: 5,
|
|
1341
|
-
numberOfSubDevices: 10,
|
|
1342
|
-
totalGroupIdentifiers: 5,
|
|
1343
|
-
},
|
|
1344
|
-
{},
|
|
1345
|
-
);
|
|
1346
|
-
|
|
1347
|
-
const touchlinkIdentifyRequest = Zcl.Frame.create(
|
|
1348
|
-
Zcl.FrameType.SPECIFIC,
|
|
1349
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
1350
|
-
false,
|
|
1351
|
-
undefined,
|
|
1352
|
-
12,
|
|
1353
|
-
"identifyRequest",
|
|
1354
|
-
Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
|
|
1355
|
-
{transactionID: 1, duration: 65535},
|
|
1356
|
-
{},
|
|
1357
|
-
);
|
|
1358
|
-
|
|
1359
|
-
const getRandomArbitrary = (min, max) => {
|
|
1360
|
-
return Math.random() * (max - min) + min;
|
|
1361
|
-
};
|
|
1362
|
-
|
|
1363
|
-
const getTempFile = () => {
|
|
1364
|
-
const tempPath = path.resolve("temp");
|
|
1365
|
-
if (!fs.existsSync(tempPath)) {
|
|
1366
|
-
fs.mkdirSync(tempPath);
|
|
1367
|
-
}
|
|
1368
|
-
return path.join(tempPath, `temp_${getRandomArbitrary(1, 99999999)}`);
|
|
1369
|
-
};
|
|
1370
|
-
|
|
1371
|
-
let znpReceived;
|
|
1372
|
-
let znpClose;
|
|
1373
|
-
let dataConfirmCode = 0;
|
|
1374
|
-
let dataConfirmCodeReset = false;
|
|
1375
|
-
let nodeDescRspErrorOnce = false;
|
|
1376
|
-
let dataRequestCode = 0;
|
|
1377
|
-
let dataRequestExtCode = 0;
|
|
1378
|
-
let lastStartIndex = 0;
|
|
1379
|
-
let simpleDescriptorEndpoint = 0;
|
|
1380
|
-
let assocGetWithAddressNodeRelation;
|
|
1381
|
-
|
|
1382
|
-
vi.mock("../../../src/adapter/z-stack/znp/znp", () => ({
|
|
1383
|
-
Znp: vi.fn(() => ({
|
|
1384
|
-
on: (event, handler) => {
|
|
1385
|
-
if (event === "received") {
|
|
1386
|
-
znpReceived = handler;
|
|
1387
|
-
} else if (event === "close") {
|
|
1388
|
-
znpClose = handler;
|
|
1389
|
-
}
|
|
1390
|
-
},
|
|
1391
|
-
open: mockZnpOpen,
|
|
1392
|
-
request: mockZnpRequest,
|
|
1393
|
-
requestZdo: mockZnpRequestZdo,
|
|
1394
|
-
requestWithReply: mockZnpRequest,
|
|
1395
|
-
waitFor: mockZnpWaitFor,
|
|
1396
|
-
close: mockZnpClose,
|
|
1397
|
-
})),
|
|
1398
|
-
}));
|
|
1399
|
-
|
|
1400
|
-
vi.mock("../../../src/utils/queue", () => ({
|
|
1401
|
-
Queue: vi.fn(() => ({
|
|
1402
|
-
execute: mockQueueExecute,
|
|
1403
|
-
count: () => 1,
|
|
1404
|
-
})),
|
|
1405
|
-
}));
|
|
1406
|
-
|
|
1407
|
-
const mocksClear = [mockLogger.debug, mockLogger.info, mockLogger.warning, mockLogger.error];
|
|
1408
|
-
|
|
1409
|
-
describe("zstack-adapter", () => {
|
|
1410
|
-
let adapter: ZStackAdapter;
|
|
1411
|
-
|
|
1412
|
-
beforeAll(() => {
|
|
1413
|
-
setLogger(mockLogger);
|
|
1414
|
-
});
|
|
1415
|
-
|
|
1416
|
-
afterAll(() => {
|
|
1417
|
-
vi.useRealTimers();
|
|
1418
|
-
});
|
|
1419
|
-
|
|
1420
|
-
beforeEach(() => {
|
|
1421
|
-
vi.useRealTimers();
|
|
1422
|
-
vi.useFakeTimers();
|
|
1423
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1424
|
-
mockZnpWaitForDefault();
|
|
1425
|
-
for (const m of mocks) m.mockRestore();
|
|
1426
|
-
for (const m of mocksClear) m.mockClear();
|
|
1427
|
-
mockQueueExecute.mockClear();
|
|
1428
|
-
mockZnpWaitFor.mockClear();
|
|
1429
|
-
dataConfirmCode = 0;
|
|
1430
|
-
dataRequestCode = 0;
|
|
1431
|
-
dataRequestExtCode = 0;
|
|
1432
|
-
bindStatusResponse = 0;
|
|
1433
|
-
assocGetWithAddressNodeRelation = 1;
|
|
1434
|
-
networkOptions.networkKeyDistribute = false;
|
|
1435
|
-
dataConfirmCodeReset = false;
|
|
1436
|
-
nodeDescRspErrorOnce = false;
|
|
1437
|
-
lastStartIndex = 0;
|
|
1438
|
-
simpleDescriptorEndpoint = 0;
|
|
1439
|
-
});
|
|
1440
|
-
|
|
1441
|
-
it("should commission network with 3.0.x adapter", async () => {
|
|
1442
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1443
|
-
const result = await adapter.start();
|
|
1444
|
-
expect(result).toBe("reset");
|
|
1445
|
-
});
|
|
1446
|
-
|
|
1447
|
-
it("should commission network with 3.0.x adapter - auto concurrency", async () => {
|
|
1448
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1449
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {});
|
|
1450
|
-
const result = await adapter.start();
|
|
1451
|
-
expect(result).toBe("reset");
|
|
1452
|
-
});
|
|
1453
|
-
|
|
1454
|
-
it("should commission network with 3.x.0 adapter - auto concurrency", async () => {
|
|
1455
|
-
mockZnpRequestWith(empty3x0AlignedRequestMock);
|
|
1456
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {});
|
|
1457
|
-
const result = await adapter.start();
|
|
1458
|
-
expect(result).toBe("reset");
|
|
1459
|
-
});
|
|
1460
|
-
|
|
1461
|
-
it("should commission network with 3.0.x adapter - unaligned 8-bit", async () => {
|
|
1462
|
-
mockZnpRequestWith(empty3UnalignedRequestMock);
|
|
1463
|
-
const result = await adapter.start();
|
|
1464
|
-
expect(result).toBe("reset");
|
|
1465
|
-
});
|
|
1466
|
-
|
|
1467
|
-
it("should commission network with 3.0.x adapter - default extended pan id", async () => {
|
|
1468
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1469
|
-
adapter = new ZStackAdapter(networkOptionsDefaultExtendedPanId, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1470
|
-
const result = await adapter.start();
|
|
1471
|
-
expect(result).toBe("reset");
|
|
1472
|
-
});
|
|
1473
|
-
|
|
1474
|
-
it("should commission with 3.0.x adapter - empty, mismatched config/backup", async () => {
|
|
1475
|
-
const backupFile = getTempFile();
|
|
1476
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupNotMatchingConfig), "utf8");
|
|
1477
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1478
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1479
|
-
const result = await adapter.start();
|
|
1480
|
-
expect(result).toBe("reset");
|
|
1481
|
-
});
|
|
1482
|
-
|
|
1483
|
-
it("should commission with 3.0.x adapter - commissioned, mismatched adapter-config-backup", async () => {
|
|
1484
|
-
const backupFile = getTempFile();
|
|
1485
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupNotMatchingConfig), "utf8");
|
|
1486
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1487
|
-
mockZnpRequestWith(commissioned3AlignedConfigMistmachRequestMock);
|
|
1488
|
-
const result = await adapter.start();
|
|
1489
|
-
expect(result).toBe("reset");
|
|
1490
|
-
});
|
|
1491
|
-
|
|
1492
|
-
it("should fail to commission network with 3.0.x adapter with invalid pan id 65535", async () => {
|
|
1493
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1494
|
-
adapter = new ZStackAdapter(networkOptionsInvalidPanId, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1495
|
-
await expect(adapter.start()).rejects.toThrowError("network commissioning failed - cannot use pan id 65535");
|
|
1496
|
-
});
|
|
1497
|
-
|
|
1498
|
-
it("should fail to commission network with 3.0.x adapter when bdb commissioning times out", async () => {
|
|
1499
|
-
mockZnpWaitForStateChangeIndTimeout();
|
|
1500
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1501
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1502
|
-
await expect(adapter.start()).rejects.toThrowError(
|
|
1503
|
-
"network commissioning timed out - most likely network with the same panId or extendedPanId already exists nearby",
|
|
1504
|
-
);
|
|
1505
|
-
});
|
|
1506
|
-
|
|
1507
|
-
it("should fail to commission network with 3.0.x adapter when nib fails to settle", async () => {
|
|
1508
|
-
mockZnpRequestWith(empty3AlignedRequestMock.clone().handle(Subsystem.APP_CNF, "bdbStartCommissioning", () => ({})));
|
|
1509
|
-
vi.setConfig({testTimeout: 35000});
|
|
1510
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1511
|
-
const promise = adapter.start();
|
|
1512
|
-
await expect(promise).rejects.toThrowError("network commissioning failed - timed out waiting for nib to settle");
|
|
1513
|
-
});
|
|
1514
|
-
|
|
1515
|
-
it("should fail to commission network with 3.0.x adapter when nib reports different pan id", async () => {
|
|
1516
|
-
mockZnpRequestWith(
|
|
1517
|
-
empty3AlignedRequestMock.clone().handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
|
|
1518
|
-
const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
|
|
1519
|
-
if (nibIndex > -1) {
|
|
1520
|
-
handler.nvItems.splice(nibIndex, 1);
|
|
1521
|
-
}
|
|
1522
|
-
handler.nvItems.push({
|
|
1523
|
-
id: NvItemsIds.NIB,
|
|
1524
|
-
value: Buffer.from(
|
|
1525
|
-
"fb050279147900640000000105018f000700020d1e0000001500000000000000000000007c000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
|
|
1526
|
-
"hex",
|
|
1527
|
-
),
|
|
1528
|
-
});
|
|
1529
|
-
return {};
|
|
1530
|
-
}),
|
|
1531
|
-
);
|
|
1532
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1533
|
-
const promise = adapter.start();
|
|
1534
|
-
await expect(promise).rejects.toThrowError("network commissioning failed - panId collision detected (expected=123, actual=124)");
|
|
1535
|
-
});
|
|
1536
|
-
|
|
1537
|
-
it("should start network with 3.0.x adapter", async () => {
|
|
1538
|
-
mockZnpRequestWith(commissioned3AlignedRequestMock);
|
|
1539
|
-
const result = await adapter.start();
|
|
1540
|
-
expect(result).toBe("resumed");
|
|
1541
|
-
});
|
|
1542
|
-
|
|
1543
|
-
it("should restore unified backup with 3.0.x adapter and create backup - empty", async () => {
|
|
1544
|
-
const backupFile = getTempFile();
|
|
1545
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1546
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1547
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1548
|
-
const result = await adapter.start();
|
|
1549
|
-
expect(result).toBe("restored");
|
|
1550
|
-
|
|
1551
|
-
await adapter.backup([]);
|
|
1552
|
-
});
|
|
1553
|
-
|
|
1554
|
-
it("should restore unified backup with 3.0.x adapter and create backup - no tclk seed", async () => {
|
|
1555
|
-
const backupFile = getTempFile();
|
|
1556
|
-
const backup = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1557
|
-
delete backup.stack_specific.zstack;
|
|
1558
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1559
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1560
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1561
|
-
const result = await adapter.start();
|
|
1562
|
-
expect(result).toBe("restored");
|
|
1563
|
-
|
|
1564
|
-
await adapter.backup([]);
|
|
1565
|
-
});
|
|
1566
|
-
|
|
1567
|
-
it("should restore unified backup with 3.x.0 adapter and create backup - empty", async () => {
|
|
1568
|
-
const backupFile = getTempFile();
|
|
1569
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1570
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1571
|
-
mockZnpRequestWith(empty3x0AlignedRequestMock);
|
|
1572
|
-
const result = await adapter.start();
|
|
1573
|
-
expect(result).toBe("restored");
|
|
1574
|
-
|
|
1575
|
-
await adapter.backup([]);
|
|
1576
|
-
});
|
|
1577
|
-
|
|
1578
|
-
it("should (recommission) restore unified backup with 1.2 adapter and create backup - empty", async () => {
|
|
1579
|
-
const backupFile = getTempFile();
|
|
1580
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig12), "utf8");
|
|
1581
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 1});
|
|
1582
|
-
mockZnpRequestWith(empty12UnalignedRequestMock);
|
|
1583
|
-
const result = await adapter.start();
|
|
1584
|
-
expect(result).toBe("restored");
|
|
1585
|
-
|
|
1586
|
-
const backup = await adapter.backup([]);
|
|
1587
|
-
expect(backup.networkKeyInfo.frameCounter).toBe(0);
|
|
1588
|
-
});
|
|
1589
|
-
|
|
1590
|
-
it("should create backup with 3.0.x adapter - default security material table entry", async () => {
|
|
1591
|
-
const builder = commissioned3AlignedRequestMock.clone();
|
|
1592
|
-
mockZnpRequestWith(builder);
|
|
1593
|
-
const result = await adapter.start();
|
|
1594
|
-
expect(result).toBe("resumed");
|
|
1595
|
-
for (let i = 0; i < 4; i++) {
|
|
1596
|
-
builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
const secMaterialTableEntry = Structs.nwkSecMaterialDescriptorEntry();
|
|
1600
|
-
secMaterialTableEntry.extendedPanID = Buffer.alloc(8, 0xff);
|
|
1601
|
-
secMaterialTableEntry.FrameCounter = 2800;
|
|
1602
|
-
builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + 0, secMaterialTableEntry.serialize("aligned"));
|
|
1603
|
-
mockZnpRequestWith(builder);
|
|
1604
|
-
|
|
1605
|
-
const backup = await adapter.backup([]);
|
|
1606
|
-
expect(backup.networkKeyInfo.frameCounter).toBe(2800);
|
|
1607
|
-
});
|
|
1608
|
-
|
|
1609
|
-
it("should create backup with 3.0.x adapter - emnpty security material table", async () => {
|
|
1610
|
-
const builder = commissioned3AlignedRequestMock.clone();
|
|
1611
|
-
mockZnpRequestWith(builder);
|
|
1612
|
-
const result = await adapter.start();
|
|
1613
|
-
expect(result).toBe("resumed");
|
|
1614
|
-
for (let i = 0; i < 4; i++) {
|
|
1615
|
-
builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
|
|
1616
|
-
}
|
|
1617
|
-
mockZnpRequestWith(builder);
|
|
1618
|
-
|
|
1619
|
-
const backup = await adapter.backup([]);
|
|
1620
|
-
expect(backup.networkKeyInfo.frameCounter).toBe(1250);
|
|
1621
|
-
});
|
|
1622
|
-
|
|
1623
|
-
it("should create backup with 3.0.x adapter - security material table with generic record", async () => {
|
|
1624
|
-
const builder = commissioned3AlignedRequestMock.clone();
|
|
1625
|
-
mockZnpRequestWith(builder);
|
|
1626
|
-
const result = await adapter.start();
|
|
1627
|
-
expect(result).toBe("resumed");
|
|
1628
|
-
for (let i = 0; i < 4; i++) {
|
|
1629
|
-
builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
|
|
1630
|
-
}
|
|
1631
|
-
const genericEntry = Structs.nwkSecMaterialDescriptorEntry();
|
|
1632
|
-
genericEntry.extendedPanID = Buffer.from("ffffffffffffffff", "hex");
|
|
1633
|
-
genericEntry.FrameCounter = 8737;
|
|
1634
|
-
builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + 3, genericEntry.serialize("aligned"));
|
|
1635
|
-
mockZnpRequestWith(builder);
|
|
1636
|
-
|
|
1637
|
-
const backup = await adapter.backup([]);
|
|
1638
|
-
expect(backup.networkKeyInfo.frameCounter).toBe(8737);
|
|
1639
|
-
});
|
|
1640
|
-
|
|
1641
|
-
it("should create backup with 1.2 adapter", async () => {
|
|
1642
|
-
mockZnpRequestWith(commissioned12UnalignedRequestMock);
|
|
1643
|
-
const result = await adapter.start();
|
|
1644
|
-
expect(result).toBe("resumed");
|
|
1645
|
-
|
|
1646
|
-
const backup = await adapter.backup([]);
|
|
1647
|
-
expect(backup.networkKeyInfo.frameCounter).toBe(0);
|
|
1648
|
-
});
|
|
1649
|
-
|
|
1650
|
-
it("should keep missing devices in backup", async () => {
|
|
1651
|
-
const backupFile = getTempFile();
|
|
1652
|
-
const backupWithMissingDevice = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1653
|
-
backupWithMissingDevice.devices.push({
|
|
1654
|
-
nwk_address: "20fa",
|
|
1655
|
-
ieee_address: "00128d11124fa80b",
|
|
1656
|
-
link_key: {
|
|
1657
|
-
key: "bff550908aa1529ee90eea3c3bdc26fc",
|
|
1658
|
-
rx_counter: 0,
|
|
1659
|
-
tx_counter: 2,
|
|
1660
|
-
},
|
|
1661
|
-
});
|
|
1662
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1663
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1664
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1665
|
-
await adapter.start();
|
|
1666
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupWithMissingDevice), "utf8");
|
|
1667
|
-
const devicesInDatabase = backupWithMissingDevice.devices.map((d) => ZSpec.Utils.eui64BEBufferToHex(d.ieee_address));
|
|
1668
|
-
const backup = await adapter.backup(devicesInDatabase);
|
|
1669
|
-
const missingDevice = backup.devices.find((d) => d.ieeeAddress.toString("hex") === "00128d11124fa80b");
|
|
1670
|
-
expect(missingDevice).not.toBeNull();
|
|
1671
|
-
expect(backupWithMissingDevice.devices.length).toBe(backup.devices.length);
|
|
1672
|
-
expect(missingDevice?.linkKey?.key.toString("hex")).toBe("bff550908aa1529ee90eea3c3bdc26fc");
|
|
1673
|
-
});
|
|
1674
|
-
|
|
1675
|
-
it("should fail when backup file is corrupted - Coordinator backup is corrupted", async () => {
|
|
1676
|
-
const backupFile = getTempFile();
|
|
1677
|
-
fs.writeFileSync(backupFile, "{", "utf8");
|
|
1678
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1679
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1680
|
-
await expect(adapter.start()).rejects.toThrowError("Coordinator backup is corrupted");
|
|
1681
|
-
});
|
|
1682
|
-
|
|
1683
|
-
it("should fail to restore unified backup with 3.0.x adapter - invalid open coordinator backup version", async () => {
|
|
1684
|
-
const backupFile = getTempFile();
|
|
1685
|
-
let backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1686
|
-
backupData = {
|
|
1687
|
-
...backupData,
|
|
1688
|
-
metadata: {
|
|
1689
|
-
...backupData.metadata,
|
|
1690
|
-
// biome-ignore lint/suspicious/noExplicitAny: mock
|
|
1691
|
-
version: 99 as any,
|
|
1692
|
-
},
|
|
1693
|
-
};
|
|
1694
|
-
|
|
1695
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1696
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1697
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1698
|
-
await expect(adapter.start()).rejects.toThrowError("Unsupported open coordinator backup version (version=99)");
|
|
1699
|
-
});
|
|
1700
|
-
|
|
1701
|
-
it("should fail to restore (unified) backup with 3.0.x adapter - unsupported backup format", async () => {
|
|
1702
|
-
const backupFile = getTempFile();
|
|
1703
|
-
let backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1704
|
-
backupData = {
|
|
1705
|
-
...backupData,
|
|
1706
|
-
metadata: {
|
|
1707
|
-
...backupData.metadata,
|
|
1708
|
-
version: undefined,
|
|
1709
|
-
},
|
|
1710
|
-
};
|
|
1711
|
-
|
|
1712
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1713
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1714
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1715
|
-
await expect(adapter.start()).rejects.toThrowError("Unknown backup format");
|
|
1716
|
-
});
|
|
1717
|
-
|
|
1718
|
-
it("should fail to restore unified backup with 3.0.x adapter - insufficient tclk table size", async () => {
|
|
1719
|
-
const backupFile = getTempFile();
|
|
1720
|
-
const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1721
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1722
|
-
|
|
1723
|
-
const builder = empty3AlignedRequestMock.clone();
|
|
1724
|
-
for (let i = 0; i < 16; i++) {
|
|
1725
|
-
builder.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, null);
|
|
1726
|
-
}
|
|
1727
|
-
builder.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + 0, Buffer.from("0000000000000000000000000000000000000000", "hex"));
|
|
1728
|
-
mockZnpRequestWith(builder);
|
|
1729
|
-
|
|
1730
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1731
|
-
await expect(adapter.start()).rejects.toThrowError("target adapter tclk table size insufficient (size=1)");
|
|
1732
|
-
});
|
|
1733
|
-
|
|
1734
|
-
it("should fail to restore unified backup with 3.0.x adapter - insufficient aps link key data table size", async () => {
|
|
1735
|
-
const backupFile = getTempFile();
|
|
1736
|
-
const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1737
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1738
|
-
|
|
1739
|
-
const builder = empty3AlignedRequestMock.clone();
|
|
1740
|
-
for (let i = 0; i < 16; i++) {
|
|
1741
|
-
builder.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, null);
|
|
1742
|
-
}
|
|
1743
|
-
builder.nv(NvItemsIds.APS_LINK_KEY_DATA_START + 0, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
|
|
1744
|
-
mockZnpRequestWith(builder);
|
|
1745
|
-
|
|
1746
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1747
|
-
await expect(adapter.start()).rejects.toThrowError("target adapter aps link key data table size insufficient (size=1)");
|
|
1748
|
-
});
|
|
1749
|
-
|
|
1750
|
-
it("should fail to restore unified backup with 3.0.x adapter - insufficient security manager table size", async () => {
|
|
1751
|
-
const backupFile = getTempFile();
|
|
1752
|
-
const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1753
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1754
|
-
|
|
1755
|
-
const builder = empty3AlignedRequestMock.clone();
|
|
1756
|
-
builder.nv(NvItemsIds.APS_LINK_KEY_TABLE, Buffer.from("0000feff00000000", "hex"));
|
|
1757
|
-
mockZnpRequestWith(builder);
|
|
1758
|
-
|
|
1759
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1760
|
-
await expect(adapter.start()).rejects.toThrowError("target adapter security manager table size insufficient (size=1)");
|
|
1761
|
-
});
|
|
1762
|
-
|
|
1763
|
-
it("should fail to restore unified backup with 1.2 adapter - backup from newer adapter", async () => {
|
|
1764
|
-
const backupFile = getTempFile();
|
|
1765
|
-
const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
|
|
1766
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
|
|
1767
|
-
|
|
1768
|
-
mockZnpRequestWith(empty12UnalignedRequestMock);
|
|
1769
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1770
|
-
await expect(adapter.start()).rejects.toThrowError(
|
|
1771
|
-
"your backup is from newer platform version (Z-Stack 3.0.x+) and cannot be restored onto Z-Stack 1.2 adapter - please remove backup before proceeding",
|
|
1772
|
-
);
|
|
1773
|
-
});
|
|
1774
|
-
|
|
1775
|
-
it("should fail to create backup with 3.0.x adapter - unable to read ieee address", async () => {
|
|
1776
|
-
mockZnpRequestWith(commissioned3AlignedRequestMock.clone().handle(Subsystem.SYS, "getExtAddr", () => ({payload: {}})));
|
|
1777
|
-
const result = await adapter.start();
|
|
1778
|
-
expect(result).toBe("resumed");
|
|
1779
|
-
await expect(adapter.backup([])).rejects.toThrowError("Failed to read adapter IEEE address");
|
|
1780
|
-
});
|
|
1781
|
-
|
|
1782
|
-
it("should fail to create backup with 3.0.x adapter - adapter not commissioned - missing nib", async () => {
|
|
1783
|
-
const builder = empty3AlignedRequestMock.clone();
|
|
1784
|
-
mockZnpRequestWith(builder);
|
|
1785
|
-
const result = await adapter.start();
|
|
1786
|
-
expect(result).toBe("reset");
|
|
1787
|
-
builder.nv(NvItemsIds.NIB, null);
|
|
1788
|
-
mockZnpRequestWith(builder);
|
|
1789
|
-
await expect(adapter.backup([])).rejects.toThrowError("Cannot backup - adapter not commissioned");
|
|
1790
|
-
});
|
|
1791
|
-
|
|
1792
|
-
it("should fail to create backup with 3.0.x adapter - missing active key info", async () => {
|
|
1793
|
-
const builder = empty3AlignedRequestMock.clone();
|
|
1794
|
-
mockZnpRequestWith(builder);
|
|
1795
|
-
const result = await adapter.start();
|
|
1796
|
-
expect(result).toBe("reset");
|
|
1797
|
-
builder.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, null);
|
|
1798
|
-
mockZnpRequestWith(builder);
|
|
1799
|
-
await expect(adapter.backup([])).rejects.toThrowError("Cannot backup - missing active key info");
|
|
1800
|
-
});
|
|
1801
|
-
|
|
1802
|
-
it("should restore legacy backup with 3.0.x adapter - empty", async () => {
|
|
1803
|
-
const backupFile = getTempFile();
|
|
1804
|
-
fs.writeFileSync(backupFile, JSON.stringify(legacyBackup), "utf8");
|
|
1805
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1806
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1807
|
-
const result = await adapter.start();
|
|
1808
|
-
expect(result).toBe("restored");
|
|
1809
|
-
});
|
|
1810
|
-
|
|
1811
|
-
it("should fail to restore legacy backup with 3.0.x adapter - missing NIB", async () => {
|
|
1812
|
-
const backupFile = getTempFile();
|
|
1813
|
-
const backup = JSON.parse(JSON.stringify(legacyBackup));
|
|
1814
|
-
delete backup.data.ZCD_NV_NIB;
|
|
1815
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1816
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1817
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1818
|
-
await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing NIB");
|
|
1819
|
-
});
|
|
1820
|
-
|
|
1821
|
-
it("should fail to restore legacy backup with 3.0.x adapter - missing active key info", async () => {
|
|
1822
|
-
const backupFile = getTempFile();
|
|
1823
|
-
const backup = JSON.parse(JSON.stringify(legacyBackup));
|
|
1824
|
-
delete backup.data.ZCD_NV_NWK_ACTIVE_KEY_INFO;
|
|
1825
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1826
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1827
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1828
|
-
await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing active key info");
|
|
1829
|
-
});
|
|
1830
|
-
|
|
1831
|
-
it("should fail to restore legacy backup with 3.0.x adapter - missing pre-configured key enabled", async () => {
|
|
1832
|
-
const backupFile = getTempFile();
|
|
1833
|
-
const backup = JSON.parse(JSON.stringify(legacyBackup));
|
|
1834
|
-
delete backup.data.ZCD_NV_PRECFGKEY_ENABLE;
|
|
1835
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1836
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1837
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1838
|
-
await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing pre-configured key enable attribute");
|
|
1839
|
-
});
|
|
1840
|
-
|
|
1841
|
-
it("should fail to restore legacy backup with 3.0.x adapter - pre-configured key enabled", async () => {
|
|
1842
|
-
const backupFile = getTempFile();
|
|
1843
|
-
const backup = JSON.parse(JSON.stringify(legacyBackup));
|
|
1844
|
-
delete backup.data.ZCD_NV_EX_NWK_SEC_MATERIAL_TABLE;
|
|
1845
|
-
delete backup.data.ZCD_NV_LEGACY_NWK_SEC_MATERIAL_TABLE_START;
|
|
1846
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1847
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1848
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1849
|
-
await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing network security material table");
|
|
1850
|
-
});
|
|
1851
|
-
|
|
1852
|
-
it("should fail to restore legacy backup with 3.0.x adapter - missing adapter ieee address", async () => {
|
|
1853
|
-
const backupFile = getTempFile();
|
|
1854
|
-
const backup = JSON.parse(JSON.stringify(legacyBackup));
|
|
1855
|
-
delete backup.data.ZCD_NV_EXTADDR;
|
|
1856
|
-
fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
|
|
1857
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1858
|
-
mockZnpRequestWith(empty3AlignedRequestMock);
|
|
1859
|
-
await expect(adapter.start()).rejects.toThrow("Backup corrupted - missing adapter IEEE address NV entry");
|
|
1860
|
-
});
|
|
1861
|
-
|
|
1862
|
-
it("should fail to start with 3.0.x adapter - commissioned, config-adapter mismatch", async () => {
|
|
1863
|
-
const backupFile = getTempFile();
|
|
1864
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1865
|
-
|
|
1866
|
-
adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3});
|
|
1867
|
-
mockZnpRequestWith(commissioned3AlignedRequestMock);
|
|
1868
|
-
await expect(adapter.start()).rejects.toThrow("startup failed - configuration-adapter mismatch - see logs above for more information");
|
|
1869
|
-
expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!");
|
|
1870
|
-
expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123");
|
|
1871
|
-
expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77");
|
|
1872
|
-
expect(mockLogger.error.mock.calls[3][0]).toBe(
|
|
1873
|
-
"- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter:active=01030507090b0d0f00020406080a0c0d adapter:preconfigured=01030507090b0d0f00020406080a0c0d, adapter:alternate=01030507090b0d0f00020406080a0c0d",
|
|
1874
|
-
);
|
|
1875
|
-
expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21");
|
|
1876
|
-
expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues.");
|
|
1877
|
-
expect(mockLogger.error.mock.calls[6][0]).toMatch(
|
|
1878
|
-
`If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`,
|
|
1879
|
-
);
|
|
1880
|
-
expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!");
|
|
1881
|
-
});
|
|
1882
|
-
|
|
1883
|
-
it("should start with runInconsistent option with 3.0.x adapter - commissioned, config-adapter mismatch", async () => {
|
|
1884
|
-
const backupFile = getTempFile();
|
|
1885
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1886
|
-
|
|
1887
|
-
adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {
|
|
1888
|
-
concurrent: 3,
|
|
1889
|
-
forceStartWithInconsistentAdapterConfiguration: true,
|
|
1890
|
-
});
|
|
1891
|
-
mockZnpRequestWith(commissioned3AlignedRequestMock);
|
|
1892
|
-
const result = await adapter.start();
|
|
1893
|
-
expect(result).toBe("resumed");
|
|
1894
|
-
expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!");
|
|
1895
|
-
expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123");
|
|
1896
|
-
expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77");
|
|
1897
|
-
expect(mockLogger.error.mock.calls[3][0]).toBe(
|
|
1898
|
-
"- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter:active=01030507090b0d0f00020406080a0c0d adapter:preconfigured=01030507090b0d0f00020406080a0c0d, adapter:alternate=01030507090b0d0f00020406080a0c0d",
|
|
1899
|
-
);
|
|
1900
|
-
expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21");
|
|
1901
|
-
expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues.");
|
|
1902
|
-
expect(mockLogger.error.mock.calls[6][0]).toMatch(
|
|
1903
|
-
`If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`,
|
|
1904
|
-
);
|
|
1905
|
-
expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!");
|
|
1906
|
-
expect(mockLogger.error.mock.calls[8][0]).toBe(
|
|
1907
|
-
"Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible.",
|
|
1908
|
-
);
|
|
1909
|
-
});
|
|
1910
|
-
|
|
1911
|
-
it("should start with 3.0.x adapter - backward-compat - reversed extended pan id", async () => {
|
|
1912
|
-
const backupFile = getTempFile();
|
|
1913
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1914
|
-
|
|
1915
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1916
|
-
const nib = Structs.nib(Buffer.from(commissioned3AlignedRequestMock.nvItems.find((item) => item.id === NvItemsIds.NIB).value));
|
|
1917
|
-
nib.extendedPANID = nib.extendedPANID.reverse();
|
|
1918
|
-
mockZnpRequestWith(commissioned3AlignedRequestMock.clone().nv(NvItemsIds.NIB, nib.serialize()));
|
|
1919
|
-
const result = await adapter.start();
|
|
1920
|
-
expect(result).toBe("resumed");
|
|
1921
|
-
expect(mockLogger.warning.mock.calls[0][0]).toBe("Extended PAN ID is reversed (expected=00124b0009d69f77, actual=779fd609004b1200)");
|
|
1922
|
-
});
|
|
1923
|
-
|
|
1924
|
-
it("should restore unified backup with 3.0.x adapter - commissioned, mismatched adapter-config, matching config-backup", async () => {
|
|
1925
|
-
const backupFile = getTempFile();
|
|
1926
|
-
fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
|
|
1927
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
|
|
1928
|
-
mockZnpRequestWith(commissioned3AlignedConfigMistmachRequestMock);
|
|
1929
|
-
const result = await adapter.start();
|
|
1930
|
-
expect(result).toBe("restored");
|
|
1931
|
-
});
|
|
1932
|
-
|
|
1933
|
-
it("should start network with 3.0.x adapter - resume in coordinator mode", async () => {
|
|
1934
|
-
mockZnpRequestWith(
|
|
1935
|
-
commissioned3AlignedRequestMock.clone().handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: DevStates.ZB_COORD}})),
|
|
1936
|
-
);
|
|
1937
|
-
mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
|
|
1938
|
-
const missing = () => {
|
|
1939
|
-
const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
|
|
1940
|
-
console.log(msg);
|
|
1941
|
-
throw new Error(msg);
|
|
1942
|
-
};
|
|
1943
|
-
|
|
1944
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
|
|
1945
|
-
return waitForResult(
|
|
1946
|
-
mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
|
|
1947
|
-
Zdo.Status.SUCCESS,
|
|
1948
|
-
{
|
|
1949
|
-
nwkAddress: 0,
|
|
1950
|
-
endpointList: [1, 2, 3],
|
|
1951
|
-
},
|
|
1952
|
-
]),
|
|
1953
|
-
);
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
|
|
1957
|
-
return waitForResult({payload: {state: 9}});
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
missing();
|
|
1961
|
-
});
|
|
1962
|
-
const result = await adapter.start();
|
|
1963
|
-
expect(result).toBe("resumed");
|
|
1964
|
-
});
|
|
1965
|
-
|
|
1966
|
-
it("should start network with 3.0.x adapter - resume in coordinator mode, extGroupFind failed", async () => {
|
|
1967
|
-
mockZnpRequestWith(
|
|
1968
|
-
commissioned3AlignedRequestMock
|
|
1969
|
-
.clone()
|
|
1970
|
-
.handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: DevStates.ZB_COORD}}))
|
|
1971
|
-
.handle(Subsystem.ZDO, "extFindGroup", () => ({payload: {status: 1}})),
|
|
1972
|
-
);
|
|
1973
|
-
const result = await adapter.start();
|
|
1974
|
-
expect(result).toBe("resumed");
|
|
1975
|
-
});
|
|
1976
|
-
|
|
1977
|
-
it("should commission network with 1.2 adapter", async () => {
|
|
1978
|
-
mockZnpRequestWith(empty12UnalignedRequestMock);
|
|
1979
|
-
const result = await adapter.start();
|
|
1980
|
-
expect(result).toBe("restored");
|
|
1981
|
-
});
|
|
1982
|
-
|
|
1983
|
-
it("should commission network with 1.2 adapter - default extended pan id", async () => {
|
|
1984
|
-
mockZnpRequestWith(empty12UnalignedRequestMock);
|
|
1985
|
-
adapter = new ZStackAdapter(networkOptionsDefaultExtendedPanId, serialPortOptions, "backup.json", {concurrent: 3});
|
|
1986
|
-
const result = await adapter.start();
|
|
1987
|
-
expect(result).toBe("restored");
|
|
1988
|
-
});
|
|
1989
|
-
|
|
1990
|
-
it("should commission network with 1.2 adapter - old adapter without version reporting", async () => {
|
|
1991
|
-
mockZnpRequestWith(empty12UnalignedRequestMock.clone().handle(Subsystem.SYS, "version", () => undefined));
|
|
1992
|
-
const result = await adapter.start();
|
|
1993
|
-
expect(result).toBe("restored");
|
|
1994
|
-
});
|
|
1995
|
-
|
|
1996
|
-
it("should reset network with 1.2 adapter - config mismtach", async () => {
|
|
1997
|
-
mockZnpRequestWith(commissioned12UnalignedMismatchRequestMock);
|
|
1998
|
-
const result = await adapter.start();
|
|
1999
|
-
expect(result).toBe("reset");
|
|
2000
|
-
});
|
|
2001
|
-
|
|
2002
|
-
it("Add install code: Install Code + CRC", async () => {
|
|
2003
|
-
basicMocks();
|
|
2004
|
-
await adapter.start();
|
|
2005
|
-
await adapter.addInstallCode(
|
|
2006
|
-
"0x9035EAFFFE424783",
|
|
2007
|
-
Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31, 0xe8, 0x02]),
|
|
2008
|
-
false,
|
|
2009
|
-
);
|
|
2010
|
-
const payload = {
|
|
2011
|
-
installCodeFormat: 0x1,
|
|
2012
|
-
ieeeaddr: "0x9035EAFFFE424783",
|
|
2013
|
-
installCode: Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31, 0xe8, 0x02]),
|
|
2014
|
-
};
|
|
2015
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.APP_CNF, "bdbAddInstallCode", payload);
|
|
2016
|
-
});
|
|
2017
|
-
|
|
2018
|
-
it("Add install code: Key derived from Install Code", async () => {
|
|
2019
|
-
basicMocks();
|
|
2020
|
-
await adapter.start();
|
|
2021
|
-
await adapter.addInstallCode(
|
|
2022
|
-
"0x9035EAFFFE424783",
|
|
2023
|
-
Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31]),
|
|
2024
|
-
true,
|
|
2025
|
-
);
|
|
2026
|
-
const payload = {
|
|
2027
|
-
installCodeFormat: 0x2,
|
|
2028
|
-
ieeeaddr: "0x9035EAFFFE424783",
|
|
2029
|
-
installCode: Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31]),
|
|
2030
|
-
};
|
|
2031
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.APP_CNF, "bdbAddInstallCode", payload);
|
|
2032
|
-
});
|
|
2033
|
-
|
|
2034
|
-
it("LED behaviour: disable LED true, firmware not handling leds", async () => {
|
|
2035
|
-
basicMocks();
|
|
2036
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: true});
|
|
2037
|
-
await adapter.start();
|
|
2038
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
|
|
2039
|
-
mockZnpRequest.mockClear();
|
|
2040
|
-
mockQueueExecute.mockClear();
|
|
2041
|
-
await adapter.permitJoin(255, 0);
|
|
2042
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
|
|
2043
|
-
mockZnpRequest.mockClear();
|
|
2044
|
-
mockQueueExecute.mockClear();
|
|
2045
|
-
await adapter.permitJoin(0, 0);
|
|
2046
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
|
|
2047
|
-
});
|
|
2048
|
-
|
|
2049
|
-
it("LED behaviour: disable LED false, firmware not handling leds", async () => {
|
|
2050
|
-
basicMocks();
|
|
2051
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: false});
|
|
2052
|
-
await adapter.start();
|
|
2053
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
|
|
2054
|
-
mockZnpRequest.mockClear();
|
|
2055
|
-
mockQueueExecute.mockClear();
|
|
2056
|
-
await adapter.permitJoin(255, 0);
|
|
2057
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
|
|
2058
|
-
mockZnpRequest.mockClear();
|
|
2059
|
-
mockQueueExecute.mockClear();
|
|
2060
|
-
await adapter.permitJoin(0, 0);
|
|
2061
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
|
|
2062
|
-
});
|
|
2063
|
-
|
|
2064
|
-
it("LED behaviour: disable LED true, firmware handling leds", async () => {
|
|
2065
|
-
mockZnpRequestWith(
|
|
2066
|
-
baseZnpRequestMock.clone().handle(Subsystem.SYS, "version", (_payload) => {
|
|
2067
|
-
return {payload: {product: ZnpVersion.ZStack30x, revision: 20211030}};
|
|
2068
|
-
}),
|
|
2069
|
-
);
|
|
2070
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: true});
|
|
2071
|
-
await adapter.start();
|
|
2072
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 0xff, mode: 5}, undefined, 500);
|
|
2073
|
-
mockZnpRequest.mockClear();
|
|
2074
|
-
mockQueueExecute.mockClear();
|
|
2075
|
-
await adapter.permitJoin(255, 0);
|
|
2076
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
|
|
2077
|
-
mockZnpRequest.mockClear();
|
|
2078
|
-
mockQueueExecute.mockClear();
|
|
2079
|
-
await adapter.permitJoin(0, 0);
|
|
2080
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
|
|
2081
|
-
});
|
|
2082
|
-
|
|
2083
|
-
it("LED behaviour: disable LED false, firmware handling leds", async () => {
|
|
2084
|
-
mockZnpRequestWith(
|
|
2085
|
-
baseZnpRequestMock.clone().handle(Subsystem.SYS, "version", (_payload) => {
|
|
2086
|
-
return {payload: {product: ZnpVersion.ZStack30x, revision: 20211030}};
|
|
2087
|
-
}),
|
|
2088
|
-
);
|
|
2089
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: false});
|
|
2090
|
-
await adapter.start();
|
|
2091
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
|
|
2092
|
-
mockZnpRequest.mockClear();
|
|
2093
|
-
mockQueueExecute.mockClear();
|
|
2094
|
-
await adapter.permitJoin(255, 0);
|
|
2095
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
|
|
2096
|
-
mockZnpRequest.mockClear();
|
|
2097
|
-
mockQueueExecute.mockClear();
|
|
2098
|
-
await adapter.permitJoin(0, 0);
|
|
2099
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
|
|
2100
|
-
});
|
|
2101
|
-
|
|
2102
|
-
/* Original Tests */
|
|
2103
|
-
|
|
2104
|
-
it("Call znp constructor", () => {
|
|
2105
|
-
expect(Znp).toHaveBeenCalledWith("dummy", 800, false);
|
|
2106
|
-
});
|
|
2107
|
-
|
|
2108
|
-
it("Close adapter", async () => {
|
|
2109
|
-
basicMocks();
|
|
2110
|
-
await adapter.start();
|
|
2111
|
-
await adapter.stop();
|
|
2112
|
-
expect(mockZnpClose).toHaveBeenCalledTimes(1);
|
|
2113
|
-
});
|
|
2114
|
-
|
|
2115
|
-
it("Get coordinator IEEE", async () => {
|
|
2116
|
-
basicMocks();
|
|
2117
|
-
await adapter.start();
|
|
2118
|
-
const ieee = await adapter.getCoordinatorIEEE();
|
|
2119
|
-
expect(ieee).toStrictEqual("0x00124b0009d80ba7");
|
|
2120
|
-
});
|
|
2121
|
-
|
|
2122
|
-
it("Permit join all", async () => {
|
|
2123
|
-
basicMocks();
|
|
2124
|
-
await adapter.start();
|
|
2125
|
-
mockZnpRequest.mockClear();
|
|
2126
|
-
mockZnpRequestZdo.mockClear();
|
|
2127
|
-
mockQueueExecute.mockClear();
|
|
2128
|
-
await adapter.permitJoin(100);
|
|
2129
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2130
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2131
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.PERMIT_JOINING_REQUEST, 100, 1, []);
|
|
2132
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2133
|
-
Zdo.ClusterId.PERMIT_JOINING_REQUEST,
|
|
2134
|
-
Buffer.from([
|
|
2135
|
-
AddressMode.ADDR_BROADCAST,
|
|
2136
|
-
ZSpec.BroadcastAddress.DEFAULT & 0xff,
|
|
2137
|
-
(ZSpec.BroadcastAddress.DEFAULT >> 8) & 0xff,
|
|
2138
|
-
...zdoPayload,
|
|
2139
|
-
]),
|
|
2140
|
-
undefined,
|
|
2141
|
-
// Subsystem.ZDO, 'mgmtPermitJoinReq', {
|
|
2142
|
-
// addrmode: 0x0f,
|
|
2143
|
-
// dstaddr: 0xfffc,
|
|
2144
|
-
// duration: 100,
|
|
2145
|
-
// tcsignificance: 0,
|
|
2146
|
-
// }
|
|
2147
|
-
);
|
|
2148
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
|
|
2149
|
-
});
|
|
2150
|
-
|
|
2151
|
-
it("Permit join specific networkAddress", async () => {
|
|
2152
|
-
basicMocks();
|
|
2153
|
-
await adapter.start();
|
|
2154
|
-
mockZnpRequest.mockClear();
|
|
2155
|
-
mockZnpRequestZdo.mockClear();
|
|
2156
|
-
mockQueueExecute.mockClear();
|
|
2157
|
-
await adapter.permitJoin(102, 42102);
|
|
2158
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2159
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2160
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.PERMIT_JOINING_REQUEST, 102, 1, []);
|
|
2161
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2162
|
-
Zdo.ClusterId.PERMIT_JOINING_REQUEST,
|
|
2163
|
-
Buffer.from([AddressMode.ADDR_16BIT, 42102 & 0xff, (42102 >> 8) & 0xff, ...zdoPayload]),
|
|
2164
|
-
expect.any(Number),
|
|
2165
|
-
// Subsystem.ZDO, 'mgmtPermitJoinReq', {
|
|
2166
|
-
// addrmode: 2,
|
|
2167
|
-
// dstaddr: 42102,
|
|
2168
|
-
// duration: 102,
|
|
2169
|
-
// tcsignificance: 0,
|
|
2170
|
-
// }
|
|
2171
|
-
);
|
|
2172
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
|
|
2173
|
-
});
|
|
2174
|
-
|
|
2175
|
-
it("Get coordinator version", async () => {
|
|
2176
|
-
basicMocks();
|
|
2177
|
-
await adapter.start();
|
|
2178
|
-
mockZnpRequest.mockClear();
|
|
2179
|
-
mockQueueExecute.mockClear();
|
|
2180
|
-
expect(await adapter.getCoordinatorVersion()).toStrictEqual({type: "ZStack3x0", meta: {revision: 20210430, product: 1}});
|
|
2181
|
-
});
|
|
2182
|
-
|
|
2183
|
-
it("Soft reset", async () => {
|
|
2184
|
-
basicMocks();
|
|
2185
|
-
await adapter.start();
|
|
2186
|
-
mockZnpRequest.mockClear();
|
|
2187
|
-
mockQueueExecute.mockClear();
|
|
2188
|
-
await adapter.reset("soft");
|
|
2189
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2190
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "resetReq", {type: 1});
|
|
2191
|
-
});
|
|
2192
|
-
|
|
2193
|
-
it("Hard reset", async () => {
|
|
2194
|
-
basicMocks();
|
|
2195
|
-
await adapter.start();
|
|
2196
|
-
mockZnpRequest.mockClear();
|
|
2197
|
-
mockQueueExecute.mockClear();
|
|
2198
|
-
await adapter.reset("hard");
|
|
2199
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2200
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "resetReq", {type: 0});
|
|
2201
|
-
});
|
|
2202
|
-
|
|
2203
|
-
it("Start with transmit power set", async () => {
|
|
2204
|
-
basicMocks();
|
|
2205
|
-
adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {transmitPower: 2, disableLED: false});
|
|
2206
|
-
await adapter.start();
|
|
2207
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "stackTune", {operation: 0, value: 2});
|
|
2208
|
-
});
|
|
2209
|
-
|
|
2210
|
-
it("Support LED should go to false when LED request fails", async () => {
|
|
2211
|
-
basicMocks();
|
|
2212
|
-
await adapter.start();
|
|
2213
|
-
mockZnpRequest.mockClear();
|
|
2214
|
-
mockQueueExecute.mockClear();
|
|
2215
|
-
mockZnpRequest.mockImplementation(
|
|
2216
|
-
(_, cmd) =>
|
|
2217
|
-
new Promise((resolve, reject) => {
|
|
2218
|
-
if (cmd === "ledControl") reject("FAILED");
|
|
2219
|
-
else resolve(undefined);
|
|
2220
|
-
}),
|
|
2221
|
-
);
|
|
2222
|
-
await adapter.permitJoin(0, 0);
|
|
2223
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
|
|
2224
|
-
mockZnpRequest.mockClear();
|
|
2225
|
-
mockQueueExecute.mockClear();
|
|
2226
|
-
await adapter.permitJoin(0, 0);
|
|
2227
|
-
expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
|
|
2228
|
-
});
|
|
2229
|
-
|
|
2230
|
-
it("Send zcl frame network address", async () => {
|
|
2231
|
-
basicMocks();
|
|
2232
|
-
await adapter.start();
|
|
2233
|
-
|
|
2234
|
-
mockZnpRequest.mockClear();
|
|
2235
|
-
mockQueueExecute.mockClear();
|
|
2236
|
-
const frame = Zcl.Frame.create(
|
|
2237
|
-
Zcl.FrameType.GLOBAL,
|
|
2238
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2239
|
-
true,
|
|
2240
|
-
undefined,
|
|
2241
|
-
100,
|
|
2242
|
-
"writeNoRsp",
|
|
2243
|
-
0,
|
|
2244
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2245
|
-
{},
|
|
2246
|
-
);
|
|
2247
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2248
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
2249
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2250
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2251
|
-
4,
|
|
2252
|
-
"dataRequest",
|
|
2253
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2254
|
-
99,
|
|
2255
|
-
);
|
|
2256
|
-
});
|
|
2257
|
-
|
|
2258
|
-
it("Send zcl frame network address retry on MAC channel access failure", async () => {
|
|
2259
|
-
basicMocks();
|
|
2260
|
-
dataConfirmCode = 225;
|
|
2261
|
-
dataConfirmCodeReset = true;
|
|
2262
|
-
await adapter.start();
|
|
2263
|
-
mockZnpRequest.mockClear();
|
|
2264
|
-
mockQueueExecute.mockClear();
|
|
2265
|
-
const frame = Zcl.Frame.create(
|
|
2266
|
-
Zcl.FrameType.GLOBAL,
|
|
2267
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2268
|
-
true,
|
|
2269
|
-
undefined,
|
|
2270
|
-
100,
|
|
2271
|
-
"writeNoRsp",
|
|
2272
|
-
0,
|
|
2273
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2274
|
-
{},
|
|
2275
|
-
);
|
|
2276
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2277
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
2278
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(2);
|
|
2279
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2280
|
-
4,
|
|
2281
|
-
"dataRequest",
|
|
2282
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2283
|
-
99,
|
|
2284
|
-
);
|
|
2285
|
-
});
|
|
2286
|
-
|
|
2287
|
-
it("Send zcl frame network address dataConfirm fails", async () => {
|
|
2288
|
-
basicMocks();
|
|
2289
|
-
await adapter.start();
|
|
2290
|
-
dataConfirmCode = 201;
|
|
2291
|
-
mockZnpRequest.mockClear();
|
|
2292
|
-
mockQueueExecute.mockClear();
|
|
2293
|
-
const frame = Zcl.Frame.create(
|
|
2294
|
-
Zcl.FrameType.GLOBAL,
|
|
2295
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2296
|
-
true,
|
|
2297
|
-
undefined,
|
|
2298
|
-
100,
|
|
2299
|
-
"writeNoRsp",
|
|
2300
|
-
0,
|
|
2301
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2302
|
-
{},
|
|
2303
|
-
);
|
|
2304
|
-
let error;
|
|
2305
|
-
try {
|
|
2306
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2307
|
-
} catch (e) {
|
|
2308
|
-
error = e;
|
|
2309
|
-
}
|
|
2310
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'undefined' (201)");
|
|
2311
|
-
});
|
|
2312
|
-
|
|
2313
|
-
it("Send zcl frame network address with default response", async () => {
|
|
2314
|
-
basicMocks();
|
|
2315
|
-
await adapter.start();
|
|
2316
|
-
const defaultReponse = Zcl.Frame.create(
|
|
2317
|
-
Zcl.FrameType.GLOBAL,
|
|
2318
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
2319
|
-
true,
|
|
2320
|
-
undefined,
|
|
2321
|
-
100,
|
|
2322
|
-
"defaultRsp",
|
|
2323
|
-
0,
|
|
2324
|
-
{cmdId: 0, status: 0},
|
|
2325
|
-
{},
|
|
2326
|
-
);
|
|
2327
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
2328
|
-
clusterid: 0,
|
|
2329
|
-
srcendpoint: 20,
|
|
2330
|
-
srcaddr: 2,
|
|
2331
|
-
linkquality: 101,
|
|
2332
|
-
groupid: 12,
|
|
2333
|
-
data: defaultReponse.toBuffer(),
|
|
2334
|
-
});
|
|
2335
|
-
mockZnpRequest.mockClear();
|
|
2336
|
-
mockQueueExecute.mockClear();
|
|
2337
|
-
const frame = Zcl.Frame.create(
|
|
2338
|
-
Zcl.FrameType.GLOBAL,
|
|
2339
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2340
|
-
false,
|
|
2341
|
-
undefined,
|
|
2342
|
-
100,
|
|
2343
|
-
"writeNoRsp",
|
|
2344
|
-
0,
|
|
2345
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2346
|
-
{},
|
|
2347
|
-
);
|
|
2348
|
-
const request = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2349
|
-
znpReceived(object);
|
|
2350
|
-
await request;
|
|
2351
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
2352
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2353
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2354
|
-
4,
|
|
2355
|
-
"dataRequest",
|
|
2356
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2357
|
-
99,
|
|
2358
|
-
);
|
|
2359
|
-
});
|
|
2360
|
-
|
|
2361
|
-
it("Send zcl frame network address fails because mac transaction expire, should retry", async () => {
|
|
2362
|
-
basicMocks();
|
|
2363
|
-
await adapter.start();
|
|
2364
|
-
dataConfirmCode = 240;
|
|
2365
|
-
mockZnpRequest.mockClear();
|
|
2366
|
-
mockZnpRequestZdo.mockClear();
|
|
2367
|
-
mockQueueExecute.mockClear();
|
|
2368
|
-
const frame = Zcl.Frame.create(
|
|
2369
|
-
Zcl.FrameType.GLOBAL,
|
|
2370
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2371
|
-
true,
|
|
2372
|
-
undefined,
|
|
2373
|
-
100,
|
|
2374
|
-
"writeNoRsp",
|
|
2375
|
-
0,
|
|
2376
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2377
|
-
{},
|
|
2378
|
-
);
|
|
2379
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2380
|
-
let error;
|
|
2381
|
-
try {
|
|
2382
|
-
await response;
|
|
2383
|
-
} catch (e) {
|
|
2384
|
-
error = e;
|
|
2385
|
-
}
|
|
2386
|
-
|
|
2387
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'MAC transaction expired' (240)");
|
|
2388
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(9);
|
|
2389
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2390
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2391
|
-
1,
|
|
2392
|
-
4,
|
|
2393
|
-
"dataRequest",
|
|
2394
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2395
|
-
99,
|
|
2396
|
-
);
|
|
2397
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2398
|
-
2,
|
|
2399
|
-
4,
|
|
2400
|
-
"dataRequest",
|
|
2401
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
2402
|
-
99,
|
|
2403
|
-
);
|
|
2404
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
|
|
2405
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 7, "assocRemove", {ieeeadr: "0x02"});
|
|
2406
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2407
|
-
5,
|
|
2408
|
-
4,
|
|
2409
|
-
"dataRequest",
|
|
2410
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
|
|
2411
|
-
99,
|
|
2412
|
-
);
|
|
2413
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(6, 7, "assocAdd", {ieeeadr: "0x02", noderelation: 1, nwkaddr: 2});
|
|
2414
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(7, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
|
|
2415
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2416
|
-
8,
|
|
2417
|
-
4,
|
|
2418
|
-
"dataRequest",
|
|
2419
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
|
|
2420
|
-
99,
|
|
2421
|
-
);
|
|
2422
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2423
|
-
Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
|
|
2424
|
-
Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
|
|
2425
|
-
expect.any(Number),
|
|
2426
|
-
//9, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
|
|
2427
|
-
);
|
|
2428
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2429
|
-
9,
|
|
2430
|
-
4,
|
|
2431
|
-
"dataRequest",
|
|
2432
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
|
|
2433
|
-
99,
|
|
2434
|
-
);
|
|
2435
|
-
});
|
|
2436
|
-
|
|
2437
|
-
it("Send zcl frame network address fails because mac transaction expire when not being a parent, should retry", async () => {
|
|
2438
|
-
basicMocks();
|
|
2439
|
-
await adapter.start();
|
|
2440
|
-
dataConfirmCode = 240;
|
|
2441
|
-
assocGetWithAddressNodeRelation = 255;
|
|
2442
|
-
mockZnpRequest.mockClear();
|
|
2443
|
-
mockZnpRequestZdo.mockClear();
|
|
2444
|
-
mockQueueExecute.mockClear();
|
|
2445
|
-
const frame = Zcl.Frame.create(
|
|
2446
|
-
Zcl.FrameType.GLOBAL,
|
|
2447
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2448
|
-
true,
|
|
2449
|
-
undefined,
|
|
2450
|
-
100,
|
|
2451
|
-
"writeNoRsp",
|
|
2452
|
-
0,
|
|
2453
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2454
|
-
{},
|
|
2455
|
-
);
|
|
2456
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2457
|
-
let error;
|
|
2458
|
-
try {
|
|
2459
|
-
await response;
|
|
2460
|
-
} catch (e) {
|
|
2461
|
-
error = e;
|
|
2462
|
-
}
|
|
2463
|
-
|
|
2464
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'MAC transaction expired' (240)");
|
|
2465
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(7);
|
|
2466
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2467
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2468
|
-
1,
|
|
2469
|
-
4,
|
|
2470
|
-
"dataRequest",
|
|
2471
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2472
|
-
99,
|
|
2473
|
-
);
|
|
2474
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2475
|
-
2,
|
|
2476
|
-
4,
|
|
2477
|
-
"dataRequest",
|
|
2478
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
2479
|
-
99,
|
|
2480
|
-
);
|
|
2481
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
|
|
2482
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
|
|
2483
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2484
|
-
5,
|
|
2485
|
-
4,
|
|
2486
|
-
"dataRequest",
|
|
2487
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
|
|
2488
|
-
99,
|
|
2489
|
-
);
|
|
2490
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2491
|
-
Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
|
|
2492
|
-
Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
|
|
2493
|
-
expect.any(Number),
|
|
2494
|
-
//6, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
|
|
2495
|
-
);
|
|
2496
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2497
|
-
6,
|
|
2498
|
-
4,
|
|
2499
|
-
"dataRequest",
|
|
2500
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
|
|
2501
|
-
99,
|
|
2502
|
-
);
|
|
2503
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2504
|
-
7,
|
|
2505
|
-
4,
|
|
2506
|
-
"dataRequest",
|
|
2507
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
|
|
2508
|
-
99,
|
|
2509
|
-
);
|
|
2510
|
-
});
|
|
2511
|
-
|
|
2512
|
-
it("Send zcl frame network address fails because mac no ack, should retry", async () => {
|
|
2513
|
-
basicMocks();
|
|
2514
|
-
await adapter.start();
|
|
2515
|
-
dataConfirmCode = 233;
|
|
2516
|
-
mockZnpRequest.mockClear();
|
|
2517
|
-
mockZnpRequestZdo.mockClear();
|
|
2518
|
-
mockQueueExecute.mockClear();
|
|
2519
|
-
const frame = Zcl.Frame.create(
|
|
2520
|
-
Zcl.FrameType.GLOBAL,
|
|
2521
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2522
|
-
true,
|
|
2523
|
-
undefined,
|
|
2524
|
-
100,
|
|
2525
|
-
"writeNoRsp",
|
|
2526
|
-
0,
|
|
2527
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2528
|
-
{},
|
|
2529
|
-
);
|
|
2530
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2531
|
-
let error;
|
|
2532
|
-
try {
|
|
2533
|
-
await response;
|
|
2534
|
-
} catch (e) {
|
|
2535
|
-
error = e;
|
|
2536
|
-
}
|
|
2537
|
-
|
|
2538
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'MAC no ack' (233)");
|
|
2539
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(6);
|
|
2540
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2541
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2542
|
-
1,
|
|
2543
|
-
4,
|
|
2544
|
-
"dataRequest",
|
|
2545
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2546
|
-
99,
|
|
2547
|
-
);
|
|
2548
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2549
|
-
2,
|
|
2550
|
-
4,
|
|
2551
|
-
"dataRequest",
|
|
2552
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
2553
|
-
99,
|
|
2554
|
-
);
|
|
2555
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
|
|
2556
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2557
|
-
4,
|
|
2558
|
-
4,
|
|
2559
|
-
"dataRequest",
|
|
2560
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
|
|
2561
|
-
99,
|
|
2562
|
-
);
|
|
2563
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2564
|
-
Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
|
|
2565
|
-
Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
|
|
2566
|
-
expect.any(Number),
|
|
2567
|
-
//5, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
|
|
2568
|
-
);
|
|
2569
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2570
|
-
5,
|
|
2571
|
-
4,
|
|
2572
|
-
"dataRequest",
|
|
2573
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
|
|
2574
|
-
99,
|
|
2575
|
-
);
|
|
2576
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2577
|
-
6,
|
|
2578
|
-
4,
|
|
2579
|
-
"dataRequest",
|
|
2580
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
|
|
2581
|
-
99,
|
|
2582
|
-
);
|
|
2583
|
-
});
|
|
2584
|
-
|
|
2585
|
-
it("Send zcl frame network address fails because mac no ack with network address change, should retry", async () => {
|
|
2586
|
-
basicMocks();
|
|
2587
|
-
await adapter.start();
|
|
2588
|
-
dataConfirmCode = 233;
|
|
2589
|
-
mockZnpRequest.mockClear();
|
|
2590
|
-
mockZnpRequestZdo.mockClear();
|
|
2591
|
-
mockQueueExecute.mockClear();
|
|
2592
|
-
const frame = Zcl.Frame.create(
|
|
2593
|
-
Zcl.FrameType.GLOBAL,
|
|
2594
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2595
|
-
true,
|
|
2596
|
-
undefined,
|
|
2597
|
-
100,
|
|
2598
|
-
"writeNoRsp",
|
|
2599
|
-
0,
|
|
2600
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2601
|
-
{},
|
|
2602
|
-
);
|
|
2603
|
-
const response = adapter.sendZclFrameToEndpoint("0x03", 2, 20, frame, 10000, false, false);
|
|
2604
|
-
let error;
|
|
2605
|
-
try {
|
|
2606
|
-
await response;
|
|
2607
|
-
} catch (e) {
|
|
2608
|
-
error = e;
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'MAC no ack' (233)");
|
|
2612
|
-
// expect(mockZnpRequest).toHaveBeenCalledTimes(7);
|
|
2613
|
-
// expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
|
|
2614
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2615
|
-
1,
|
|
2616
|
-
4,
|
|
2617
|
-
"dataRequest",
|
|
2618
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2619
|
-
99,
|
|
2620
|
-
);
|
|
2621
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2622
|
-
2,
|
|
2623
|
-
4,
|
|
2624
|
-
"dataRequest",
|
|
2625
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
2626
|
-
99,
|
|
2627
|
-
);
|
|
2628
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
|
|
2629
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2630
|
-
4,
|
|
2631
|
-
4,
|
|
2632
|
-
"dataRequest",
|
|
2633
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
|
|
2634
|
-
99,
|
|
2635
|
-
);
|
|
2636
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
2637
|
-
Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
|
|
2638
|
-
Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x03", false, 0),
|
|
2639
|
-
expect.any(Number),
|
|
2640
|
-
//5, 5, 'nwkAddrReq', {ieeeaddr: '0x03', reqtype: 0, startindex: 0}
|
|
2641
|
-
);
|
|
2642
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(5, 5, "extRouteDisc", {dstAddr: 3, options: 0, radius: 30});
|
|
2643
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2644
|
-
6,
|
|
2645
|
-
4,
|
|
2646
|
-
"dataRequest",
|
|
2647
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 3, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
|
|
2648
|
-
99,
|
|
2649
|
-
);
|
|
2650
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2651
|
-
7,
|
|
2652
|
-
4,
|
|
2653
|
-
"dataRequest",
|
|
2654
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 3, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
|
|
2655
|
-
99,
|
|
2656
|
-
);
|
|
2657
|
-
});
|
|
2658
|
-
|
|
2659
|
-
it("Send zcl frame network address fails because mac no ack with network address change, without recovery", async () => {
|
|
2660
|
-
basicMocks();
|
|
2661
|
-
await adapter.start();
|
|
2662
|
-
dataConfirmCode = 233;
|
|
2663
|
-
mockZnpRequest.mockClear();
|
|
2664
|
-
mockQueueExecute.mockClear();
|
|
2665
|
-
const frame = Zcl.Frame.create(
|
|
2666
|
-
Zcl.FrameType.GLOBAL,
|
|
2667
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2668
|
-
true,
|
|
2669
|
-
undefined,
|
|
2670
|
-
100,
|
|
2671
|
-
"writeNoRsp",
|
|
2672
|
-
0,
|
|
2673
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2674
|
-
{},
|
|
2675
|
-
);
|
|
2676
|
-
const response = adapter.sendZclFrameToEndpoint("0x03", 2, 20, frame, 10000, false, true, undefined);
|
|
2677
|
-
let error;
|
|
2678
|
-
try {
|
|
2679
|
-
await response;
|
|
2680
|
-
} catch (e) {
|
|
2681
|
-
error = e;
|
|
2682
|
-
}
|
|
2683
|
-
|
|
2684
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'MAC no ack' (233)");
|
|
2685
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2686
|
-
});
|
|
2687
|
-
|
|
2688
|
-
it("Send zcl frame network address should retry on dataconfirm timeout", async () => {
|
|
2689
|
-
basicMocks();
|
|
2690
|
-
await adapter.start();
|
|
2691
|
-
dataConfirmCode = 9999;
|
|
2692
|
-
dataConfirmCodeReset = true;
|
|
2693
|
-
mockZnpRequest.mockClear();
|
|
2694
|
-
mockQueueExecute.mockClear();
|
|
2695
|
-
const frame = Zcl.Frame.create(
|
|
2696
|
-
Zcl.FrameType.GLOBAL,
|
|
2697
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2698
|
-
true,
|
|
2699
|
-
undefined,
|
|
2700
|
-
100,
|
|
2701
|
-
"writeNoRsp",
|
|
2702
|
-
0,
|
|
2703
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2704
|
-
{},
|
|
2705
|
-
);
|
|
2706
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2707
|
-
let error;
|
|
2708
|
-
try {
|
|
2709
|
-
await response;
|
|
2710
|
-
} catch (e) {
|
|
2711
|
-
error = e;
|
|
2712
|
-
}
|
|
2713
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'Timeout' (9999)");
|
|
2714
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2715
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
2716
|
-
1,
|
|
2717
|
-
4,
|
|
2718
|
-
"dataRequest",
|
|
2719
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
2720
|
-
99,
|
|
2721
|
-
);
|
|
2722
|
-
});
|
|
2723
|
-
|
|
2724
|
-
it("Send zcl frame group", async () => {
|
|
2725
|
-
basicMocks();
|
|
2726
|
-
await adapter.start();
|
|
2727
|
-
|
|
2728
|
-
mockZnpRequest.mockClear();
|
|
2729
|
-
mockQueueExecute.mockClear();
|
|
2730
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2731
|
-
await adapter.sendZclFrameToGroup(25, frame, 1);
|
|
2732
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2733
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2734
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2735
|
-
4,
|
|
2736
|
-
"dataRequestExt",
|
|
2737
|
-
{
|
|
2738
|
-
clusterid: 0,
|
|
2739
|
-
data: frame.toBuffer(),
|
|
2740
|
-
destendpoint: 255,
|
|
2741
|
-
dstaddr: "0x0000000000000019",
|
|
2742
|
-
len: 5,
|
|
2743
|
-
options: 0,
|
|
2744
|
-
radius: 30,
|
|
2745
|
-
srcendpoint: 1,
|
|
2746
|
-
transid: 1,
|
|
2747
|
-
dstaddrmode: 1,
|
|
2748
|
-
dstpanid: 0,
|
|
2749
|
-
},
|
|
2750
|
-
99,
|
|
2751
|
-
);
|
|
2752
|
-
});
|
|
2753
|
-
|
|
2754
|
-
it("Send zcl frame group retry on MAC channel access failure", async () => {
|
|
2755
|
-
basicMocks();
|
|
2756
|
-
dataConfirmCode = 225;
|
|
2757
|
-
dataConfirmCodeReset = true;
|
|
2758
|
-
await adapter.start();
|
|
2759
|
-
mockZnpRequest.mockClear();
|
|
2760
|
-
mockQueueExecute.mockClear();
|
|
2761
|
-
const frame = Zcl.Frame.create(
|
|
2762
|
-
Zcl.FrameType.GLOBAL,
|
|
2763
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2764
|
-
false,
|
|
2765
|
-
undefined,
|
|
2766
|
-
100,
|
|
2767
|
-
"writeNoRsp",
|
|
2768
|
-
0,
|
|
2769
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2770
|
-
{},
|
|
2771
|
-
);
|
|
2772
|
-
await adapter.sendZclFrameToGroup(25, frame, 1);
|
|
2773
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2774
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(2);
|
|
2775
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2776
|
-
4,
|
|
2777
|
-
"dataRequestExt",
|
|
2778
|
-
{
|
|
2779
|
-
clusterid: 0,
|
|
2780
|
-
data: frame.toBuffer(),
|
|
2781
|
-
destendpoint: 255,
|
|
2782
|
-
dstaddr: "0x0000000000000019",
|
|
2783
|
-
len: 6,
|
|
2784
|
-
options: 0,
|
|
2785
|
-
radius: 30,
|
|
2786
|
-
srcendpoint: 1,
|
|
2787
|
-
transid: 1,
|
|
2788
|
-
dstaddrmode: 1,
|
|
2789
|
-
dstpanid: 0,
|
|
2790
|
-
},
|
|
2791
|
-
99,
|
|
2792
|
-
);
|
|
2793
|
-
});
|
|
2794
|
-
|
|
2795
|
-
it("Send zcl frame to all - DEFAULT", async () => {
|
|
2796
|
-
basicMocks();
|
|
2797
|
-
await adapter.start();
|
|
2798
|
-
|
|
2799
|
-
mockZnpRequest.mockClear();
|
|
2800
|
-
mockQueueExecute.mockClear();
|
|
2801
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2802
|
-
await adapter.sendZclFrameToAll(242, frame, 250, BroadcastAddress.DEFAULT);
|
|
2803
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2804
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2805
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2806
|
-
4,
|
|
2807
|
-
"dataRequestExt",
|
|
2808
|
-
{
|
|
2809
|
-
clusterid: 0,
|
|
2810
|
-
data: frame.toBuffer(),
|
|
2811
|
-
destendpoint: 242,
|
|
2812
|
-
dstaddr: "0x000000000000fffc",
|
|
2813
|
-
len: 5,
|
|
2814
|
-
options: 0,
|
|
2815
|
-
radius: 30,
|
|
2816
|
-
srcendpoint: 250,
|
|
2817
|
-
transid: 1,
|
|
2818
|
-
dstaddrmode: 2,
|
|
2819
|
-
dstpanid: 0,
|
|
2820
|
-
},
|
|
2821
|
-
undefined,
|
|
2822
|
-
);
|
|
2823
|
-
});
|
|
2824
|
-
|
|
2825
|
-
it("Send zcl frame to all - RX_ON_WHEN_IDLE", async () => {
|
|
2826
|
-
basicMocks();
|
|
2827
|
-
await adapter.start();
|
|
2828
|
-
|
|
2829
|
-
mockZnpRequest.mockClear();
|
|
2830
|
-
mockQueueExecute.mockClear();
|
|
2831
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2832
|
-
await adapter.sendZclFrameToAll(255, frame, 1, BroadcastAddress.RX_ON_WHEN_IDLE);
|
|
2833
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2834
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2835
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2836
|
-
4,
|
|
2837
|
-
"dataRequestExt",
|
|
2838
|
-
{
|
|
2839
|
-
clusterid: 0,
|
|
2840
|
-
data: frame.toBuffer(),
|
|
2841
|
-
destendpoint: 255,
|
|
2842
|
-
dstaddr: "0x000000000000fffd",
|
|
2843
|
-
len: 5,
|
|
2844
|
-
options: 0,
|
|
2845
|
-
radius: 30,
|
|
2846
|
-
srcendpoint: 1,
|
|
2847
|
-
transid: 1,
|
|
2848
|
-
dstaddrmode: 2,
|
|
2849
|
-
dstpanid: 0,
|
|
2850
|
-
},
|
|
2851
|
-
undefined,
|
|
2852
|
-
);
|
|
2853
|
-
});
|
|
2854
|
-
|
|
2855
|
-
it("Send zcl frame to all - SLEEPY", async () => {
|
|
2856
|
-
basicMocks();
|
|
2857
|
-
await adapter.start();
|
|
2858
|
-
|
|
2859
|
-
mockZnpRequest.mockClear();
|
|
2860
|
-
mockQueueExecute.mockClear();
|
|
2861
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2862
|
-
await adapter.sendZclFrameToAll(255, frame, 1, BroadcastAddress.SLEEPY);
|
|
2863
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2864
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2865
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2866
|
-
4,
|
|
2867
|
-
"dataRequestExt",
|
|
2868
|
-
{
|
|
2869
|
-
clusterid: 0,
|
|
2870
|
-
data: frame.toBuffer(),
|
|
2871
|
-
destendpoint: 255,
|
|
2872
|
-
dstaddr: "0x000000000000ffff",
|
|
2873
|
-
len: 5,
|
|
2874
|
-
options: 0,
|
|
2875
|
-
radius: 30,
|
|
2876
|
-
srcendpoint: 1,
|
|
2877
|
-
transid: 1,
|
|
2878
|
-
dstaddrmode: 2,
|
|
2879
|
-
dstpanid: 0,
|
|
2880
|
-
},
|
|
2881
|
-
undefined,
|
|
2882
|
-
);
|
|
2883
|
-
});
|
|
2884
|
-
|
|
2885
|
-
it("Send zcl frame network address transaction number shouldnt go higher than 255", async () => {
|
|
2886
|
-
basicMocks();
|
|
2887
|
-
await adapter.start();
|
|
2888
|
-
let transactionID = 0;
|
|
2889
|
-
|
|
2890
|
-
mockZnpRequest.mockClear();
|
|
2891
|
-
mockQueueExecute.mockClear();
|
|
2892
|
-
|
|
2893
|
-
for (let i = 0; i < 300; i++) {
|
|
2894
|
-
if (transactionID > 200) {
|
|
2895
|
-
transactionID = 0;
|
|
2896
|
-
}
|
|
2897
|
-
|
|
2898
|
-
const frame = Zcl.Frame.create(
|
|
2899
|
-
Zcl.FrameType.GLOBAL,
|
|
2900
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
2901
|
-
true,
|
|
2902
|
-
undefined,
|
|
2903
|
-
100,
|
|
2904
|
-
"writeNoRsp",
|
|
2905
|
-
0,
|
|
2906
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
2907
|
-
{},
|
|
2908
|
-
);
|
|
2909
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
2910
|
-
}
|
|
2911
|
-
|
|
2912
|
-
const got: number[] = [];
|
|
2913
|
-
for (let i = 0; i < 300; i++) {
|
|
2914
|
-
got.push(mockZnpRequest.mock.calls[i][2].transid);
|
|
2915
|
-
}
|
|
2916
|
-
|
|
2917
|
-
expect(got[0]).toBe(1);
|
|
2918
|
-
expect(got.find((g) => g === 0)).toBe(undefined);
|
|
2919
|
-
expect(got.find((g) => g > 255)).toBe(undefined);
|
|
2920
|
-
expect(got.filter((g) => g === 1).length).toBe(2);
|
|
2921
|
-
expect(got.filter((g) => g === 255).length).toBe(1);
|
|
2922
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(300);
|
|
2923
|
-
});
|
|
2924
|
-
|
|
2925
|
-
it("Send zcl frame group dataConfirm fails", async () => {
|
|
2926
|
-
basicMocks();
|
|
2927
|
-
await adapter.start();
|
|
2928
|
-
dataConfirmCode = 184;
|
|
2929
|
-
let error;
|
|
2930
|
-
mockZnpRequest.mockClear();
|
|
2931
|
-
mockQueueExecute.mockClear();
|
|
2932
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2933
|
-
try {
|
|
2934
|
-
await adapter.sendZclFrameToGroup(25, frame);
|
|
2935
|
-
} catch (e) {
|
|
2936
|
-
error = e;
|
|
2937
|
-
}
|
|
2938
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
|
|
2939
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
2940
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
2941
|
-
4,
|
|
2942
|
-
"dataRequestExt",
|
|
2943
|
-
{
|
|
2944
|
-
clusterid: 0,
|
|
2945
|
-
data: frame.toBuffer(),
|
|
2946
|
-
destendpoint: 255,
|
|
2947
|
-
dstaddr: "0x0000000000000019",
|
|
2948
|
-
len: 5,
|
|
2949
|
-
options: 0,
|
|
2950
|
-
radius: 30,
|
|
2951
|
-
srcendpoint: 1,
|
|
2952
|
-
transid: 1,
|
|
2953
|
-
dstaddrmode: 1,
|
|
2954
|
-
dstpanid: 0,
|
|
2955
|
-
},
|
|
2956
|
-
99,
|
|
2957
|
-
);
|
|
2958
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'undefined' (184)");
|
|
2959
|
-
});
|
|
2960
|
-
|
|
2961
|
-
it("Send zcl frame network address and default response", async () => {
|
|
2962
|
-
basicMocks();
|
|
2963
|
-
await adapter.start();
|
|
2964
|
-
|
|
2965
|
-
mockZnpRequest.mockClear();
|
|
2966
|
-
mockQueueExecute.mockClear();
|
|
2967
|
-
|
|
2968
|
-
const responseMismatchFrame = Zcl.Frame.create(
|
|
2969
|
-
Zcl.FrameType.GLOBAL,
|
|
2970
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
2971
|
-
true,
|
|
2972
|
-
undefined,
|
|
2973
|
-
102,
|
|
2974
|
-
"readRsp",
|
|
2975
|
-
0,
|
|
2976
|
-
[{attrId: 0, attrData: 5, dataType: 32, status: 0}],
|
|
2977
|
-
{},
|
|
2978
|
-
);
|
|
2979
|
-
const responseFrame = Zcl.Frame.create(
|
|
2980
|
-
Zcl.FrameType.GLOBAL,
|
|
2981
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
2982
|
-
true,
|
|
2983
|
-
undefined,
|
|
2984
|
-
100,
|
|
2985
|
-
"readRsp",
|
|
2986
|
-
0,
|
|
2987
|
-
[{attrId: 0, attrData: 2, dataType: 32, status: 0}],
|
|
2988
|
-
{},
|
|
2989
|
-
);
|
|
2990
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
2991
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
2992
|
-
clusterid: 0,
|
|
2993
|
-
srcendpoint: 20,
|
|
2994
|
-
srcaddr: 2,
|
|
2995
|
-
linkquality: 101,
|
|
2996
|
-
groupid: 12,
|
|
2997
|
-
data: responseFrame.toBuffer(),
|
|
2998
|
-
});
|
|
2999
|
-
const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3000
|
-
clusterid: 0,
|
|
3001
|
-
srcendpoint: 20,
|
|
3002
|
-
srcaddr: 2,
|
|
3003
|
-
linkquality: 101,
|
|
3004
|
-
groupid: 12,
|
|
3005
|
-
data: responseMismatchFrame.toBuffer(),
|
|
3006
|
-
});
|
|
3007
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3008
|
-
znpReceived(objectMismatch);
|
|
3009
|
-
znpReceived(object);
|
|
3010
|
-
const result = await response;
|
|
3011
|
-
|
|
3012
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
3013
|
-
4,
|
|
3014
|
-
"dataRequest",
|
|
3015
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
3016
|
-
99,
|
|
3017
|
-
);
|
|
3018
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
3019
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3020
|
-
expect(result.endpoint).toStrictEqual(20);
|
|
3021
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3022
|
-
expect(result.linkquality).toStrictEqual(101);
|
|
3023
|
-
expect(result.address).toStrictEqual(2);
|
|
3024
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3025
|
-
expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
|
|
3026
|
-
});
|
|
3027
|
-
|
|
3028
|
-
it("Send zcl frame network address and default response", async () => {
|
|
3029
|
-
basicMocks();
|
|
3030
|
-
await adapter.start();
|
|
3031
|
-
|
|
3032
|
-
mockZnpRequest.mockClear();
|
|
3033
|
-
mockQueueExecute.mockClear();
|
|
3034
|
-
|
|
3035
|
-
const responseMismatchFrame = Zcl.Frame.create(
|
|
3036
|
-
Zcl.FrameType.GLOBAL,
|
|
3037
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3038
|
-
true,
|
|
3039
|
-
undefined,
|
|
3040
|
-
102,
|
|
3041
|
-
"readRsp",
|
|
3042
|
-
0,
|
|
3043
|
-
[{attrId: 0, attrData: 5, dataType: 32, status: 0}],
|
|
3044
|
-
{},
|
|
3045
|
-
);
|
|
3046
|
-
const responseFrame = Zcl.Frame.create(
|
|
3047
|
-
Zcl.FrameType.GLOBAL,
|
|
3048
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3049
|
-
true,
|
|
3050
|
-
undefined,
|
|
3051
|
-
100,
|
|
3052
|
-
"readRsp",
|
|
3053
|
-
0,
|
|
3054
|
-
[{attrId: 0, attrData: 2, dataType: 32, status: 0}],
|
|
3055
|
-
{},
|
|
3056
|
-
);
|
|
3057
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3058
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3059
|
-
clusterid: 0,
|
|
3060
|
-
srcendpoint: 20,
|
|
3061
|
-
srcaddr: 2,
|
|
3062
|
-
linkquality: 101,
|
|
3063
|
-
groupid: 12,
|
|
3064
|
-
data: responseFrame.toBuffer(),
|
|
3065
|
-
});
|
|
3066
|
-
const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3067
|
-
clusterid: 0,
|
|
3068
|
-
srcendpoint: 20,
|
|
3069
|
-
srcaddr: 2,
|
|
3070
|
-
linkquality: 101,
|
|
3071
|
-
groupid: 12,
|
|
3072
|
-
data: responseMismatchFrame.toBuffer(),
|
|
3073
|
-
});
|
|
3074
|
-
const defaultReponse = Zcl.Frame.create(
|
|
3075
|
-
Zcl.FrameType.GLOBAL,
|
|
3076
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3077
|
-
true,
|
|
3078
|
-
undefined,
|
|
3079
|
-
100,
|
|
3080
|
-
"defaultRsp",
|
|
3081
|
-
0,
|
|
3082
|
-
{cmdId: 0, status: 0},
|
|
3083
|
-
{},
|
|
3084
|
-
);
|
|
3085
|
-
const defaultObject = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3086
|
-
clusterid: 0,
|
|
3087
|
-
srcendpoint: 20,
|
|
3088
|
-
srcaddr: 2,
|
|
3089
|
-
linkquality: 101,
|
|
3090
|
-
groupid: 12,
|
|
3091
|
-
data: defaultReponse.toBuffer(),
|
|
3092
|
-
});
|
|
3093
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3094
|
-
znpReceived(objectMismatch);
|
|
3095
|
-
znpReceived(defaultObject);
|
|
3096
|
-
znpReceived(object);
|
|
3097
|
-
const result = await response;
|
|
3098
|
-
|
|
3099
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
3100
|
-
4,
|
|
3101
|
-
"dataRequest",
|
|
3102
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
3103
|
-
99,
|
|
3104
|
-
);
|
|
3105
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
3106
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3107
|
-
expect(result.endpoint).toStrictEqual(20);
|
|
3108
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3109
|
-
expect(result.linkquality).toStrictEqual(101);
|
|
3110
|
-
expect(result.address).toStrictEqual(2);
|
|
3111
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3112
|
-
expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
|
|
3113
|
-
});
|
|
3114
|
-
|
|
3115
|
-
it("Send zcl frame network address data confirm fails with default response", async () => {
|
|
3116
|
-
basicMocks();
|
|
3117
|
-
await adapter.start();
|
|
3118
|
-
dataConfirmCode = 201;
|
|
3119
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3120
|
-
let error;
|
|
3121
|
-
try {
|
|
3122
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3123
|
-
} catch (e) {
|
|
3124
|
-
error = e;
|
|
3125
|
-
}
|
|
3126
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'undefined' (201)");
|
|
3127
|
-
});
|
|
3128
|
-
|
|
3129
|
-
it("Send zcl frame network address data confirm fails without default response", async () => {
|
|
3130
|
-
basicMocks();
|
|
3131
|
-
await adapter.start();
|
|
3132
|
-
dataConfirmCode = 201;
|
|
3133
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3134
|
-
let error;
|
|
3135
|
-
try {
|
|
3136
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3137
|
-
} catch (e) {
|
|
3138
|
-
error = e;
|
|
3139
|
-
}
|
|
3140
|
-
expect(error.message).toStrictEqual("Data request failed with error: 'undefined' (201)");
|
|
3141
|
-
});
|
|
3142
|
-
|
|
3143
|
-
it("Send zcl frame network address timeout should discover route and retry", async () => {
|
|
3144
|
-
basicMocks();
|
|
3145
|
-
await adapter.start();
|
|
3146
|
-
|
|
3147
|
-
mockZnpRequest.mockClear();
|
|
3148
|
-
mockQueueExecute.mockClear();
|
|
3149
|
-
assocGetWithAddressNodeRelation = 2;
|
|
3150
|
-
const responseMismatchFrame = Zcl.Frame.create(
|
|
3151
|
-
Zcl.FrameType.GLOBAL,
|
|
3152
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3153
|
-
true,
|
|
3154
|
-
undefined,
|
|
3155
|
-
102,
|
|
3156
|
-
"readRsp",
|
|
3157
|
-
0,
|
|
3158
|
-
[{attrId: 0, attrData: 5, dataType: 32, status: 0}],
|
|
3159
|
-
{},
|
|
3160
|
-
);
|
|
3161
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3162
|
-
const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3163
|
-
clusterid: 0,
|
|
3164
|
-
srcendpoint: 20,
|
|
3165
|
-
srcaddr: 2,
|
|
3166
|
-
linkquality: 101,
|
|
3167
|
-
groupid: 12,
|
|
3168
|
-
data: responseMismatchFrame.toBuffer(),
|
|
3169
|
-
});
|
|
3170
|
-
let error;
|
|
3171
|
-
try {
|
|
3172
|
-
const spy = mockSetTimeout();
|
|
3173
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 1, false, false);
|
|
3174
|
-
znpReceived(objectMismatch);
|
|
3175
|
-
await response;
|
|
3176
|
-
spy.mockRestore();
|
|
3177
|
-
} catch (e) {
|
|
3178
|
-
error = e;
|
|
3179
|
-
}
|
|
3180
|
-
|
|
3181
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
3182
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(4);
|
|
3183
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
3184
|
-
1,
|
|
3185
|
-
4,
|
|
3186
|
-
"dataRequest",
|
|
3187
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
3188
|
-
99,
|
|
3189
|
-
);
|
|
3190
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(2, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
|
|
3191
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: Constants.AF.DEFAULT_RADIUS});
|
|
3192
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
3193
|
-
4,
|
|
3194
|
-
4,
|
|
3195
|
-
"dataRequest",
|
|
3196
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
3197
|
-
99,
|
|
3198
|
-
);
|
|
3199
|
-
expect(error).toStrictEqual(new Error("Timeout - 2 - 20 - 100 - 0 - 1 after 1ms"));
|
|
3200
|
-
});
|
|
3201
|
-
|
|
3202
|
-
it("Send zcl frame network address timeout should discover route, rewrite child entry and retry for sleepy end device", async () => {
|
|
3203
|
-
basicMocks();
|
|
3204
|
-
await adapter.start();
|
|
3205
|
-
|
|
3206
|
-
mockZnpRequest.mockClear();
|
|
3207
|
-
mockQueueExecute.mockClear();
|
|
3208
|
-
|
|
3209
|
-
const responseMismatchFrame = Zcl.Frame.create(
|
|
3210
|
-
Zcl.FrameType.GLOBAL,
|
|
3211
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3212
|
-
true,
|
|
3213
|
-
undefined,
|
|
3214
|
-
102,
|
|
3215
|
-
"readRsp",
|
|
3216
|
-
0,
|
|
3217
|
-
[{attrId: 0, attrData: 5, dataType: 32, status: 0}],
|
|
3218
|
-
{},
|
|
3219
|
-
);
|
|
3220
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3221
|
-
const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3222
|
-
clusterid: 0,
|
|
3223
|
-
srcendpoint: 20,
|
|
3224
|
-
srcaddr: 2,
|
|
3225
|
-
linkquality: 101,
|
|
3226
|
-
groupid: 12,
|
|
3227
|
-
data: responseMismatchFrame.toBuffer(),
|
|
3228
|
-
});
|
|
3229
|
-
let error;
|
|
3230
|
-
try {
|
|
3231
|
-
const spy = mockSetTimeout();
|
|
3232
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 1, false, false);
|
|
3233
|
-
znpReceived(objectMismatch);
|
|
3234
|
-
await response;
|
|
3235
|
-
spy.mockRestore();
|
|
3236
|
-
} catch (e) {
|
|
3237
|
-
error = e;
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
3241
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(6);
|
|
3242
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
3243
|
-
1,
|
|
3244
|
-
4,
|
|
3245
|
-
"dataRequest",
|
|
3246
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
3247
|
-
99,
|
|
3248
|
-
);
|
|
3249
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(2, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
|
|
3250
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocRemove", {ieeeadr: "0x02"});
|
|
3251
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 7, "assocAdd", {ieeeadr: "0x02", nwkaddr: 2, noderelation: 1});
|
|
3252
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(5, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: Constants.AF.DEFAULT_RADIUS});
|
|
3253
|
-
expect(mockZnpRequest).toHaveBeenNthCalledWith(
|
|
3254
|
-
6,
|
|
3255
|
-
4,
|
|
3256
|
-
"dataRequest",
|
|
3257
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 2},
|
|
3258
|
-
99,
|
|
3259
|
-
);
|
|
3260
|
-
expect(error).toStrictEqual(new Error("Timeout - 2 - 20 - 100 - 0 - 1 after 1ms"));
|
|
3261
|
-
});
|
|
3262
|
-
|
|
3263
|
-
it("Send zcl frame network address with default response timeout shouldnt care because command has response", async () => {
|
|
3264
|
-
basicMocks();
|
|
3265
|
-
await adapter.start();
|
|
3266
|
-
|
|
3267
|
-
mockZnpRequest.mockClear();
|
|
3268
|
-
mockQueueExecute.mockClear();
|
|
3269
|
-
const responseFrame = Zcl.Frame.create(
|
|
3270
|
-
Zcl.FrameType.GLOBAL,
|
|
3271
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3272
|
-
true,
|
|
3273
|
-
undefined,
|
|
3274
|
-
100,
|
|
3275
|
-
"readRsp",
|
|
3276
|
-
0,
|
|
3277
|
-
[{attrId: 0, attrData: 2, dataType: 32, status: 0}],
|
|
3278
|
-
{},
|
|
3279
|
-
);
|
|
3280
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
|
|
3281
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3282
|
-
clusterid: 0,
|
|
3283
|
-
srcendpoint: 20,
|
|
3284
|
-
srcaddr: 2,
|
|
3285
|
-
linkquality: 101,
|
|
3286
|
-
groupid: 12,
|
|
3287
|
-
data: responseFrame.toBuffer(),
|
|
3288
|
-
});
|
|
3289
|
-
const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3290
|
-
znpReceived(object);
|
|
3291
|
-
|
|
3292
|
-
let error = null;
|
|
3293
|
-
try {
|
|
3294
|
-
await response;
|
|
3295
|
-
} catch (e) {
|
|
3296
|
-
error = e;
|
|
3297
|
-
}
|
|
3298
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
3299
|
-
4,
|
|
3300
|
-
"dataRequest",
|
|
3301
|
-
{clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
|
|
3302
|
-
99,
|
|
3303
|
-
);
|
|
3304
|
-
expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
|
|
3305
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3306
|
-
expect(error).toStrictEqual(null);
|
|
3307
|
-
});
|
|
3308
|
-
|
|
3309
|
-
it("Supports backup", async () => {
|
|
3310
|
-
basicMocks();
|
|
3311
|
-
await adapter.start();
|
|
3312
|
-
expect(await adapter.supportsBackup()).toBeTruthy();
|
|
3313
|
-
});
|
|
3314
|
-
|
|
3315
|
-
it("Incoming message extended", async () => {
|
|
3316
|
-
basicMocks();
|
|
3317
|
-
await adapter.start();
|
|
3318
|
-
let zclData;
|
|
3319
|
-
const responseFrame = Zcl.Frame.create(
|
|
3320
|
-
Zcl.FrameType.GLOBAL,
|
|
3321
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3322
|
-
true,
|
|
3323
|
-
undefined,
|
|
3324
|
-
100,
|
|
3325
|
-
"readRsp",
|
|
3326
|
-
0,
|
|
3327
|
-
[{attrId: 0, attrData: 2, dataType: 32, status: 0}],
|
|
3328
|
-
{},
|
|
3329
|
-
);
|
|
3330
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
|
|
3331
|
-
clusterid: 0,
|
|
3332
|
-
srcendpoint: 20,
|
|
3333
|
-
srcaddr: 2,
|
|
3334
|
-
linkquality: 101,
|
|
3335
|
-
groupid: 12,
|
|
3336
|
-
data: responseFrame.toBuffer(),
|
|
3337
|
-
});
|
|
3338
|
-
adapter.on("zclPayload", (p) => {
|
|
3339
|
-
zclData = p;
|
|
3340
|
-
});
|
|
3341
|
-
znpReceived(object);
|
|
3342
|
-
expect(zclData.endpoint).toStrictEqual(20);
|
|
3343
|
-
expect(zclData.groupID).toStrictEqual(12);
|
|
3344
|
-
expect(zclData.linkquality).toStrictEqual(101);
|
|
3345
|
-
expect(zclData.address).toStrictEqual(2);
|
|
3346
|
-
expect(zclData.groupID).toStrictEqual(12);
|
|
3347
|
-
expect(zclData.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
|
|
3348
|
-
expect(zclData.header.commandIdentifier).toBe(1);
|
|
3349
|
-
});
|
|
3350
|
-
|
|
3351
|
-
it("Incoming message raw (not ZCL)", async () => {
|
|
3352
|
-
basicMocks();
|
|
3353
|
-
await adapter.start();
|
|
3354
|
-
let rawData;
|
|
3355
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3356
|
-
clusterid: 1,
|
|
3357
|
-
srcendpoint: 20,
|
|
3358
|
-
srcaddr: 2,
|
|
3359
|
-
linkquality: 101,
|
|
3360
|
-
groupid: 12,
|
|
3361
|
-
data: Buffer.from([0x0, 0x1]),
|
|
3362
|
-
});
|
|
3363
|
-
adapter.on("zclPayload", (p) => {
|
|
3364
|
-
rawData = p;
|
|
3365
|
-
});
|
|
3366
|
-
znpReceived(object);
|
|
3367
|
-
expect(rawData.clusterID).toStrictEqual(1);
|
|
3368
|
-
expect(rawData.endpoint).toStrictEqual(20);
|
|
3369
|
-
expect(rawData.groupID).toStrictEqual(12);
|
|
3370
|
-
expect(rawData.linkquality).toStrictEqual(101);
|
|
3371
|
-
expect(rawData.address).toStrictEqual(2);
|
|
3372
|
-
expect(rawData.data).toStrictEqual(Buffer.from([0x0, 0x01]));
|
|
3373
|
-
});
|
|
3374
|
-
|
|
3375
|
-
it("Adapter disconnected", async () => {
|
|
3376
|
-
basicMocks();
|
|
3377
|
-
await adapter.start();
|
|
3378
|
-
let closeEvent = false;
|
|
3379
|
-
adapter.on("disconnected", () => {
|
|
3380
|
-
closeEvent = true;
|
|
3381
|
-
});
|
|
3382
|
-
znpClose();
|
|
3383
|
-
expect(closeEvent).toBeTruthy();
|
|
3384
|
-
});
|
|
3385
|
-
|
|
3386
|
-
it("Adapter disconnected dont emit when closing", async () => {
|
|
3387
|
-
basicMocks();
|
|
3388
|
-
await adapter.start();
|
|
3389
|
-
await adapter.stop();
|
|
3390
|
-
let closeEvent = false;
|
|
3391
|
-
adapter.on("disconnected", () => {
|
|
3392
|
-
closeEvent = true;
|
|
3393
|
-
});
|
|
3394
|
-
znpClose();
|
|
3395
|
-
expect(closeEvent).toBeFalsy();
|
|
3396
|
-
});
|
|
3397
|
-
|
|
3398
|
-
it("Device joined", async () => {
|
|
3399
|
-
basicMocks();
|
|
3400
|
-
await adapter.start();
|
|
3401
|
-
let deviceJoin;
|
|
3402
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "tcDeviceInd", {nwkaddr: 123, extaddr: "0x123"});
|
|
3403
|
-
adapter.on("deviceJoined", (p) => {
|
|
3404
|
-
deviceJoin = p;
|
|
3405
|
-
});
|
|
3406
|
-
znpReceived(object);
|
|
3407
|
-
expect(deviceJoin).toStrictEqual({ieeeAddr: "0x123", networkAddress: 123});
|
|
3408
|
-
});
|
|
3409
|
-
|
|
3410
|
-
it("Device announce", async () => {
|
|
3411
|
-
basicMocks();
|
|
3412
|
-
await adapter.start();
|
|
3413
|
-
mockZnpRequest.mockClear();
|
|
3414
|
-
mockQueueExecute.mockClear();
|
|
3415
|
-
const object = mockZdoZpiObject<EndDeviceAnnounce>("endDeviceAnnceInd", 123, [
|
|
3416
|
-
Zdo.Status.SUCCESS,
|
|
3417
|
-
{
|
|
3418
|
-
capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES,
|
|
3419
|
-
eui64: "0x123",
|
|
3420
|
-
nwkAddress: 123,
|
|
3421
|
-
},
|
|
3422
|
-
]);
|
|
3423
|
-
adapter.on("zdoResponse", (clusterId, payload) => {
|
|
3424
|
-
expect(clusterId).toStrictEqual(Zdo.ClusterId.END_DEVICE_ANNOUNCE);
|
|
3425
|
-
expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
|
|
3426
|
-
expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 123, capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES});
|
|
3427
|
-
});
|
|
3428
|
-
znpReceived(object);
|
|
3429
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(0);
|
|
3430
|
-
});
|
|
3431
|
-
|
|
3432
|
-
it("Device announce should discover route to end devices", async () => {
|
|
3433
|
-
basicMocks();
|
|
3434
|
-
await adapter.start();
|
|
3435
|
-
mockZnpRequest.mockClear();
|
|
3436
|
-
mockQueueExecute.mockClear();
|
|
3437
|
-
const object = mockZdoZpiObject<EndDeviceAnnounce>("endDeviceAnnceInd", 123, [
|
|
3438
|
-
Zdo.Status.SUCCESS,
|
|
3439
|
-
{
|
|
3440
|
-
capabilities: {...DUMMY_NODE_DESC_RSP_CAPABILITIES, deviceType: 0},
|
|
3441
|
-
eui64: "0x123",
|
|
3442
|
-
nwkAddress: 123,
|
|
3443
|
-
},
|
|
3444
|
-
]);
|
|
3445
|
-
adapter.on("zdoResponse", (clusterId, payload) => {
|
|
3446
|
-
expect(clusterId).toStrictEqual(Zdo.ClusterId.END_DEVICE_ANNOUNCE);
|
|
3447
|
-
expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
|
|
3448
|
-
expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 123, capabilities: {...DUMMY_NODE_DESC_RSP_CAPABILITIES, deviceType: 0}});
|
|
3449
|
-
});
|
|
3450
|
-
znpReceived(object);
|
|
3451
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3452
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 123, options: 0, radius: 30});
|
|
3453
|
-
|
|
3454
|
-
// Should debounce route discovery.
|
|
3455
|
-
znpReceived(object);
|
|
3456
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3457
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 123, options: 0, radius: 30});
|
|
3458
|
-
});
|
|
3459
|
-
|
|
3460
|
-
it("Network address response", async () => {
|
|
3461
|
-
basicMocks();
|
|
3462
|
-
await adapter.start();
|
|
3463
|
-
const object = mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", 124, [
|
|
3464
|
-
Zdo.Status.SUCCESS,
|
|
3465
|
-
{
|
|
3466
|
-
eui64: "0x123",
|
|
3467
|
-
nwkAddress: 124,
|
|
3468
|
-
assocDevList: [],
|
|
3469
|
-
startIndex: 0,
|
|
3470
|
-
},
|
|
3471
|
-
]);
|
|
3472
|
-
adapter.on("zdoResponse", (clusterId, payload) => {
|
|
3473
|
-
expect(clusterId).toStrictEqual(Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE);
|
|
3474
|
-
expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
|
|
3475
|
-
expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 124, assocDevList: [], startIndex: 0});
|
|
3476
|
-
});
|
|
3477
|
-
znpReceived(object);
|
|
3478
|
-
});
|
|
3479
|
-
|
|
3480
|
-
it("Concentrator Callback Indication", async () => {
|
|
3481
|
-
basicMocks();
|
|
3482
|
-
await adapter.start();
|
|
3483
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "concentratorIndCb", {srcaddr: 124, extaddr: "0x123"});
|
|
3484
|
-
adapter.on("zdoResponse", (clusterId, payload) => {
|
|
3485
|
-
expect(clusterId).toStrictEqual(Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE);
|
|
3486
|
-
expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
|
|
3487
|
-
expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 124, assocDevList: [], startIndex: 0});
|
|
3488
|
-
});
|
|
3489
|
-
znpReceived(object);
|
|
3490
|
-
});
|
|
3491
|
-
|
|
3492
|
-
it("Device leave", async () => {
|
|
3493
|
-
basicMocks();
|
|
3494
|
-
await adapter.start();
|
|
3495
|
-
let deviceAnnounce;
|
|
3496
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123"});
|
|
3497
|
-
adapter.on("deviceLeave", (p) => {
|
|
3498
|
-
deviceAnnounce = p;
|
|
3499
|
-
});
|
|
3500
|
-
znpReceived(object);
|
|
3501
|
-
expect(deviceAnnounce).toStrictEqual({ieeeAddr: "0x123", networkAddress: 123});
|
|
3502
|
-
});
|
|
3503
|
-
|
|
3504
|
-
it("Ignore device leave with rejoin", async () => {
|
|
3505
|
-
basicMocks();
|
|
3506
|
-
await adapter.start();
|
|
3507
|
-
let deviceAnnounce;
|
|
3508
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123", rejoin: true});
|
|
3509
|
-
adapter.on("deviceLeave", (p) => {
|
|
3510
|
-
deviceAnnounce = p;
|
|
3511
|
-
});
|
|
3512
|
-
znpReceived(object);
|
|
3513
|
-
expect(deviceAnnounce).toStrictEqual(undefined);
|
|
3514
|
-
});
|
|
3515
|
-
|
|
3516
|
-
it("Do nothing wiht non areq event", async () => {
|
|
3517
|
-
basicMocks();
|
|
3518
|
-
await adapter.start();
|
|
3519
|
-
let deviceLeave;
|
|
3520
|
-
const object = mockZpiObject(Type.SREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123"});
|
|
3521
|
-
adapter.on("deviceLeave", (p) => {
|
|
3522
|
-
deviceLeave = p;
|
|
3523
|
-
});
|
|
3524
|
-
znpReceived(object);
|
|
3525
|
-
expect(deviceLeave).toStrictEqual(undefined);
|
|
3526
|
-
});
|
|
3527
|
-
|
|
3528
|
-
it("Get network parameters", async () => {
|
|
3529
|
-
basicMocks();
|
|
3530
|
-
await adapter.start();
|
|
3531
|
-
mockZnpRequest.mockClear();
|
|
3532
|
-
mockQueueExecute.mockClear();
|
|
3533
|
-
const result = await adapter.getNetworkParameters();
|
|
3534
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3535
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extNwkInfo", {});
|
|
3536
|
-
expect(result).toStrictEqual({channel: 21, extendedPanID: "0x00124b0009d69f77", panID: 123, nwkUpdateID: 0});
|
|
3537
|
-
});
|
|
3538
|
-
|
|
3539
|
-
it("Set interpan channel", async () => {
|
|
3540
|
-
basicMocks();
|
|
3541
|
-
await adapter.start();
|
|
3542
|
-
mockZnpRequest.mockClear();
|
|
3543
|
-
mockQueueExecute.mockClear();
|
|
3544
|
-
await adapter.setChannelInterPAN(14);
|
|
3545
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(2);
|
|
3546
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 1, data: [14]});
|
|
3547
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 2, data: [12]});
|
|
3548
|
-
|
|
3549
|
-
mockZnpRequest.mockClear();
|
|
3550
|
-
mockQueueExecute.mockClear();
|
|
3551
|
-
await adapter.setChannelInterPAN(15);
|
|
3552
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3553
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 1, data: [15]});
|
|
3554
|
-
});
|
|
3555
|
-
|
|
3556
|
-
it("Restore interpan channel", async () => {
|
|
3557
|
-
basicMocks();
|
|
3558
|
-
await adapter.start();
|
|
3559
|
-
mockZnpRequest.mockClear();
|
|
3560
|
-
mockQueueExecute.mockClear();
|
|
3561
|
-
await adapter.restoreChannelInterPAN();
|
|
3562
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3563
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 0, data: []});
|
|
3564
|
-
});
|
|
3565
|
-
|
|
3566
|
-
it("Send zcl frame interpan", async () => {
|
|
3567
|
-
basicMocks();
|
|
3568
|
-
await adapter.start();
|
|
3569
|
-
mockZnpRequest.mockClear();
|
|
3570
|
-
mockQueueExecute.mockClear();
|
|
3571
|
-
await adapter.sendZclFrameInterPANToIeeeAddr(touchlinkIdentifyRequest, "0x0017880104c9cd33");
|
|
3572
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3573
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
3574
|
-
4,
|
|
3575
|
-
"dataRequestExt",
|
|
3576
|
-
{
|
|
3577
|
-
clusterid: 4096,
|
|
3578
|
-
data: touchlinkIdentifyRequest.toBuffer(),
|
|
3579
|
-
destendpoint: 254,
|
|
3580
|
-
dstaddr: "0x0017880104c9cd33",
|
|
3581
|
-
len: 9,
|
|
3582
|
-
options: 0,
|
|
3583
|
-
radius: 30,
|
|
3584
|
-
srcendpoint: 12,
|
|
3585
|
-
transid: 1,
|
|
3586
|
-
dstaddrmode: 3,
|
|
3587
|
-
dstpanid: 65535,
|
|
3588
|
-
},
|
|
3589
|
-
undefined,
|
|
3590
|
-
);
|
|
3591
|
-
});
|
|
3592
|
-
|
|
3593
|
-
it("Send zcl frame interpan with response", async () => {
|
|
3594
|
-
basicMocks();
|
|
3595
|
-
await adapter.start();
|
|
3596
|
-
mockZnpRequest.mockClear();
|
|
3597
|
-
mockQueueExecute.mockClear();
|
|
3598
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
|
|
3599
|
-
clusterid: 4096,
|
|
3600
|
-
srcendpoint: 0xfe,
|
|
3601
|
-
srcaddr: 12394,
|
|
3602
|
-
linkquality: 101,
|
|
3603
|
-
groupid: 0,
|
|
3604
|
-
data: touchlinkScanResponse.toBuffer(),
|
|
3605
|
-
});
|
|
3606
|
-
|
|
3607
|
-
let result: ZclPayload | Promise<ZclPayload> = adapter.sendZclFrameInterPANBroadcast(touchlinkScanRequest, 1000);
|
|
3608
|
-
znpReceived(object);
|
|
3609
|
-
result = await result;
|
|
3610
|
-
|
|
3611
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3612
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(
|
|
3613
|
-
4,
|
|
3614
|
-
"dataRequestExt",
|
|
3615
|
-
{
|
|
3616
|
-
clusterid: 4096,
|
|
3617
|
-
data: touchlinkScanRequest.toBuffer(),
|
|
3618
|
-
destendpoint: 254,
|
|
3619
|
-
dstaddr: "0x000000000000ffff",
|
|
3620
|
-
len: 9,
|
|
3621
|
-
options: 0,
|
|
3622
|
-
radius: 30,
|
|
3623
|
-
srcendpoint: 12,
|
|
3624
|
-
transid: 1,
|
|
3625
|
-
dstaddrmode: 2,
|
|
3626
|
-
dstpanid: 65535,
|
|
3627
|
-
},
|
|
3628
|
-
undefined,
|
|
3629
|
-
);
|
|
3630
|
-
expect(deepClone(result)).toStrictEqual({
|
|
3631
|
-
clusterID: 4096,
|
|
3632
|
-
data: {
|
|
3633
|
-
type: "Buffer",
|
|
3634
|
-
data: [9, 12, 1, 1, 0, 0, 0, 10, 5, 6, 12, 0, 11, 0, 0, 0, 51, 205, 217, 4, 1, 33, 23, 0, 1, 12, 13, 0, 5, 0, 10, 5],
|
|
3635
|
-
},
|
|
3636
|
-
header: {
|
|
3637
|
-
frameControl: {frameType: 1, manufacturerSpecific: false, direction: 1, disableDefaultResponse: false, reservedBits: 0},
|
|
3638
|
-
transactionSequenceNumber: 12,
|
|
3639
|
-
commandIdentifier: 1,
|
|
3640
|
-
},
|
|
3641
|
-
address: 12394,
|
|
3642
|
-
endpoint: 254,
|
|
3643
|
-
linkquality: 101,
|
|
3644
|
-
groupID: 0,
|
|
3645
|
-
wasBroadcast: false,
|
|
3646
|
-
});
|
|
3647
|
-
});
|
|
3648
|
-
|
|
3649
|
-
it("Send zcl frame interpan throw exception when command has no response", async () => {
|
|
3650
|
-
basicMocks();
|
|
3651
|
-
await adapter.start();
|
|
3652
|
-
mockZnpRequest.mockClear();
|
|
3653
|
-
mockQueueExecute.mockClear();
|
|
3654
|
-
let error;
|
|
3655
|
-
try {
|
|
3656
|
-
await adapter.sendZclFrameInterPANBroadcast(touchlinkIdentifyRequest, 1000);
|
|
3657
|
-
} catch (e) {
|
|
3658
|
-
error = e;
|
|
3659
|
-
}
|
|
3660
|
-
expect(error).toStrictEqual(new Error(`Command 'identifyRequest' has no response, cannot wait for response`));
|
|
3661
|
-
});
|
|
3662
|
-
|
|
3663
|
-
it("Send zcl frame interpan throw exception data request fails", async () => {
|
|
3664
|
-
basicMocks();
|
|
3665
|
-
dataRequestExtCode = 99;
|
|
3666
|
-
await adapter.start();
|
|
3667
|
-
mockZnpRequest.mockClear();
|
|
3668
|
-
mockQueueExecute.mockClear();
|
|
3669
|
-
let error;
|
|
3670
|
-
try {
|
|
3671
|
-
await adapter.sendZclFrameInterPANBroadcast(touchlinkScanRequest, 1000);
|
|
3672
|
-
} catch (e) {
|
|
3673
|
-
error = e;
|
|
3674
|
-
}
|
|
3675
|
-
expect(error).toStrictEqual(new Error(`Data request failed with code '99'`));
|
|
3676
|
-
});
|
|
3677
|
-
|
|
3678
|
-
it("Refuse to start when ping fails", async () => {
|
|
3679
|
-
mockZnpRequest.mockImplementation((subsystem, command, payload, _expectedStatus) => {
|
|
3680
|
-
const missing = () => {
|
|
3681
|
-
const msg = `Not implemented - ${Subsystem[subsystem]} - ${command} - ${JSON.stringify(payload)}`;
|
|
3682
|
-
console.log(msg);
|
|
3683
|
-
throw new Error(msg);
|
|
3684
|
-
};
|
|
3685
|
-
|
|
3686
|
-
if (subsystem === Subsystem.SYS && command === "ping") {
|
|
3687
|
-
throw new Error("Couldnt lock port");
|
|
3688
|
-
}
|
|
3689
|
-
|
|
3690
|
-
missing();
|
|
3691
|
-
});
|
|
3692
|
-
|
|
3693
|
-
let error;
|
|
3694
|
-
try {
|
|
3695
|
-
await adapter.start();
|
|
3696
|
-
} catch (e) {
|
|
3697
|
-
error = e;
|
|
3698
|
-
}
|
|
3699
|
-
expect(error).toStrictEqual(new Error("Failed to connect to the adapter (Error: Couldnt lock port)"));
|
|
3700
|
-
});
|
|
3701
|
-
|
|
3702
|
-
it("Wait for", async () => {
|
|
3703
|
-
basicMocks();
|
|
3704
|
-
await adapter.start();
|
|
3705
|
-
|
|
3706
|
-
const responseFrame = Zcl.Frame.create(
|
|
3707
|
-
Zcl.FrameType.GLOBAL,
|
|
3708
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
3709
|
-
true,
|
|
3710
|
-
undefined,
|
|
3711
|
-
100,
|
|
3712
|
-
"readRsp",
|
|
3713
|
-
0,
|
|
3714
|
-
[{attrId: 0, attrData: 2, dataType: 32, status: 0}],
|
|
3715
|
-
{},
|
|
3716
|
-
);
|
|
3717
|
-
const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
|
|
3718
|
-
clusterid: 0,
|
|
3719
|
-
srcendpoint: 20,
|
|
3720
|
-
srcaddr: 2,
|
|
3721
|
-
linkquality: 101,
|
|
3722
|
-
groupid: 12,
|
|
3723
|
-
data: responseFrame.toBuffer(),
|
|
3724
|
-
});
|
|
3725
|
-
const wait = adapter.waitFor(2, 20, 0, 1, 100, 0, 1, 10);
|
|
3726
|
-
znpReceived(object);
|
|
3727
|
-
const result = await wait.promise;
|
|
3728
|
-
expect(result.endpoint).toStrictEqual(20);
|
|
3729
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3730
|
-
expect(result.linkquality).toStrictEqual(101);
|
|
3731
|
-
expect(result.address).toStrictEqual(2);
|
|
3732
|
-
expect(result.groupID).toStrictEqual(12);
|
|
3733
|
-
expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
|
|
3734
|
-
});
|
|
3735
|
-
|
|
3736
|
-
it("Command should fail when in interpan", async () => {
|
|
3737
|
-
const frame = Zcl.Frame.create(
|
|
3738
|
-
Zcl.FrameType.GLOBAL,
|
|
3739
|
-
Zcl.Direction.CLIENT_TO_SERVER,
|
|
3740
|
-
true,
|
|
3741
|
-
undefined,
|
|
3742
|
-
100,
|
|
3743
|
-
"writeNoRsp",
|
|
3744
|
-
0,
|
|
3745
|
-
[{attrId: 0, dataType: 0, attrData: null}],
|
|
3746
|
-
{},
|
|
3747
|
-
);
|
|
3748
|
-
basicMocks();
|
|
3749
|
-
await adapter.start();
|
|
3750
|
-
|
|
3751
|
-
await adapter.setChannelInterPAN(14);
|
|
3752
|
-
mockZnpRequest.mockClear();
|
|
3753
|
-
mockQueueExecute.mockClear();
|
|
3754
|
-
let error;
|
|
3755
|
-
try {
|
|
3756
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3757
|
-
} catch (e) {
|
|
3758
|
-
error = e;
|
|
3759
|
-
}
|
|
3760
|
-
expect(error).toStrictEqual(new Error("Cannot execute command, in Inter-PAN mode"));
|
|
3761
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(0);
|
|
3762
|
-
|
|
3763
|
-
await adapter.restoreChannelInterPAN();
|
|
3764
|
-
mockZnpRequest.mockClear();
|
|
3765
|
-
mockQueueExecute.mockClear();
|
|
3766
|
-
|
|
3767
|
-
await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
|
|
3768
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3769
|
-
});
|
|
3770
|
-
|
|
3771
|
-
it("Sends proper ZDO request payload for PERMIT_JOINING_REQUEST to target", async () => {
|
|
3772
|
-
basicMocks();
|
|
3773
|
-
await adapter.start();
|
|
3774
|
-
mockZnpRequestZdo.mockClear();
|
|
3775
|
-
|
|
3776
|
-
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
|
|
3777
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 250, 1, []);
|
|
3778
|
-
|
|
3779
|
-
await adapter.sendZdo("0x1122334455667788", 1234, clusterId, zdoPayload, true);
|
|
3780
|
-
|
|
3781
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
3782
|
-
clusterId,
|
|
3783
|
-
Buffer.from([AddressMode.ADDR_16BIT, 1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]),
|
|
3784
|
-
undefined,
|
|
3785
|
-
);
|
|
3786
|
-
});
|
|
3787
|
-
|
|
3788
|
-
it("Sends proper ZDO request payload for PERMIT_JOINING_REQUEST broadcast", async () => {
|
|
3789
|
-
basicMocks();
|
|
3790
|
-
await adapter.start();
|
|
3791
|
-
mockZnpRequestZdo.mockClear();
|
|
3792
|
-
|
|
3793
|
-
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
|
|
3794
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 250, 1, []);
|
|
3795
|
-
|
|
3796
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
|
|
3797
|
-
|
|
3798
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
3799
|
-
clusterId,
|
|
3800
|
-
Buffer.from([
|
|
3801
|
-
AddressMode.ADDR_BROADCAST,
|
|
3802
|
-
ZSpec.BroadcastAddress.DEFAULT & 0xff,
|
|
3803
|
-
(ZSpec.BroadcastAddress.DEFAULT >> 8) & 0xff,
|
|
3804
|
-
...zdoPayload,
|
|
3805
|
-
]),
|
|
3806
|
-
undefined,
|
|
3807
|
-
);
|
|
3808
|
-
});
|
|
3809
|
-
|
|
3810
|
-
it("Sends proper ZDO request payload for NWK_UPDATE_REQUEST UNICAST", async () => {
|
|
3811
|
-
basicMocks();
|
|
3812
|
-
await adapter.start();
|
|
3813
|
-
mockZnpRequestZdo.mockClear();
|
|
3814
|
-
|
|
3815
|
-
const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
|
|
3816
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, [15], 0xfe, 0, undefined, 0);
|
|
3817
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 0x123, clusterId, zdoPayload, true);
|
|
3818
|
-
|
|
3819
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
3820
|
-
clusterId,
|
|
3821
|
-
Buffer.from([
|
|
3822
|
-
0x123 & 0xff,
|
|
3823
|
-
(0x123 >> 8) & 0xff,
|
|
3824
|
-
AddressMode.ADDR_16BIT,
|
|
3825
|
-
...zdoPayload,
|
|
3826
|
-
0, // scancount
|
|
3827
|
-
0, // nwkmanageraddr
|
|
3828
|
-
0, // nwkmanageraddr
|
|
3829
|
-
]),
|
|
3830
|
-
undefined,
|
|
3831
|
-
);
|
|
3832
|
-
});
|
|
3833
|
-
|
|
3834
|
-
it("Sends proper ZDO request payload for NWK_UPDATE_REQUEST BROADCAST", async () => {
|
|
3835
|
-
basicMocks();
|
|
3836
|
-
await adapter.start();
|
|
3837
|
-
mockZnpRequestZdo.mockClear();
|
|
3838
|
-
|
|
3839
|
-
const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
|
|
3840
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, [15], 0xfe, 0, undefined, 0);
|
|
3841
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.SLEEPY, clusterId, zdoPayload, true);
|
|
3842
|
-
|
|
3843
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
3844
|
-
clusterId,
|
|
3845
|
-
Buffer.from([
|
|
3846
|
-
ZSpec.BroadcastAddress.SLEEPY & 0xff,
|
|
3847
|
-
(ZSpec.BroadcastAddress.SLEEPY >> 8) & 0xff,
|
|
3848
|
-
AddressMode.ADDR_BROADCAST,
|
|
3849
|
-
...zdoPayload,
|
|
3850
|
-
0, // scancount
|
|
3851
|
-
0, // nwkmanageraddr
|
|
3852
|
-
0, // nwkmanageraddr
|
|
3853
|
-
]),
|
|
3854
|
-
undefined,
|
|
3855
|
-
);
|
|
3856
|
-
});
|
|
3857
|
-
|
|
3858
|
-
it("Sends proper ZDO request payload for BIND_REQUEST/UNBIND_REQUEST UNICAST", async () => {
|
|
3859
|
-
basicMocks();
|
|
3860
|
-
await adapter.start();
|
|
3861
|
-
mockZnpRequestZdo.mockClear();
|
|
3862
|
-
|
|
3863
|
-
const clusterId = Zdo.ClusterId.BIND_REQUEST;
|
|
3864
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(
|
|
3865
|
-
false,
|
|
3866
|
-
clusterId,
|
|
3867
|
-
"0x1122334455667788",
|
|
3868
|
-
3,
|
|
3869
|
-
Zcl.Clusters.barrierControl.ID,
|
|
3870
|
-
Zdo.UNICAST_BINDING,
|
|
3871
|
-
"0x5544332211667788",
|
|
3872
|
-
0,
|
|
3873
|
-
5,
|
|
3874
|
-
);
|
|
3875
|
-
|
|
3876
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
|
|
3877
|
-
|
|
3878
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
|
|
3879
|
-
});
|
|
3880
|
-
|
|
3881
|
-
it("Sends proper ZDO request payload for BIND_REQUEST/UNBIND_REQUEST MULTICAST", async () => {
|
|
3882
|
-
basicMocks();
|
|
3883
|
-
await adapter.start();
|
|
3884
|
-
mockZnpRequestZdo.mockClear();
|
|
3885
|
-
|
|
3886
|
-
const clusterId = Zdo.ClusterId.BIND_REQUEST;
|
|
3887
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(
|
|
3888
|
-
false,
|
|
3889
|
-
clusterId,
|
|
3890
|
-
"0x1122334455667788",
|
|
3891
|
-
3,
|
|
3892
|
-
Zcl.Clusters.barrierControl.ID,
|
|
3893
|
-
Zdo.MULTICAST_BINDING,
|
|
3894
|
-
ZSpec.BLANK_EUI64,
|
|
3895
|
-
32,
|
|
3896
|
-
0,
|
|
3897
|
-
);
|
|
3898
|
-
|
|
3899
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
|
|
3900
|
-
|
|
3901
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(
|
|
3902
|
-
clusterId,
|
|
3903
|
-
Buffer.from([
|
|
3904
|
-
1234 & 0xff,
|
|
3905
|
-
(1234 >> 8) & 0xff,
|
|
3906
|
-
...zdoPayload,
|
|
3907
|
-
0, // match destination EUI64 length
|
|
3908
|
-
0, // match destination EUI64 length
|
|
3909
|
-
0, // match destination EUI64 length
|
|
3910
|
-
0, // match destination EUI64 length
|
|
3911
|
-
0, // match destination EUI64 length
|
|
3912
|
-
0, // match destination EUI64 length
|
|
3913
|
-
0, // endpoint
|
|
3914
|
-
]),
|
|
3915
|
-
undefined,
|
|
3916
|
-
);
|
|
3917
|
-
});
|
|
3918
|
-
|
|
3919
|
-
it("Sends proper ZDO request payload for NETWORK_ADDRESS_REQUEST", async () => {
|
|
3920
|
-
basicMocks();
|
|
3921
|
-
await adapter.start();
|
|
3922
|
-
mockZnpRequestZdo.mockClear();
|
|
3923
|
-
|
|
3924
|
-
const clusterId = Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
|
|
3925
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, "0x1122334455667788", false, 0);
|
|
3926
|
-
|
|
3927
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
|
|
3928
|
-
|
|
3929
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, zdoPayload, undefined);
|
|
3930
|
-
});
|
|
3931
|
-
|
|
3932
|
-
it("Sends proper ZDO request payload for generic logic request", async () => {
|
|
3933
|
-
basicMocks();
|
|
3934
|
-
await adapter.start();
|
|
3935
|
-
mockZnpRequestZdo.mockClear();
|
|
3936
|
-
|
|
3937
|
-
const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
|
|
3938
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 1234);
|
|
3939
|
-
|
|
3940
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
|
|
3941
|
-
|
|
3942
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
|
|
3943
|
-
});
|
|
3944
|
-
|
|
3945
|
-
it("Node descriptor request should discover route to fix potential fails", async () => {
|
|
3946
|
-
// https://github.com/Koenkk/zigbee2mqtt/issues/3276
|
|
3947
|
-
basicMocks();
|
|
3948
|
-
await adapter.start();
|
|
3949
|
-
mockZnpRequest.mockClear();
|
|
3950
|
-
mockZnpRequestZdo.mockClear();
|
|
3951
|
-
mockZnpRequestZdo.mockRejectedValueOnce(new Error("Failed"));
|
|
3952
|
-
|
|
3953
|
-
const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
|
|
3954
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 1234);
|
|
3955
|
-
|
|
3956
|
-
await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
|
|
3957
|
-
|
|
3958
|
-
expect(mockZnpRequestZdo).toHaveBeenCalledTimes(2);
|
|
3959
|
-
expect(mockZnpRequestZdo).toHaveBeenNthCalledWith(1, clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
|
|
3960
|
-
expect(mockZnpRequestZdo).toHaveBeenNthCalledWith(2, clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
|
|
3961
|
-
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
|
|
3962
|
-
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 1234, options: 0, radius: 30});
|
|
3963
|
-
});
|
|
3964
|
-
|
|
3965
|
-
it("Should throw error when ZDO call fails", async () => {
|
|
3966
|
-
basicMocks();
|
|
3967
|
-
await adapter.start();
|
|
3968
|
-
mockZnpRequest.mockClear();
|
|
3969
|
-
mockZnpRequestZdo.mockClear();
|
|
3970
|
-
mockZnpRequestZdo.mockRejectedValueOnce(new Error("Failed"));
|
|
3971
|
-
|
|
3972
|
-
const clusterId = Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST;
|
|
3973
|
-
const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 123, 0);
|
|
3974
|
-
|
|
3975
|
-
await expect(adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true)).rejects.toThrow("Failed");
|
|
3976
|
-
});
|
|
3977
|
-
|
|
3978
|
-
it("Should throw error when registerEndpoints fails", async () => {
|
|
3979
|
-
basicMocks();
|
|
3980
|
-
vi.spyOn(adapter, "sendZdo").mockResolvedValueOnce([Zdo.Status.NOT_ACTIVE, undefined]);
|
|
3981
|
-
|
|
3982
|
-
await expect(adapter.start()).rejects.toThrow(`Status 'NOT_ACTIVE'`);
|
|
3983
|
-
});
|
|
3984
|
-
});
|