zigbee-herdsman 6.0.2 → 6.0.4
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 +14 -0
- package/package.json +9 -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
package/test/greenpower.test.ts
DELETED
|
@@ -1,1408 +0,0 @@
|
|
|
1
|
-
import type {MockInstance} from "vitest";
|
|
2
|
-
import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
|
3
|
-
import type {ZclPayload} from "../src/adapter/events";
|
|
4
|
-
import {GreenPower} from "../src/controller/greenPower";
|
|
5
|
-
import type {GreenPowerDeviceJoinedPayload} from "../src/controller/tstype";
|
|
6
|
-
import {logger} from "../src/utils/logger";
|
|
7
|
-
import {GP_ENDPOINT, GP_GROUP_ID} from "../src/zspec/consts";
|
|
8
|
-
import * as Zcl from "../src/zspec/zcl";
|
|
9
|
-
|
|
10
|
-
describe("GreenPower", () => {
|
|
11
|
-
let gp: GreenPower;
|
|
12
|
-
let logDebugSpy: MockInstance;
|
|
13
|
-
let logInfoSpy: MockInstance;
|
|
14
|
-
let logWarningSpy: MockInstance;
|
|
15
|
-
let logErrorSpy: MockInstance;
|
|
16
|
-
|
|
17
|
-
const clearLogMocks = (): void => {
|
|
18
|
-
logDebugSpy.mockClear();
|
|
19
|
-
logInfoSpy.mockClear();
|
|
20
|
-
logWarningSpy.mockClear();
|
|
21
|
-
logErrorSpy.mockClear();
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const makeNotificationOptions = (
|
|
25
|
-
applicationId: number,
|
|
26
|
-
gpdfSecurityLevel: number,
|
|
27
|
-
gpdfSecurityKeyType: number,
|
|
28
|
-
bidirectionalInfo: number,
|
|
29
|
-
): number => {
|
|
30
|
-
return (applicationId & 0x7) | ((gpdfSecurityLevel & 0x3) << 6) | ((gpdfSecurityKeyType & 0x7) << 8) | ((bidirectionalInfo & 0x3) << 11);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const makeHeader = (
|
|
34
|
-
sequenceNumber: number,
|
|
35
|
-
commandIdentifier: number,
|
|
36
|
-
applicationId: number,
|
|
37
|
-
gpdfSecurityLevel: number,
|
|
38
|
-
gpdfSecurityKeyType: number,
|
|
39
|
-
bidirectionalInfo: number,
|
|
40
|
-
sourceId: number,
|
|
41
|
-
gpdSecurityFrameCounter: number,
|
|
42
|
-
gpdCommandId: number,
|
|
43
|
-
payloadLength: number,
|
|
44
|
-
options?: number,
|
|
45
|
-
): Buffer => {
|
|
46
|
-
const gpdHeader = Buffer.alloc(15);
|
|
47
|
-
gpdHeader.writeUInt8(0b00000001, 0); // frameControl: FrameType.SPECIFIC + Direction.CLIENT_TO_SERVER + disableDefaultResponse=false
|
|
48
|
-
gpdHeader.writeUInt8(sequenceNumber, 1);
|
|
49
|
-
gpdHeader.writeUInt8(commandIdentifier, 2);
|
|
50
|
-
gpdHeader.writeUInt16LE(options ?? makeNotificationOptions(applicationId, gpdfSecurityLevel, gpdfSecurityKeyType, bidirectionalInfo), 3);
|
|
51
|
-
gpdHeader.writeUInt32LE(sourceId, 5);
|
|
52
|
-
gpdHeader.writeUInt32LE(gpdSecurityFrameCounter, 9);
|
|
53
|
-
gpdHeader.writeUInt8(gpdCommandId, 13);
|
|
54
|
-
gpdHeader.writeUInt8(payloadLength, 14);
|
|
55
|
-
|
|
56
|
-
return gpdHeader;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const makeFooter = (options: number, gppNwkAddr?: number, gppGpdLink?: number, mic?: number): Buffer => {
|
|
60
|
-
const hasGppData = options & 0x800;
|
|
61
|
-
const hasMic = options & 0x200;
|
|
62
|
-
const gpdFooter = Buffer.alloc((hasGppData ? 3 : 0) + (hasMic ? 4 : 0));
|
|
63
|
-
|
|
64
|
-
if (hasGppData) {
|
|
65
|
-
gpdFooter.writeUInt16LE(gppNwkAddr!, 0);
|
|
66
|
-
gpdFooter.writeUInt8(gppGpdLink!, 2);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (hasMic) {
|
|
70
|
-
gpdFooter.writeUInt32LE(mic!, hasGppData ? 3 : 0);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return gpdFooter;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const makePayload = (sourceId: number, buffer: Buffer, linkQuality: number): ZclPayload => {
|
|
77
|
-
return {
|
|
78
|
-
clusterID: Zcl.Clusters.greenPower.ID,
|
|
79
|
-
header: Zcl.Header.fromBuffer(buffer),
|
|
80
|
-
address: sourceId & 0xffff,
|
|
81
|
-
data: buffer,
|
|
82
|
-
endpoint: GP_ENDPOINT,
|
|
83
|
-
linkquality: linkQuality,
|
|
84
|
-
groupID: GP_GROUP_ID,
|
|
85
|
-
wasBroadcast: true,
|
|
86
|
-
destinationEndpoint: GP_ENDPOINT,
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
beforeAll(() => {
|
|
91
|
-
vi.useFakeTimers();
|
|
92
|
-
|
|
93
|
-
logDebugSpy = vi.spyOn(logger, "debug");
|
|
94
|
-
logInfoSpy = vi.spyOn(logger, "info");
|
|
95
|
-
logWarningSpy = vi.spyOn(logger, "warning");
|
|
96
|
-
logErrorSpy = vi.spyOn(logger, "error");
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
beforeEach(() => {
|
|
100
|
-
clearLogMocks();
|
|
101
|
-
|
|
102
|
-
gp = new GreenPower(
|
|
103
|
-
// @ts-expect-error minimal mock
|
|
104
|
-
{
|
|
105
|
-
getCoordinatorIEEE: vi.fn(),
|
|
106
|
-
sendZclFrameToAll: vi.fn(),
|
|
107
|
-
sendZclFrameToEndpoint: vi.fn(),
|
|
108
|
-
getNetworkParameters: vi.fn(),
|
|
109
|
-
},
|
|
110
|
-
);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
afterAll(() => {
|
|
114
|
-
vi.useRealTimers();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("encodes & decodes pairing options", () => {
|
|
118
|
-
let rawByte = 0b000000000110101000;
|
|
119
|
-
let rawOptions = {
|
|
120
|
-
appId: 0,
|
|
121
|
-
addSink: true,
|
|
122
|
-
removeGpd: false,
|
|
123
|
-
communicationMode: 0b01,
|
|
124
|
-
gpdFixed: true,
|
|
125
|
-
gpdMacSeqNumCapabilities: true,
|
|
126
|
-
securityLevel: 0,
|
|
127
|
-
securityKeyType: 0,
|
|
128
|
-
gpdSecurityFrameCounterPresent: false,
|
|
129
|
-
gpdSecurityKeyPresent: false,
|
|
130
|
-
assignedAliasPresent: false,
|
|
131
|
-
groupcastRadiusPresent: false,
|
|
132
|
-
};
|
|
133
|
-
let options = GreenPower.decodePairingOptions(rawByte);
|
|
134
|
-
let byte = GreenPower.encodePairingOptions(rawOptions);
|
|
135
|
-
|
|
136
|
-
expect(options).toStrictEqual(rawOptions);
|
|
137
|
-
expect(rawByte).toStrictEqual(byte);
|
|
138
|
-
|
|
139
|
-
rawByte = 0b001110010101001000;
|
|
140
|
-
rawOptions = {
|
|
141
|
-
appId: 0,
|
|
142
|
-
addSink: true,
|
|
143
|
-
removeGpd: false,
|
|
144
|
-
communicationMode: 0b10,
|
|
145
|
-
gpdFixed: false,
|
|
146
|
-
gpdMacSeqNumCapabilities: true,
|
|
147
|
-
securityLevel: 0b10,
|
|
148
|
-
securityKeyType: 0b100,
|
|
149
|
-
gpdSecurityFrameCounterPresent: true,
|
|
150
|
-
gpdSecurityKeyPresent: true,
|
|
151
|
-
assignedAliasPresent: false,
|
|
152
|
-
groupcastRadiusPresent: false,
|
|
153
|
-
};
|
|
154
|
-
options = GreenPower.decodePairingOptions(rawByte);
|
|
155
|
-
byte = GreenPower.encodePairingOptions(rawOptions);
|
|
156
|
-
|
|
157
|
-
expect(options).toStrictEqual(rawOptions);
|
|
158
|
-
expect(rawByte).toStrictEqual(byte);
|
|
159
|
-
|
|
160
|
-
rawByte = 0b001110010101101000;
|
|
161
|
-
rawOptions = {
|
|
162
|
-
appId: 0,
|
|
163
|
-
addSink: true,
|
|
164
|
-
removeGpd: false,
|
|
165
|
-
communicationMode: 0b11,
|
|
166
|
-
gpdFixed: false,
|
|
167
|
-
gpdMacSeqNumCapabilities: true,
|
|
168
|
-
securityLevel: 0b10,
|
|
169
|
-
securityKeyType: 0b100,
|
|
170
|
-
gpdSecurityFrameCounterPresent: true,
|
|
171
|
-
gpdSecurityKeyPresent: true,
|
|
172
|
-
assignedAliasPresent: false,
|
|
173
|
-
groupcastRadiusPresent: false,
|
|
174
|
-
};
|
|
175
|
-
options = GreenPower.decodePairingOptions(rawByte);
|
|
176
|
-
byte = GreenPower.encodePairingOptions(rawOptions);
|
|
177
|
-
|
|
178
|
-
expect(options).toStrictEqual(rawOptions);
|
|
179
|
-
expect(rawByte).toStrictEqual(byte);
|
|
180
|
-
|
|
181
|
-
rawByte = 0b000000000110110000;
|
|
182
|
-
rawOptions = {
|
|
183
|
-
appId: 0,
|
|
184
|
-
addSink: false,
|
|
185
|
-
removeGpd: true,
|
|
186
|
-
communicationMode: 0b01,
|
|
187
|
-
gpdFixed: true,
|
|
188
|
-
gpdMacSeqNumCapabilities: true,
|
|
189
|
-
securityLevel: 0b00,
|
|
190
|
-
securityKeyType: 0b000,
|
|
191
|
-
gpdSecurityFrameCounterPresent: false,
|
|
192
|
-
gpdSecurityKeyPresent: false,
|
|
193
|
-
assignedAliasPresent: false,
|
|
194
|
-
groupcastRadiusPresent: false,
|
|
195
|
-
};
|
|
196
|
-
options = GreenPower.decodePairingOptions(rawByte);
|
|
197
|
-
byte = GreenPower.encodePairingOptions(rawOptions);
|
|
198
|
-
|
|
199
|
-
expect(options).toStrictEqual(rawOptions);
|
|
200
|
-
expect(rawByte).toStrictEqual(byte);
|
|
201
|
-
|
|
202
|
-
// coverage
|
|
203
|
-
rawByte = 0b110000000010110000;
|
|
204
|
-
rawOptions = {
|
|
205
|
-
appId: 0,
|
|
206
|
-
addSink: false,
|
|
207
|
-
removeGpd: true,
|
|
208
|
-
communicationMode: 0b01,
|
|
209
|
-
gpdFixed: true,
|
|
210
|
-
gpdMacSeqNumCapabilities: false,
|
|
211
|
-
securityLevel: 0b00,
|
|
212
|
-
securityKeyType: 0b000,
|
|
213
|
-
gpdSecurityFrameCounterPresent: false,
|
|
214
|
-
gpdSecurityKeyPresent: false,
|
|
215
|
-
assignedAliasPresent: true,
|
|
216
|
-
groupcastRadiusPresent: true,
|
|
217
|
-
};
|
|
218
|
-
options = GreenPower.decodePairingOptions(rawByte);
|
|
219
|
-
byte = GreenPower.encodePairingOptions(rawOptions);
|
|
220
|
-
|
|
221
|
-
expect(options).toStrictEqual(rawOptions);
|
|
222
|
-
expect(rawByte).toStrictEqual(byte);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("encodes & decodes commissioning mode options", () => {
|
|
226
|
-
let rawByte = 0x0b;
|
|
227
|
-
let rawOptions = {action: 1, commissioningWindowPresent: true, exitMode: 0b10, channelPresent: false, unicastCommunication: false};
|
|
228
|
-
let options = GreenPower.decodeCommissioningModeOptions(rawByte);
|
|
229
|
-
let byte = GreenPower.encodeCommissioningModeOptions(rawOptions);
|
|
230
|
-
|
|
231
|
-
expect(options).toStrictEqual(rawOptions);
|
|
232
|
-
expect(rawByte).toStrictEqual(byte);
|
|
233
|
-
rawByte = 0x2b;
|
|
234
|
-
rawOptions = {action: 1, commissioningWindowPresent: true, exitMode: 0b10, channelPresent: false, unicastCommunication: true};
|
|
235
|
-
options = GreenPower.decodeCommissioningModeOptions(rawByte);
|
|
236
|
-
byte = GreenPower.encodeCommissioningModeOptions(rawOptions);
|
|
237
|
-
|
|
238
|
-
expect(options).toStrictEqual(rawOptions);
|
|
239
|
-
expect(rawByte).toStrictEqual(byte);
|
|
240
|
-
rawByte = 0x0a;
|
|
241
|
-
rawOptions = {action: 0, commissioningWindowPresent: true, exitMode: 0b10, channelPresent: false, unicastCommunication: false};
|
|
242
|
-
options = GreenPower.decodeCommissioningModeOptions(rawByte);
|
|
243
|
-
byte = GreenPower.encodeCommissioningModeOptions(rawOptions);
|
|
244
|
-
|
|
245
|
-
expect(options).toStrictEqual(rawOptions);
|
|
246
|
-
expect(rawByte).toStrictEqual(byte);
|
|
247
|
-
expect(options).toStrictEqual(rawOptions);
|
|
248
|
-
expect(rawByte).toStrictEqual(byte);
|
|
249
|
-
|
|
250
|
-
// coverage
|
|
251
|
-
rawByte = 0b111100;
|
|
252
|
-
rawOptions = {action: 0, commissioningWindowPresent: false, exitMode: 0b11, channelPresent: true, unicastCommunication: true};
|
|
253
|
-
options = GreenPower.decodeCommissioningModeOptions(rawByte);
|
|
254
|
-
byte = GreenPower.encodeCommissioningModeOptions(rawOptions);
|
|
255
|
-
|
|
256
|
-
expect(options).toStrictEqual(rawOptions);
|
|
257
|
-
expect(rawByte).toStrictEqual(byte);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("omits GPP data from raw payload", async () => {
|
|
261
|
-
const addr = {applicationId: 0, sourceId: 2777252112, endpoint: 0};
|
|
262
|
-
const options = 0x800;
|
|
263
|
-
const sequenceNumber = 18;
|
|
264
|
-
const gpdSecurityFrameCounter = 17326;
|
|
265
|
-
const gpdCommandId = 38;
|
|
266
|
-
const gpdCommandPayload = Buffer.from([0x3e]);
|
|
267
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
268
|
-
const gppNwkAddr = 24404;
|
|
269
|
-
const gppGpdLink = 207;
|
|
270
|
-
|
|
271
|
-
const gpdHeader = makeHeader(
|
|
272
|
-
sequenceNumber,
|
|
273
|
-
commandIdentifier,
|
|
274
|
-
0,
|
|
275
|
-
0,
|
|
276
|
-
0,
|
|
277
|
-
0,
|
|
278
|
-
addr.sourceId,
|
|
279
|
-
gpdSecurityFrameCounter,
|
|
280
|
-
gpdCommandId,
|
|
281
|
-
gpdCommandPayload.length,
|
|
282
|
-
options,
|
|
283
|
-
);
|
|
284
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink);
|
|
285
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
286
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
287
|
-
const retFrame = await gp.processCommand(payload, frame, undefined);
|
|
288
|
-
|
|
289
|
-
expect(frame.payload.gppNwkAddr).toStrictEqual(gppNwkAddr);
|
|
290
|
-
expect(frame.payload.gppGpdLink).toStrictEqual(gppGpdLink);
|
|
291
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({raw: gpdCommandPayload});
|
|
292
|
-
expect(retFrame.payload.gppNwkAddr).toStrictEqual(gppNwkAddr);
|
|
293
|
-
expect(retFrame.payload.gppGpdLink).toStrictEqual(gppGpdLink);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it("omits MIC from raw payload", async () => {
|
|
297
|
-
const securityKey = Buffer.from([227, 227, 225, 134, 235, 104, 141, 250, 162, 211, 104, 147, 201, 146, 67, 175]);
|
|
298
|
-
const addr = {applicationId: 0, sourceId: 2777252112, endpoint: 0};
|
|
299
|
-
const options = 0x30 | 0x200;
|
|
300
|
-
const sequenceNumber = 18;
|
|
301
|
-
const gpdSecurityFrameCounter = 17326;
|
|
302
|
-
const gpdCommandId = 38;
|
|
303
|
-
const gpdCommandPayload = Buffer.from([0x3e]);
|
|
304
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
305
|
-
const mic = 1441399364;
|
|
306
|
-
|
|
307
|
-
const gpdHeader = makeHeader(
|
|
308
|
-
sequenceNumber,
|
|
309
|
-
commandIdentifier,
|
|
310
|
-
0,
|
|
311
|
-
0,
|
|
312
|
-
0,
|
|
313
|
-
0,
|
|
314
|
-
addr.sourceId,
|
|
315
|
-
gpdSecurityFrameCounter,
|
|
316
|
-
gpdCommandId,
|
|
317
|
-
gpdCommandPayload.length,
|
|
318
|
-
options,
|
|
319
|
-
);
|
|
320
|
-
const gpdFooter = makeFooter(options, undefined, undefined, mic);
|
|
321
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
322
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
323
|
-
const retFrame = await gp.processCommand(payload, frame, securityKey);
|
|
324
|
-
|
|
325
|
-
expect(frame.payload.mic).toBeDefined(); // garbage
|
|
326
|
-
expect(retFrame.payload.commandID).toStrictEqual(0x21); // just to be sure it decrypted properly
|
|
327
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({raw: Buffer.from([207 /* decrypted, bogus data */])});
|
|
328
|
-
expect(retFrame.payload.mic).toStrictEqual(undefined); // removed once decrypted
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it("omits GPP data and MIC from raw payload", async () => {
|
|
332
|
-
const securityKey = Buffer.from([227, 227, 225, 134, 235, 104, 141, 250, 162, 211, 104, 147, 201, 146, 67, 175]);
|
|
333
|
-
const addr = {applicationId: 0, sourceId: 2777252112, endpoint: 0};
|
|
334
|
-
const options = 0x30 | 0x200 | 0x800;
|
|
335
|
-
const sequenceNumber = 18;
|
|
336
|
-
const gpdSecurityFrameCounter = 17326;
|
|
337
|
-
const gpdCommandId = 38;
|
|
338
|
-
const gpdCommandPayload = Buffer.from([0x3e]);
|
|
339
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
340
|
-
const gppNwkAddr = 24404;
|
|
341
|
-
const gppGpdLink = 207;
|
|
342
|
-
const mic = 1441399364;
|
|
343
|
-
|
|
344
|
-
const gpdHeader = makeHeader(
|
|
345
|
-
sequenceNumber,
|
|
346
|
-
commandIdentifier,
|
|
347
|
-
0,
|
|
348
|
-
0,
|
|
349
|
-
0,
|
|
350
|
-
0,
|
|
351
|
-
addr.sourceId,
|
|
352
|
-
gpdSecurityFrameCounter,
|
|
353
|
-
gpdCommandId,
|
|
354
|
-
gpdCommandPayload.length,
|
|
355
|
-
options,
|
|
356
|
-
);
|
|
357
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
358
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
359
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
360
|
-
const retFrame = await gp.processCommand(payload, frame, securityKey);
|
|
361
|
-
|
|
362
|
-
expect(frame.payload.gppNwkAddr).toBeDefined(); // garbage
|
|
363
|
-
expect(frame.payload.gppGpdLink).toBeDefined(); // garbage
|
|
364
|
-
expect(frame.payload.mic).toBeDefined(); // garbage
|
|
365
|
-
expect(retFrame.payload.commandID).toStrictEqual(0x21); // just to be sure it decrypted properly
|
|
366
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({raw: Buffer.from([207 /* decrypted, bogus data */])});
|
|
367
|
-
expect(retFrame.payload.gppNwkAddr).toStrictEqual(gppNwkAddr); // removed once decrypted
|
|
368
|
-
expect(retFrame.payload.gppGpdLink).toStrictEqual(gppGpdLink); // removed once decrypted
|
|
369
|
-
expect(retFrame.payload.mic).toStrictEqual(undefined); // removed once decrypted
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
it("does not parse command frame when FULLENCR security level - SINK", async () => {
|
|
373
|
-
const addr = {applicationId: 0, sourceId: 2888399791, endpoint: 0};
|
|
374
|
-
const securityLevelFullEncr = 3;
|
|
375
|
-
const securityKeyTypeNWK = 1;
|
|
376
|
-
const gpdLink = 207;
|
|
377
|
-
const sequenceNumber = 143;
|
|
378
|
-
const bidirectionalInfo = 0;
|
|
379
|
-
const gpdSecurityFrameCounter = 3727;
|
|
380
|
-
const gpdCommandId = 227; // this would otherwise be CHANNEL_REQUEST and result in bad parsing
|
|
381
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
382
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
383
|
-
|
|
384
|
-
const gpdHeader = makeHeader(
|
|
385
|
-
sequenceNumber,
|
|
386
|
-
commandIdentifier,
|
|
387
|
-
addr.applicationId,
|
|
388
|
-
securityLevelFullEncr,
|
|
389
|
-
securityKeyTypeNWK,
|
|
390
|
-
bidirectionalInfo,
|
|
391
|
-
addr.sourceId,
|
|
392
|
-
gpdSecurityFrameCounter,
|
|
393
|
-
gpdCommandId,
|
|
394
|
-
gpdCommandPayload.length,
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
398
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
399
|
-
|
|
400
|
-
expect(frame.payload.commandFrame).toBeUndefined(); // as opposed to `{}` when parsing (payloadSize=0)
|
|
401
|
-
|
|
402
|
-
const retFrame = await gp.processCommand(payload, frame, Buffer.alloc(16) /* just for the codepath, decrypting not important */);
|
|
403
|
-
|
|
404
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
405
|
-
1,
|
|
406
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x9d srcID=2888399791 gpp=NO",
|
|
407
|
-
"zh:controller:greenpower",
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
411
|
-
clonedFrame.payload.commandID = 0x9d;
|
|
412
|
-
clonedFrame.payload.options = 256;
|
|
413
|
-
clonedFrame.payload.commandFrame = {};
|
|
414
|
-
|
|
415
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
it("does not parse command frame when FULLENCR security level - GPP", async () => {
|
|
419
|
-
const addr = {applicationId: 0, sourceId: 2888399791, endpoint: 0};
|
|
420
|
-
const gpdLink = 207;
|
|
421
|
-
const sequenceNumber = 143;
|
|
422
|
-
const gpdSecurityFrameCounter = 3727;
|
|
423
|
-
const gpdCommandId = 227; // this would otherwise be CHANNEL_REQUEST and result in bad parsing
|
|
424
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
425
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
426
|
-
const gppNwkAddr = 24404;
|
|
427
|
-
const gppGpdLink = 123;
|
|
428
|
-
const mic = 456;
|
|
429
|
-
const options = 2864;
|
|
430
|
-
|
|
431
|
-
const gpdHeader = makeHeader(
|
|
432
|
-
sequenceNumber,
|
|
433
|
-
commandIdentifier,
|
|
434
|
-
0,
|
|
435
|
-
0,
|
|
436
|
-
0,
|
|
437
|
-
0,
|
|
438
|
-
addr.sourceId,
|
|
439
|
-
gpdSecurityFrameCounter,
|
|
440
|
-
gpdCommandId,
|
|
441
|
-
gpdCommandPayload.length,
|
|
442
|
-
options,
|
|
443
|
-
);
|
|
444
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
445
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), gpdLink);
|
|
446
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
447
|
-
|
|
448
|
-
expect(frame.payload.commandFrame).toBeUndefined(); // as opposed to `{}` when parsing (payloadSize=0)
|
|
449
|
-
|
|
450
|
-
const retFrame = await gp.processCommand(payload, frame, Buffer.alloc(16) /* just for the codepath, decrypting not important */);
|
|
451
|
-
|
|
452
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
453
|
-
1,
|
|
454
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x9d srcID=2888399791 gpp=24404 rssi=59 linkQuality=Moderate",
|
|
455
|
-
"zh:controller:greenpower",
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
459
|
-
clonedFrame.payload.commandID = 0x9d;
|
|
460
|
-
clonedFrame.payload.options = 2304;
|
|
461
|
-
clonedFrame.payload.commandFrame = {};
|
|
462
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
463
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
464
|
-
delete clonedFrame.payload.mic;
|
|
465
|
-
|
|
466
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// @see https://github.com/Koenkk/zigbee2mqtt/issues/19405#issuecomment-2727338024
|
|
470
|
-
it("FULLENCR ZT-LP-ZEU2S-WH-MS MOES 2-gang vectors from ember", async () => {
|
|
471
|
-
let joinData: GreenPowerDeviceJoinedPayload | undefined;
|
|
472
|
-
|
|
473
|
-
gp.on("deviceJoined", (payload) => {
|
|
474
|
-
joinData = payload;
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
const addr = {applicationId: 0, sourceId: 1496140231, endpoint: 0};
|
|
478
|
-
|
|
479
|
-
{
|
|
480
|
-
const gpdLink = 214;
|
|
481
|
-
const sequenceNumber = 19;
|
|
482
|
-
const gpdfSecurityLevel = 0; // NONE
|
|
483
|
-
const gpdfSecurityKeyType = 0; // NONE
|
|
484
|
-
const bidirectionalInfo = 0;
|
|
485
|
-
const gpdSecurityFrameCounter = 4294967295;
|
|
486
|
-
const gpdCommandId = 224;
|
|
487
|
-
const gpdCommandPayload = Buffer.from("0289f31adb70a88d71196ee50c03580537767de27ad5331309000037647a62697061304047503030303157", "hex");
|
|
488
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
489
|
-
|
|
490
|
-
const gpdHeader = makeHeader(
|
|
491
|
-
sequenceNumber,
|
|
492
|
-
commandIdentifier,
|
|
493
|
-
addr.applicationId,
|
|
494
|
-
gpdfSecurityLevel,
|
|
495
|
-
gpdfSecurityKeyType,
|
|
496
|
-
bidirectionalInfo,
|
|
497
|
-
addr.sourceId,
|
|
498
|
-
gpdSecurityFrameCounter,
|
|
499
|
-
gpdCommandId,
|
|
500
|
-
gpdCommandPayload.length,
|
|
501
|
-
);
|
|
502
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
503
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
504
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey); // always undefined since not yet joined
|
|
505
|
-
|
|
506
|
-
await vi.waitUntil(() => joinData !== undefined);
|
|
507
|
-
|
|
508
|
-
expect(joinData).toStrictEqual({
|
|
509
|
-
sourceID: addr.sourceId,
|
|
510
|
-
deviceID: frame.payload.commandFrame.deviceID,
|
|
511
|
-
networkAddress: addr.sourceId & 0xffff,
|
|
512
|
-
securityKey: frame.payload.commandFrame.securityKey,
|
|
513
|
-
});
|
|
514
|
-
expect(logInfoSpy).toHaveBeenNthCalledWith(1, "[COMMISSIONING] srcID=1496140231 gpp=NO", "zh:controller:greenpower");
|
|
515
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
516
|
-
1,
|
|
517
|
-
"[PAIRING] srcID=1496140231 gpp=NO options=58696 (addSink=true commMode=2)",
|
|
518
|
-
"zh:controller:greenpower",
|
|
519
|
-
);
|
|
520
|
-
|
|
521
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
522
|
-
clonedFrame.payload.commandID = 0xe0;
|
|
523
|
-
clonedFrame.payload.options = 0;
|
|
524
|
-
clonedFrame.payload.commandFrame = {
|
|
525
|
-
deviceID: 2,
|
|
526
|
-
options: 137,
|
|
527
|
-
extendedOptions: 243,
|
|
528
|
-
securityKey: joinData?.securityKey,
|
|
529
|
-
keyMic: 869628642,
|
|
530
|
-
outgoingCounter: 2323,
|
|
531
|
-
applicationInfo: addr.applicationId,
|
|
532
|
-
manufacturerID: 0,
|
|
533
|
-
modelID: 0,
|
|
534
|
-
numGpdCommands: 0,
|
|
535
|
-
gpdCommandIdList: Buffer.from([]),
|
|
536
|
-
numServerClusters: 0,
|
|
537
|
-
numClientClusters: 0,
|
|
538
|
-
gpdServerClusters: Buffer.from([]),
|
|
539
|
-
gpdClientClusters: Buffer.from([]),
|
|
540
|
-
genericSwitchConfig: 0,
|
|
541
|
-
currentContactStatus: 0,
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
545
|
-
expect(retFrame.payload.commandFrame.securityKey).toStrictEqual(joinData?.securityKey);
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
clearLogMocks();
|
|
549
|
-
|
|
550
|
-
const securityLevelFullEncr = 3;
|
|
551
|
-
const securityKeyTypeNWK = 1;
|
|
552
|
-
|
|
553
|
-
// left
|
|
554
|
-
{
|
|
555
|
-
const gpdLink = 220;
|
|
556
|
-
const sequenceNumber = 28;
|
|
557
|
-
const bidirectionalInfo = 0;
|
|
558
|
-
const gpdSecurityFrameCounter = 2332;
|
|
559
|
-
const gpdCommandId = 136;
|
|
560
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
561
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
562
|
-
|
|
563
|
-
const gpdHeader = makeHeader(
|
|
564
|
-
sequenceNumber,
|
|
565
|
-
commandIdentifier,
|
|
566
|
-
addr.applicationId,
|
|
567
|
-
securityLevelFullEncr,
|
|
568
|
-
securityKeyTypeNWK,
|
|
569
|
-
bidirectionalInfo,
|
|
570
|
-
addr.sourceId,
|
|
571
|
-
gpdSecurityFrameCounter,
|
|
572
|
-
gpdCommandId,
|
|
573
|
-
gpdCommandPayload.length,
|
|
574
|
-
);
|
|
575
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
576
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
577
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
578
|
-
|
|
579
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
580
|
-
1,
|
|
581
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=1496140231 gpp=NO",
|
|
582
|
-
"zh:controller:greenpower",
|
|
583
|
-
);
|
|
584
|
-
|
|
585
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
586
|
-
clonedFrame.payload.commandID = 0x20;
|
|
587
|
-
clonedFrame.payload.options = 256;
|
|
588
|
-
clonedFrame.payload.commandFrame = {};
|
|
589
|
-
|
|
590
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
591
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
clearLogMocks();
|
|
595
|
-
|
|
596
|
-
// left
|
|
597
|
-
{
|
|
598
|
-
const gpdLink = 220;
|
|
599
|
-
const sequenceNumber = 46;
|
|
600
|
-
const bidirectionalInfo = 0;
|
|
601
|
-
const gpdSecurityFrameCounter = 2350;
|
|
602
|
-
const gpdCommandId = 152;
|
|
603
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
604
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
605
|
-
|
|
606
|
-
const gpdHeader = makeHeader(
|
|
607
|
-
sequenceNumber,
|
|
608
|
-
commandIdentifier,
|
|
609
|
-
addr.applicationId,
|
|
610
|
-
securityLevelFullEncr,
|
|
611
|
-
securityKeyTypeNWK,
|
|
612
|
-
bidirectionalInfo,
|
|
613
|
-
addr.sourceId,
|
|
614
|
-
gpdSecurityFrameCounter,
|
|
615
|
-
gpdCommandId,
|
|
616
|
-
gpdCommandPayload.length,
|
|
617
|
-
);
|
|
618
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
619
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
620
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
621
|
-
|
|
622
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
623
|
-
1,
|
|
624
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=1496140231 gpp=NO",
|
|
625
|
-
"zh:controller:greenpower",
|
|
626
|
-
);
|
|
627
|
-
|
|
628
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
629
|
-
clonedFrame.payload.commandID = 0x20;
|
|
630
|
-
clonedFrame.payload.options = 256;
|
|
631
|
-
clonedFrame.payload.commandFrame = {};
|
|
632
|
-
|
|
633
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
634
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
clearLogMocks();
|
|
638
|
-
|
|
639
|
-
// left
|
|
640
|
-
{
|
|
641
|
-
const gpdLink = 223;
|
|
642
|
-
const sequenceNumber = 55;
|
|
643
|
-
const bidirectionalInfo = 0;
|
|
644
|
-
const gpdSecurityFrameCounter = 2359;
|
|
645
|
-
const gpdCommandId = 189;
|
|
646
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
647
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
648
|
-
|
|
649
|
-
const gpdHeader = makeHeader(
|
|
650
|
-
sequenceNumber,
|
|
651
|
-
commandIdentifier,
|
|
652
|
-
addr.applicationId,
|
|
653
|
-
securityLevelFullEncr,
|
|
654
|
-
securityKeyTypeNWK,
|
|
655
|
-
bidirectionalInfo,
|
|
656
|
-
addr.sourceId,
|
|
657
|
-
gpdSecurityFrameCounter,
|
|
658
|
-
gpdCommandId,
|
|
659
|
-
gpdCommandPayload.length,
|
|
660
|
-
);
|
|
661
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
662
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
663
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
664
|
-
|
|
665
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
666
|
-
1,
|
|
667
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=1496140231 gpp=NO",
|
|
668
|
-
"zh:controller:greenpower",
|
|
669
|
-
);
|
|
670
|
-
|
|
671
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
672
|
-
clonedFrame.payload.commandID = 0x20;
|
|
673
|
-
clonedFrame.payload.options = 256;
|
|
674
|
-
clonedFrame.payload.commandFrame = {};
|
|
675
|
-
|
|
676
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
677
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
clearLogMocks();
|
|
681
|
-
|
|
682
|
-
// right
|
|
683
|
-
{
|
|
684
|
-
const gpdLink = 218;
|
|
685
|
-
const sequenceNumber = 37;
|
|
686
|
-
const bidirectionalInfo = 0;
|
|
687
|
-
const gpdSecurityFrameCounter = 2341;
|
|
688
|
-
const gpdCommandId = 172;
|
|
689
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
690
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
691
|
-
|
|
692
|
-
const gpdHeader = makeHeader(
|
|
693
|
-
sequenceNumber,
|
|
694
|
-
commandIdentifier,
|
|
695
|
-
addr.applicationId,
|
|
696
|
-
securityLevelFullEncr,
|
|
697
|
-
securityKeyTypeNWK,
|
|
698
|
-
bidirectionalInfo,
|
|
699
|
-
addr.sourceId,
|
|
700
|
-
gpdSecurityFrameCounter,
|
|
701
|
-
gpdCommandId,
|
|
702
|
-
gpdCommandPayload.length,
|
|
703
|
-
);
|
|
704
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
705
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
706
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
707
|
-
|
|
708
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
709
|
-
1,
|
|
710
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=1496140231 gpp=NO",
|
|
711
|
-
"zh:controller:greenpower",
|
|
712
|
-
);
|
|
713
|
-
|
|
714
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
715
|
-
clonedFrame.payload.commandID = 0x21;
|
|
716
|
-
clonedFrame.payload.options = 256;
|
|
717
|
-
clonedFrame.payload.commandFrame = {};
|
|
718
|
-
|
|
719
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
720
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
clearLogMocks();
|
|
724
|
-
|
|
725
|
-
// right
|
|
726
|
-
{
|
|
727
|
-
const gpdLink = 222;
|
|
728
|
-
const sequenceNumber = 64;
|
|
729
|
-
const bidirectionalInfo = 0;
|
|
730
|
-
const gpdSecurityFrameCounter = 2368;
|
|
731
|
-
const gpdCommandId = 159;
|
|
732
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
733
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
734
|
-
|
|
735
|
-
const gpdHeader = makeHeader(
|
|
736
|
-
sequenceNumber,
|
|
737
|
-
commandIdentifier,
|
|
738
|
-
addr.applicationId,
|
|
739
|
-
securityLevelFullEncr,
|
|
740
|
-
securityKeyTypeNWK,
|
|
741
|
-
bidirectionalInfo,
|
|
742
|
-
addr.sourceId,
|
|
743
|
-
gpdSecurityFrameCounter,
|
|
744
|
-
gpdCommandId,
|
|
745
|
-
gpdCommandPayload.length,
|
|
746
|
-
);
|
|
747
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
748
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
749
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
750
|
-
|
|
751
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
752
|
-
1,
|
|
753
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=1496140231 gpp=NO",
|
|
754
|
-
"zh:controller:greenpower",
|
|
755
|
-
);
|
|
756
|
-
|
|
757
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
758
|
-
clonedFrame.payload.commandID = 0x21;
|
|
759
|
-
clonedFrame.payload.options = 256;
|
|
760
|
-
clonedFrame.payload.commandFrame = {};
|
|
761
|
-
|
|
762
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
763
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
clearLogMocks();
|
|
767
|
-
|
|
768
|
-
// right
|
|
769
|
-
{
|
|
770
|
-
const gpdLink = 222;
|
|
771
|
-
const sequenceNumber = 73;
|
|
772
|
-
const bidirectionalInfo = 0;
|
|
773
|
-
const gpdSecurityFrameCounter = 2377;
|
|
774
|
-
const gpdCommandId = 11;
|
|
775
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
776
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
777
|
-
|
|
778
|
-
const gpdHeader = makeHeader(
|
|
779
|
-
sequenceNumber,
|
|
780
|
-
commandIdentifier,
|
|
781
|
-
addr.applicationId,
|
|
782
|
-
securityLevelFullEncr,
|
|
783
|
-
securityKeyTypeNWK,
|
|
784
|
-
bidirectionalInfo,
|
|
785
|
-
addr.sourceId,
|
|
786
|
-
gpdSecurityFrameCounter,
|
|
787
|
-
gpdCommandId,
|
|
788
|
-
gpdCommandPayload.length,
|
|
789
|
-
);
|
|
790
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
791
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
792
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
793
|
-
|
|
794
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
795
|
-
1,
|
|
796
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=1496140231 gpp=NO",
|
|
797
|
-
"zh:controller:greenpower",
|
|
798
|
-
);
|
|
799
|
-
|
|
800
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
801
|
-
clonedFrame.payload.commandID = 0x21;
|
|
802
|
-
clonedFrame.payload.options = 256;
|
|
803
|
-
clonedFrame.payload.commandFrame = {};
|
|
804
|
-
|
|
805
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
806
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
clearLogMocks();
|
|
810
|
-
|
|
811
|
-
// mock FULLENCR with unknown security key
|
|
812
|
-
{
|
|
813
|
-
const gpdLink = 222;
|
|
814
|
-
const sequenceNumber = 73;
|
|
815
|
-
const bidirectionalInfo = 0;
|
|
816
|
-
const gpdSecurityFrameCounter = 2377;
|
|
817
|
-
const gpdCommandId = 11;
|
|
818
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
819
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
820
|
-
|
|
821
|
-
const gpdHeader = makeHeader(
|
|
822
|
-
sequenceNumber,
|
|
823
|
-
commandIdentifier,
|
|
824
|
-
addr.applicationId,
|
|
825
|
-
securityLevelFullEncr,
|
|
826
|
-
securityKeyTypeNWK,
|
|
827
|
-
bidirectionalInfo,
|
|
828
|
-
addr.sourceId,
|
|
829
|
-
gpdSecurityFrameCounter,
|
|
830
|
-
gpdCommandId,
|
|
831
|
-
gpdCommandPayload.length,
|
|
832
|
-
);
|
|
833
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
834
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
835
|
-
const retFrame = await gp.processCommand(payload, frame, undefined);
|
|
836
|
-
|
|
837
|
-
expect(logErrorSpy).toHaveBeenNthCalledWith(
|
|
838
|
-
1,
|
|
839
|
-
"[FULLENCR] srcID=1496140231 gpp=NO commandIdentifier=0 Unknown security key",
|
|
840
|
-
"zh:controller:greenpower",
|
|
841
|
-
);
|
|
842
|
-
|
|
843
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(frame)));
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
clearLogMocks();
|
|
847
|
-
|
|
848
|
-
// mock FULLENCR with gpp data
|
|
849
|
-
{
|
|
850
|
-
const gpdLink = 222;
|
|
851
|
-
const sequenceNumber = 73;
|
|
852
|
-
const gpdSecurityFrameCounter = 2377;
|
|
853
|
-
const gpdCommandId = 11;
|
|
854
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
855
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
856
|
-
const gppNwkAddr = 24404;
|
|
857
|
-
const gppGpdLink = 207;
|
|
858
|
-
const options = ((0b11 & 0x3) << 6) | 0x4000;
|
|
859
|
-
|
|
860
|
-
const gpdHeader = makeHeader(
|
|
861
|
-
sequenceNumber,
|
|
862
|
-
commandIdentifier,
|
|
863
|
-
0,
|
|
864
|
-
0,
|
|
865
|
-
0,
|
|
866
|
-
0,
|
|
867
|
-
addr.sourceId,
|
|
868
|
-
gpdSecurityFrameCounter,
|
|
869
|
-
gpdCommandId,
|
|
870
|
-
gpdCommandPayload.length,
|
|
871
|
-
options,
|
|
872
|
-
);
|
|
873
|
-
const gpdFooter = Buffer.alloc(3);
|
|
874
|
-
gpdFooter.writeUInt16LE(gppNwkAddr, 0);
|
|
875
|
-
gpdFooter.writeUInt8(gppGpdLink, 2);
|
|
876
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), gpdLink);
|
|
877
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
878
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
879
|
-
|
|
880
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
881
|
-
1,
|
|
882
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=1496140231 gpp=24404 rssi=15 linkQuality=Excellent",
|
|
883
|
-
"zh:controller:greenpower",
|
|
884
|
-
);
|
|
885
|
-
|
|
886
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
887
|
-
clonedFrame.payload.commandID = 0x21;
|
|
888
|
-
clonedFrame.payload.options = 16384;
|
|
889
|
-
clonedFrame.payload.commandFrame = {};
|
|
890
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
891
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
892
|
-
|
|
893
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
894
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
895
|
-
}
|
|
896
|
-
});
|
|
897
|
-
|
|
898
|
-
// @see https://github.com/Koenkk/zigbee2mqtt/issues/19405#issuecomment-2732204071
|
|
899
|
-
it("FULLENCR ZT-LP-ZEU2S-WH-MS MOES 3-gang vectors from ember", async () => {
|
|
900
|
-
let joinData: GreenPowerDeviceJoinedPayload | undefined;
|
|
901
|
-
|
|
902
|
-
gp.on("deviceJoined", (payload) => {
|
|
903
|
-
joinData = payload;
|
|
904
|
-
});
|
|
905
|
-
|
|
906
|
-
const addr = {applicationId: 0, sourceId: 344902069, endpoint: 0};
|
|
907
|
-
|
|
908
|
-
{
|
|
909
|
-
const gpdLink = 219;
|
|
910
|
-
const sequenceNumber = 139;
|
|
911
|
-
const gpdfSecurityLevel = 0; // NONE
|
|
912
|
-
const gpdfSecurityKeyType = 0; // NONE
|
|
913
|
-
const bidirectionalInfo = 0;
|
|
914
|
-
const gpdSecurityFrameCounter = 4294967295;
|
|
915
|
-
const gpdCommandId = 224;
|
|
916
|
-
const gpdCommandPayload = Buffer.from("0289f35690230a93ea5f1951926f200236c7820891812a8b0400007165726837706f7840475030303031be", "hex");
|
|
917
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
918
|
-
|
|
919
|
-
const gpdHeader = makeHeader(
|
|
920
|
-
sequenceNumber,
|
|
921
|
-
commandIdentifier,
|
|
922
|
-
addr.applicationId,
|
|
923
|
-
gpdfSecurityLevel,
|
|
924
|
-
gpdfSecurityKeyType,
|
|
925
|
-
bidirectionalInfo,
|
|
926
|
-
addr.sourceId,
|
|
927
|
-
gpdSecurityFrameCounter,
|
|
928
|
-
gpdCommandId,
|
|
929
|
-
gpdCommandPayload.length,
|
|
930
|
-
);
|
|
931
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
932
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
933
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey); // always undefined since not yet joined
|
|
934
|
-
|
|
935
|
-
await vi.waitUntil(() => joinData !== undefined);
|
|
936
|
-
|
|
937
|
-
expect(joinData).toStrictEqual({
|
|
938
|
-
sourceID: addr.sourceId,
|
|
939
|
-
deviceID: frame.payload.commandFrame.deviceID,
|
|
940
|
-
networkAddress: addr.sourceId & 0xffff,
|
|
941
|
-
securityKey: frame.payload.commandFrame.securityKey,
|
|
942
|
-
});
|
|
943
|
-
expect(logInfoSpy).toHaveBeenNthCalledWith(1, "[COMMISSIONING] srcID=344902069 gpp=NO", "zh:controller:greenpower");
|
|
944
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
945
|
-
1,
|
|
946
|
-
"[PAIRING] srcID=344902069 gpp=NO options=58696 (addSink=true commMode=2)",
|
|
947
|
-
"zh:controller:greenpower",
|
|
948
|
-
);
|
|
949
|
-
|
|
950
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
951
|
-
clonedFrame.payload.commandID = 0xe0;
|
|
952
|
-
clonedFrame.payload.options = 0;
|
|
953
|
-
clonedFrame.payload.commandFrame = {
|
|
954
|
-
deviceID: 2,
|
|
955
|
-
options: 137,
|
|
956
|
-
extendedOptions: 243,
|
|
957
|
-
securityKey: joinData?.securityKey,
|
|
958
|
-
keyMic: 713134344,
|
|
959
|
-
outgoingCounter: 1163,
|
|
960
|
-
applicationInfo: addr.applicationId,
|
|
961
|
-
manufacturerID: 0,
|
|
962
|
-
modelID: 0,
|
|
963
|
-
numGpdCommands: 0,
|
|
964
|
-
gpdCommandIdList: Buffer.from([]),
|
|
965
|
-
numServerClusters: 0,
|
|
966
|
-
numClientClusters: 0,
|
|
967
|
-
gpdServerClusters: Buffer.from([]),
|
|
968
|
-
gpdClientClusters: Buffer.from([]),
|
|
969
|
-
genericSwitchConfig: 0,
|
|
970
|
-
currentContactStatus: 0,
|
|
971
|
-
};
|
|
972
|
-
|
|
973
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
974
|
-
expect(retFrame.payload.commandFrame.securityKey).toStrictEqual(joinData?.securityKey);
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
clearLogMocks();
|
|
978
|
-
|
|
979
|
-
const securityLevelFullEncr = 3;
|
|
980
|
-
const securityKeyTypeNWK = 1;
|
|
981
|
-
|
|
982
|
-
// left
|
|
983
|
-
{
|
|
984
|
-
const gpdLink = 224;
|
|
985
|
-
const sequenceNumber = 175;
|
|
986
|
-
const bidirectionalInfo = 0;
|
|
987
|
-
const gpdSecurityFrameCounter = 1199;
|
|
988
|
-
const gpdCommandId = 92;
|
|
989
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
990
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
991
|
-
|
|
992
|
-
const gpdHeader = makeHeader(
|
|
993
|
-
sequenceNumber,
|
|
994
|
-
commandIdentifier,
|
|
995
|
-
addr.applicationId,
|
|
996
|
-
securityLevelFullEncr,
|
|
997
|
-
securityKeyTypeNWK,
|
|
998
|
-
bidirectionalInfo,
|
|
999
|
-
addr.sourceId,
|
|
1000
|
-
gpdSecurityFrameCounter,
|
|
1001
|
-
gpdCommandId,
|
|
1002
|
-
gpdCommandPayload.length,
|
|
1003
|
-
);
|
|
1004
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
1005
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1006
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1007
|
-
|
|
1008
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1009
|
-
1,
|
|
1010
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=344902069 gpp=NO",
|
|
1011
|
-
"zh:controller:greenpower",
|
|
1012
|
-
);
|
|
1013
|
-
|
|
1014
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1015
|
-
clonedFrame.payload.commandID = 0x20;
|
|
1016
|
-
clonedFrame.payload.options = 256;
|
|
1017
|
-
clonedFrame.payload.commandFrame = {};
|
|
1018
|
-
|
|
1019
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1020
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
clearLogMocks();
|
|
1024
|
-
|
|
1025
|
-
// middle
|
|
1026
|
-
{
|
|
1027
|
-
const gpdLink = 225;
|
|
1028
|
-
const sequenceNumber = 184;
|
|
1029
|
-
const bidirectionalInfo = 0;
|
|
1030
|
-
const gpdSecurityFrameCounter = 1208;
|
|
1031
|
-
const gpdCommandId = 109;
|
|
1032
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1033
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
1034
|
-
|
|
1035
|
-
const gpdHeader = makeHeader(
|
|
1036
|
-
sequenceNumber,
|
|
1037
|
-
commandIdentifier,
|
|
1038
|
-
addr.applicationId,
|
|
1039
|
-
securityLevelFullEncr,
|
|
1040
|
-
securityKeyTypeNWK,
|
|
1041
|
-
bidirectionalInfo,
|
|
1042
|
-
addr.sourceId,
|
|
1043
|
-
gpdSecurityFrameCounter,
|
|
1044
|
-
gpdCommandId,
|
|
1045
|
-
gpdCommandPayload.length,
|
|
1046
|
-
);
|
|
1047
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
1048
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1049
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1050
|
-
|
|
1051
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1052
|
-
1,
|
|
1053
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=344902069 gpp=NO",
|
|
1054
|
-
"zh:controller:greenpower",
|
|
1055
|
-
);
|
|
1056
|
-
|
|
1057
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1058
|
-
clonedFrame.payload.commandID = 0x21;
|
|
1059
|
-
clonedFrame.payload.options = 256;
|
|
1060
|
-
clonedFrame.payload.commandFrame = {};
|
|
1061
|
-
|
|
1062
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1063
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
clearLogMocks();
|
|
1067
|
-
|
|
1068
|
-
// right
|
|
1069
|
-
{
|
|
1070
|
-
const gpdLink = 225;
|
|
1071
|
-
const sequenceNumber = 193;
|
|
1072
|
-
const bidirectionalInfo = 0;
|
|
1073
|
-
const gpdSecurityFrameCounter = 1217;
|
|
1074
|
-
const gpdCommandId = 219;
|
|
1075
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1076
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.notification.ID;
|
|
1077
|
-
|
|
1078
|
-
const gpdHeader = makeHeader(
|
|
1079
|
-
sequenceNumber,
|
|
1080
|
-
commandIdentifier,
|
|
1081
|
-
addr.applicationId,
|
|
1082
|
-
securityLevelFullEncr,
|
|
1083
|
-
securityKeyTypeNWK,
|
|
1084
|
-
bidirectionalInfo,
|
|
1085
|
-
addr.sourceId,
|
|
1086
|
-
gpdSecurityFrameCounter,
|
|
1087
|
-
gpdCommandId,
|
|
1088
|
-
gpdCommandPayload.length,
|
|
1089
|
-
);
|
|
1090
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload]), gpdLink);
|
|
1091
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1092
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1093
|
-
|
|
1094
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1095
|
-
1,
|
|
1096
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x11 srcID=344902069 gpp=NO",
|
|
1097
|
-
"zh:controller:greenpower",
|
|
1098
|
-
);
|
|
1099
|
-
|
|
1100
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1101
|
-
clonedFrame.payload.commandID = 0x11;
|
|
1102
|
-
clonedFrame.payload.options = 256;
|
|
1103
|
-
clonedFrame.payload.commandFrame = {};
|
|
1104
|
-
|
|
1105
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1106
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1107
|
-
}
|
|
1108
|
-
});
|
|
1109
|
-
|
|
1110
|
-
// @see https://github.com/Koenkk/zigbee2mqtt/issues/19405#issuecomment-2744667458
|
|
1111
|
-
it("FULLENCR ZT-LP-ZEU2S-WH-MS MOES 2-gang vectors from zstack through GPP", async () => {
|
|
1112
|
-
const joinData: GreenPowerDeviceJoinedPayload = {
|
|
1113
|
-
sourceID: 2777252112,
|
|
1114
|
-
deviceID: 2,
|
|
1115
|
-
networkAddress: 2777252112 & 0xffff,
|
|
1116
|
-
securityKey: Buffer.from([227, 227, 225, 134, 235, 104, 141, 250, 162, 211, 104, 147, 201, 146, 67, 175]),
|
|
1117
|
-
};
|
|
1118
|
-
const addr = {applicationId: 0, sourceId: 2777252112, endpoint: 0};
|
|
1119
|
-
const gppNwkAddr = 24404;
|
|
1120
|
-
const options = 2864;
|
|
1121
|
-
|
|
1122
|
-
// right
|
|
1123
|
-
{
|
|
1124
|
-
const sequenceNumber = 18;
|
|
1125
|
-
const gpdSecurityFrameCounter = 17326;
|
|
1126
|
-
const gpdCommandId = 38;
|
|
1127
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1128
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1129
|
-
const gppGpdLink = 207;
|
|
1130
|
-
const mic = 1441399364;
|
|
1131
|
-
|
|
1132
|
-
const gpdHeader = makeHeader(
|
|
1133
|
-
sequenceNumber,
|
|
1134
|
-
commandIdentifier,
|
|
1135
|
-
0,
|
|
1136
|
-
0,
|
|
1137
|
-
0,
|
|
1138
|
-
0,
|
|
1139
|
-
addr.sourceId,
|
|
1140
|
-
gpdSecurityFrameCounter,
|
|
1141
|
-
gpdCommandId,
|
|
1142
|
-
gpdCommandPayload.length,
|
|
1143
|
-
options,
|
|
1144
|
-
);
|
|
1145
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1146
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
1147
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1148
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1149
|
-
|
|
1150
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1151
|
-
1,
|
|
1152
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=2777252112 gpp=24404 rssi=15 linkQuality=Excellent",
|
|
1153
|
-
"zh:controller:greenpower",
|
|
1154
|
-
);
|
|
1155
|
-
|
|
1156
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1157
|
-
clonedFrame.payload.commandID = 0x21;
|
|
1158
|
-
clonedFrame.payload.options = 2304;
|
|
1159
|
-
clonedFrame.payload.commandFrame = {};
|
|
1160
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1161
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1162
|
-
delete clonedFrame.payload.mic;
|
|
1163
|
-
|
|
1164
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1165
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
clearLogMocks();
|
|
1169
|
-
|
|
1170
|
-
// right
|
|
1171
|
-
{
|
|
1172
|
-
const sequenceNumber = 19;
|
|
1173
|
-
const gpdSecurityFrameCounter = 17335;
|
|
1174
|
-
const gpdCommandId = 17;
|
|
1175
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1176
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1177
|
-
const gppGpdLink = 207;
|
|
1178
|
-
const mic = 3064327344;
|
|
1179
|
-
|
|
1180
|
-
const gpdHeader = makeHeader(
|
|
1181
|
-
sequenceNumber,
|
|
1182
|
-
commandIdentifier,
|
|
1183
|
-
0,
|
|
1184
|
-
0,
|
|
1185
|
-
0,
|
|
1186
|
-
0,
|
|
1187
|
-
addr.sourceId,
|
|
1188
|
-
gpdSecurityFrameCounter,
|
|
1189
|
-
gpdCommandId,
|
|
1190
|
-
gpdCommandPayload.length,
|
|
1191
|
-
options,
|
|
1192
|
-
);
|
|
1193
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1194
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 127);
|
|
1195
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1196
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1197
|
-
|
|
1198
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1199
|
-
1,
|
|
1200
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=2777252112 gpp=24404 rssi=15 linkQuality=Excellent",
|
|
1201
|
-
"zh:controller:greenpower",
|
|
1202
|
-
);
|
|
1203
|
-
|
|
1204
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1205
|
-
clonedFrame.payload.commandID = 0x21;
|
|
1206
|
-
clonedFrame.payload.options = 2304;
|
|
1207
|
-
clonedFrame.payload.commandFrame = {};
|
|
1208
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1209
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1210
|
-
delete clonedFrame.payload.mic;
|
|
1211
|
-
|
|
1212
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1213
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
clearLogMocks();
|
|
1217
|
-
|
|
1218
|
-
// right
|
|
1219
|
-
{
|
|
1220
|
-
const sequenceNumber = 20;
|
|
1221
|
-
const gpdSecurityFrameCounter = 17344;
|
|
1222
|
-
const gpdCommandId = 211;
|
|
1223
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1224
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1225
|
-
const gppGpdLink = 207;
|
|
1226
|
-
const mic = 3315864057;
|
|
1227
|
-
|
|
1228
|
-
const gpdHeader = makeHeader(
|
|
1229
|
-
sequenceNumber,
|
|
1230
|
-
commandIdentifier,
|
|
1231
|
-
0,
|
|
1232
|
-
0,
|
|
1233
|
-
0,
|
|
1234
|
-
0,
|
|
1235
|
-
addr.sourceId,
|
|
1236
|
-
gpdSecurityFrameCounter,
|
|
1237
|
-
gpdCommandId,
|
|
1238
|
-
gpdCommandPayload.length,
|
|
1239
|
-
options,
|
|
1240
|
-
);
|
|
1241
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1242
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
1243
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1244
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1245
|
-
|
|
1246
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1247
|
-
1,
|
|
1248
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x21 srcID=2777252112 gpp=24404 rssi=15 linkQuality=Excellent",
|
|
1249
|
-
"zh:controller:greenpower",
|
|
1250
|
-
);
|
|
1251
|
-
|
|
1252
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1253
|
-
clonedFrame.payload.commandID = 0x21;
|
|
1254
|
-
clonedFrame.payload.options = 2304;
|
|
1255
|
-
clonedFrame.payload.commandFrame = {};
|
|
1256
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1257
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1258
|
-
delete clonedFrame.payload.mic;
|
|
1259
|
-
|
|
1260
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1261
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
clearLogMocks();
|
|
1265
|
-
|
|
1266
|
-
// left
|
|
1267
|
-
{
|
|
1268
|
-
const sequenceNumber = 21;
|
|
1269
|
-
const gpdSecurityFrameCounter = 17353;
|
|
1270
|
-
const gpdCommandId = 174;
|
|
1271
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1272
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1273
|
-
const gppGpdLink = 142;
|
|
1274
|
-
const mic = 827946906;
|
|
1275
|
-
|
|
1276
|
-
const gpdHeader = makeHeader(
|
|
1277
|
-
sequenceNumber,
|
|
1278
|
-
commandIdentifier,
|
|
1279
|
-
0,
|
|
1280
|
-
0,
|
|
1281
|
-
0,
|
|
1282
|
-
0,
|
|
1283
|
-
addr.sourceId,
|
|
1284
|
-
gpdSecurityFrameCounter,
|
|
1285
|
-
gpdCommandId,
|
|
1286
|
-
gpdCommandPayload.length,
|
|
1287
|
-
options,
|
|
1288
|
-
);
|
|
1289
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1290
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
1291
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1292
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1293
|
-
|
|
1294
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1295
|
-
1,
|
|
1296
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=2777252112 gpp=24404 rssi=14 linkQuality=High",
|
|
1297
|
-
"zh:controller:greenpower",
|
|
1298
|
-
);
|
|
1299
|
-
|
|
1300
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1301
|
-
clonedFrame.payload.commandID = 0x20;
|
|
1302
|
-
clonedFrame.payload.options = 2304;
|
|
1303
|
-
clonedFrame.payload.commandFrame = {};
|
|
1304
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1305
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1306
|
-
delete clonedFrame.payload.mic;
|
|
1307
|
-
|
|
1308
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1309
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
clearLogMocks();
|
|
1313
|
-
|
|
1314
|
-
// left
|
|
1315
|
-
{
|
|
1316
|
-
const sequenceNumber = 22;
|
|
1317
|
-
const gpdSecurityFrameCounter = 17362;
|
|
1318
|
-
const gpdCommandId = 230;
|
|
1319
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1320
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1321
|
-
const gppGpdLink = 209;
|
|
1322
|
-
const mic = 2941277720;
|
|
1323
|
-
|
|
1324
|
-
const gpdHeader = makeHeader(
|
|
1325
|
-
sequenceNumber,
|
|
1326
|
-
commandIdentifier,
|
|
1327
|
-
0,
|
|
1328
|
-
0,
|
|
1329
|
-
0,
|
|
1330
|
-
0,
|
|
1331
|
-
addr.sourceId,
|
|
1332
|
-
gpdSecurityFrameCounter,
|
|
1333
|
-
gpdCommandId,
|
|
1334
|
-
gpdCommandPayload.length,
|
|
1335
|
-
options,
|
|
1336
|
-
);
|
|
1337
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1338
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 142);
|
|
1339
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1340
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1341
|
-
|
|
1342
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1343
|
-
1,
|
|
1344
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=2777252112 gpp=24404 rssi=17 linkQuality=Excellent",
|
|
1345
|
-
"zh:controller:greenpower",
|
|
1346
|
-
);
|
|
1347
|
-
|
|
1348
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1349
|
-
clonedFrame.payload.commandID = 0x20;
|
|
1350
|
-
clonedFrame.payload.options = 2304;
|
|
1351
|
-
clonedFrame.payload.commandFrame = {};
|
|
1352
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1353
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1354
|
-
delete clonedFrame.payload.mic;
|
|
1355
|
-
|
|
1356
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1357
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
clearLogMocks();
|
|
1361
|
-
|
|
1362
|
-
// left
|
|
1363
|
-
{
|
|
1364
|
-
const sequenceNumber = 23;
|
|
1365
|
-
const gpdSecurityFrameCounter = 17371;
|
|
1366
|
-
const gpdCommandId = 59;
|
|
1367
|
-
const gpdCommandPayload = Buffer.from("", "hex");
|
|
1368
|
-
const commandIdentifier = Zcl.Clusters.greenPower.commands.commissioningNotification.ID;
|
|
1369
|
-
const gppGpdLink = 209;
|
|
1370
|
-
const mic = 3231351307;
|
|
1371
|
-
|
|
1372
|
-
const gpdHeader = makeHeader(
|
|
1373
|
-
sequenceNumber,
|
|
1374
|
-
commandIdentifier,
|
|
1375
|
-
0,
|
|
1376
|
-
0,
|
|
1377
|
-
0,
|
|
1378
|
-
0,
|
|
1379
|
-
addr.sourceId,
|
|
1380
|
-
gpdSecurityFrameCounter,
|
|
1381
|
-
gpdCommandId,
|
|
1382
|
-
gpdCommandPayload.length,
|
|
1383
|
-
options,
|
|
1384
|
-
);
|
|
1385
|
-
const gpdFooter = makeFooter(options, gppNwkAddr, gppGpdLink, mic);
|
|
1386
|
-
const payload = makePayload(addr.sourceId, Buffer.concat([gpdHeader, gpdCommandPayload, gpdFooter]), 138);
|
|
1387
|
-
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1388
|
-
const retFrame = await gp.processCommand(payload, frame, joinData?.securityKey);
|
|
1389
|
-
|
|
1390
|
-
expect(logDebugSpy).toHaveBeenNthCalledWith(
|
|
1391
|
-
1,
|
|
1392
|
-
"[UNHANDLED_CMD/PASSTHROUGH] command=0x20 srcID=2777252112 gpp=24404 rssi=17 linkQuality=Excellent",
|
|
1393
|
-
"zh:controller:greenpower",
|
|
1394
|
-
);
|
|
1395
|
-
|
|
1396
|
-
const clonedFrame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, {});
|
|
1397
|
-
clonedFrame.payload.commandID = 0x20;
|
|
1398
|
-
clonedFrame.payload.options = 2304;
|
|
1399
|
-
clonedFrame.payload.commandFrame = {};
|
|
1400
|
-
clonedFrame.payload.gppNwkAddr = gppNwkAddr;
|
|
1401
|
-
clonedFrame.payload.gppGpdLink = gppGpdLink;
|
|
1402
|
-
delete clonedFrame.payload.mic;
|
|
1403
|
-
|
|
1404
|
-
expect(JSON.parse(JSON.stringify(retFrame))).toStrictEqual(JSON.parse(JSON.stringify(clonedFrame)));
|
|
1405
|
-
expect(retFrame.payload.commandFrame).toStrictEqual({});
|
|
1406
|
-
}
|
|
1407
|
-
});
|
|
1408
|
-
});
|