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,107 +0,0 @@
|
|
|
1
|
-
import {INSTALL_CODE_CRC_SIZE, INSTALL_CODE_SIZES} from "../../zspec/consts";
|
|
2
|
-
import {crc16X25} from "../../zspec/utils";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Parse the given code using known formats:
|
|
6
|
-
* - 95 or 91-length
|
|
7
|
-
* - Widely adopted (Ubisys, Danfoss, Inovelli, Ledvance): ...Z:<ieee>$I:<key>...
|
|
8
|
-
* - Pipe-separated (Muller-Licht, Innr): <ieee>|<key>
|
|
9
|
-
* - Aqara: G$M:...$A:<ieee>$I:<key>
|
|
10
|
-
* - Hue: HUE:Z:<key> M:<ieee>...
|
|
11
|
-
* @param installCode
|
|
12
|
-
* @returns
|
|
13
|
-
* - the IEEE address
|
|
14
|
-
* - the raw key
|
|
15
|
-
*/
|
|
16
|
-
export function parseInstallCode(installCode: string): [ieeeAddr: string, key: string] {
|
|
17
|
-
const widelyAdoptedMatch = installCode.match(/Z:([a-zA-Z0-9]{16})\$I:([a-zA-Z0-9]+)/);
|
|
18
|
-
|
|
19
|
-
if (widelyAdoptedMatch) {
|
|
20
|
-
return [`0x${widelyAdoptedMatch[1].toLowerCase()}`, widelyAdoptedMatch[2]];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const pipeMatch = installCode.match(/^([a-zA-Z0-9]{16})\|([a-zA-Z0-9]+)$/);
|
|
24
|
-
|
|
25
|
-
if (pipeMatch) {
|
|
26
|
-
return [`0x${pipeMatch[1].toLowerCase()}`, pipeMatch[2]];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const aqaraMatch = installCode.match(/^G\$M:.+\$A:([a-zA-Z0-9]{16})\$I:([a-zA-Z0-9]+)$/);
|
|
30
|
-
|
|
31
|
-
if (aqaraMatch) {
|
|
32
|
-
return [`0x${aqaraMatch[1].toLowerCase()}`, aqaraMatch[2]];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const hueMatch = installCode.match(/^HUE:Z:([a-zA-Z0-9]+) M:([a-zA-Z0-9]{16})/);
|
|
36
|
-
|
|
37
|
-
if (hueMatch) {
|
|
38
|
-
return [`0x${hueMatch[2].toLowerCase()}`, hueMatch[1]];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (installCode.length === 95 || installCode.length === 91) {
|
|
42
|
-
const keyStart = installCode.length - (installCode.length === 95 ? 36 : 32);
|
|
43
|
-
|
|
44
|
-
return [`0x${installCode.substring(keyStart - 19, keyStart - 3).toLowerCase()}`, installCode.substring(keyStart, installCode.length)];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
throw new Error(`Unsupported install code, got ${installCode.length} chars, expected 95 or 91 chars, or known format`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Check if install code (little-endian) is valid, and if not, and requested, fix it.
|
|
52
|
-
*
|
|
53
|
-
* WARNING: Due to conflicting sizes between 8-length code with invalid CRC, and 10-length code missing CRC, given 8-length codes are always assumed to be 8-length code with invalid CRC (most probable scenario).
|
|
54
|
-
*
|
|
55
|
-
* @param code The code to check. Reference is not modified by this procedure but is returned when code was valid, as `outCode`.
|
|
56
|
-
* @param adjust If false, throws if the install code is invalid, otherwise try to fix it (CRC)
|
|
57
|
-
* @returns
|
|
58
|
-
* - The adjusted code, or `code` if not adjusted.
|
|
59
|
-
* - If adjust is false, undefined, otherwise, the reason why the code needed adjusting or undefined if not.
|
|
60
|
-
* - Throws when adjust=false and invalid, or cannot fix.
|
|
61
|
-
*/
|
|
62
|
-
export function checkInstallCode(code: Buffer, adjust = true): [outCode: Buffer, adjusted: "invalid CRC" | "missing CRC" | undefined] {
|
|
63
|
-
const crcLowByteIndex = code.length - INSTALL_CODE_CRC_SIZE;
|
|
64
|
-
const crcHighByteIndex = code.length - INSTALL_CODE_CRC_SIZE + 1;
|
|
65
|
-
|
|
66
|
-
for (const codeSize of INSTALL_CODE_SIZES) {
|
|
67
|
-
if (code.length === codeSize) {
|
|
68
|
-
// install code has CRC, check if valid, if not, replace it
|
|
69
|
-
const crc = crc16X25(code.subarray(0, -2));
|
|
70
|
-
const crcHighByte = (crc >> 8) & 0xff;
|
|
71
|
-
const crcLowByte = crc & 0xff;
|
|
72
|
-
|
|
73
|
-
if (code[crcLowByteIndex] !== crcLowByte || code[crcHighByteIndex] !== crcHighByte) {
|
|
74
|
-
// see WARNING above, 8 is smallest valid length, so always ends up here
|
|
75
|
-
if (adjust) {
|
|
76
|
-
const outCode = Buffer.from(code);
|
|
77
|
-
outCode[crcLowByteIndex] = crcLowByte;
|
|
78
|
-
outCode[crcHighByteIndex] = crcHighByte;
|
|
79
|
-
|
|
80
|
-
return [outCode, "invalid CRC"];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
throw new Error(`Install code ${code.toString("hex")} failed CRC validation`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return [code, undefined];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (code.length === codeSize - INSTALL_CODE_CRC_SIZE) {
|
|
90
|
-
if (adjust) {
|
|
91
|
-
// install code is missing CRC
|
|
92
|
-
const crc = crc16X25(code);
|
|
93
|
-
const outCode = Buffer.alloc(code.length + INSTALL_CODE_CRC_SIZE);
|
|
94
|
-
|
|
95
|
-
code.copy(outCode, 0);
|
|
96
|
-
outCode.writeUInt16LE(crc, code.length);
|
|
97
|
-
|
|
98
|
-
return [outCode, "missing CRC"];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
throw new Error(`Install code ${code.toString("hex")} failed CRC validation`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// never returned from within the above loop
|
|
106
|
-
throw new Error(`Install code ${code.toString("hex")} has invalid size`);
|
|
107
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type * as Zcl from "../../zspec/zcl";
|
|
2
|
-
import type {SendPolicy} from "../tstype";
|
|
3
|
-
|
|
4
|
-
// biome-ignore lint/suspicious/noExplicitAny: API
|
|
5
|
-
export class Request<Type = any> {
|
|
6
|
-
static defaultSendPolicy: {[key: number]: SendPolicy} = {
|
|
7
|
-
0: "keep-payload", // Read Attributes
|
|
8
|
-
1: "immediate", // Read Attributes Response
|
|
9
|
-
2: "keep-command", // Write Attributes
|
|
10
|
-
3: "keep-cmd-undiv", // Write Attributes Undivided
|
|
11
|
-
4: "immediate", // Write Attributes Response
|
|
12
|
-
5: "keep-command", // Write Attributes No Response
|
|
13
|
-
6: "keep-payload", // Configure Reporting
|
|
14
|
-
7: "immediate", // Configure Reporting Response
|
|
15
|
-
8: "keep-payload", // Read Reporting Configuration
|
|
16
|
-
9: "immediate", // Read Reporting Configuration Response
|
|
17
|
-
10: "keep-payload", // Report attributes
|
|
18
|
-
11: "immediate", // Default Response
|
|
19
|
-
12: "keep-payload", // Discover Attributes
|
|
20
|
-
13: "immediate", // Discover Attributes Response
|
|
21
|
-
14: "keep-payload", // Read Attributes Structured
|
|
22
|
-
15: "keep-payload", // Write Attributes Structured
|
|
23
|
-
16: "immediate", // Write Attributes Structured response
|
|
24
|
-
17: "keep-payload", // Discover Commands Received
|
|
25
|
-
18: "immediate", // Discover Commands Received Response
|
|
26
|
-
19: "keep-payload", // Discover Commands Generated
|
|
27
|
-
20: "immediate", // Discover Commands Generated Response
|
|
28
|
-
21: "keep-payload", // Discover Attributes Extended
|
|
29
|
-
22: "immediate", // Discover Attributes Extended Response
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
private func: () => Promise<Type>;
|
|
33
|
-
frame: Zcl.Frame;
|
|
34
|
-
expires: number;
|
|
35
|
-
sendPolicy: SendPolicy | undefined;
|
|
36
|
-
private resolveQueue: Array<(value: Type) => void>;
|
|
37
|
-
private rejectQueue: Array<(error: Error) => void>;
|
|
38
|
-
private lastError: Error;
|
|
39
|
-
|
|
40
|
-
constructor(
|
|
41
|
-
func: () => Promise<Type>,
|
|
42
|
-
frame: Zcl.Frame,
|
|
43
|
-
timeout: number,
|
|
44
|
-
sendPolicy?: SendPolicy,
|
|
45
|
-
lastError?: Error,
|
|
46
|
-
resolve?: (value: Type) => void,
|
|
47
|
-
reject?: (error: Error) => void,
|
|
48
|
-
) {
|
|
49
|
-
this.func = func;
|
|
50
|
-
this.frame = frame;
|
|
51
|
-
this.expires = timeout + Date.now();
|
|
52
|
-
this.sendPolicy = sendPolicy ?? (!frame.command ? undefined : Request.defaultSendPolicy[frame.command.ID]);
|
|
53
|
-
this.resolveQueue = resolve === undefined ? ([] as ((value: Type) => void)[]) : new Array<(value: Type) => void>(resolve);
|
|
54
|
-
this.rejectQueue = reject === undefined ? ([] as ((error: Error) => void)[]) : new Array<(error: Error) => void>(reject);
|
|
55
|
-
this.lastError = lastError ?? Error("Request rejected before first send");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
moveCallbacks(from: Request<Type>): void {
|
|
59
|
-
this.resolveQueue = this.resolveQueue.concat(from.resolveQueue);
|
|
60
|
-
this.rejectQueue = this.rejectQueue.concat(from.rejectQueue);
|
|
61
|
-
from.resolveQueue.length = 0;
|
|
62
|
-
from.rejectQueue.length = 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
addCallbacks(resolve: (value: Type) => void, reject: (error: Error) => void): void {
|
|
66
|
-
this.resolveQueue.push(resolve);
|
|
67
|
-
this.rejectQueue.push(reject);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
reject(error?: Error): void {
|
|
71
|
-
for (const el of this.rejectQueue) {
|
|
72
|
-
el(error ?? this.lastError);
|
|
73
|
-
}
|
|
74
|
-
this.rejectQueue.length = 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
resolve(value: Type): void {
|
|
78
|
-
for (const el of this.resolveQueue) {
|
|
79
|
-
el(value);
|
|
80
|
-
}
|
|
81
|
-
this.resolveQueue.length = 0;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async send(): Promise<Type> {
|
|
85
|
-
try {
|
|
86
|
-
const ret = await this.func();
|
|
87
|
-
|
|
88
|
-
return ret;
|
|
89
|
-
} catch (error) {
|
|
90
|
-
this.lastError = error as Error;
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default Request;
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import {logger} from "../../utils/logger";
|
|
2
|
-
import type * as Zcl from "../../zspec/zcl";
|
|
3
|
-
import type {Endpoint} from "../model";
|
|
4
|
-
import type Request from "./request";
|
|
5
|
-
|
|
6
|
-
const NS = "zh:controller:requestqueue";
|
|
7
|
-
|
|
8
|
-
type Mutable<T> = {-readonly [P in keyof T]: T[P]};
|
|
9
|
-
|
|
10
|
-
export class RequestQueue extends Set<Request> {
|
|
11
|
-
private sendInProgress: boolean;
|
|
12
|
-
private id: number;
|
|
13
|
-
private deviceIeeeAddress: string;
|
|
14
|
-
|
|
15
|
-
constructor(endpoint: Endpoint) {
|
|
16
|
-
super();
|
|
17
|
-
this.sendInProgress = false;
|
|
18
|
-
this.id = endpoint.ID;
|
|
19
|
-
this.deviceIeeeAddress = endpoint.deviceIeeeAddress;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public async send(fastPolling: boolean): Promise<void> {
|
|
23
|
-
if (this.size === 0) return;
|
|
24
|
-
|
|
25
|
-
if (!fastPolling && this.sendInProgress) {
|
|
26
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): sendPendingRequests already in progress`, NS);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
this.sendInProgress = true;
|
|
30
|
-
|
|
31
|
-
// Remove expired requests first
|
|
32
|
-
const now = Date.now();
|
|
33
|
-
for (const request of this) {
|
|
34
|
-
if (now > request.expires) {
|
|
35
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): discard after timeout. Size before: ${this.size}`, NS);
|
|
36
|
-
request.reject();
|
|
37
|
-
this.delete(request);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): send pending requests (${this.size}, ${fastPolling})`, NS);
|
|
42
|
-
|
|
43
|
-
for (const request of this) {
|
|
44
|
-
if (fastPolling || request.sendPolicy !== "bulk") {
|
|
45
|
-
try {
|
|
46
|
-
const result = await request.send();
|
|
47
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): send success`, NS);
|
|
48
|
-
request.resolve(result);
|
|
49
|
-
this.delete(request);
|
|
50
|
-
} catch (error) {
|
|
51
|
-
logger.debug(
|
|
52
|
-
`Request Queue (${this.deviceIeeeAddress}/${this.id}): send failed, expires in ` +
|
|
53
|
-
`${(request.expires - now) / 1000} seconds (${(error as Error).message})`,
|
|
54
|
-
NS,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
this.sendInProgress = false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public async queue<Type>(request: Request<Type>): Promise<Type> {
|
|
63
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): Sending when active. Expires: ${request.expires}`, NS);
|
|
64
|
-
return await new Promise((resolve, reject): void => {
|
|
65
|
-
request.addCallbacks(resolve, reject);
|
|
66
|
-
this.add(request);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public filter(newRequest: Request): void {
|
|
71
|
-
if (this.size === 0 || !newRequest.frame.command) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const clusterID = newRequest.frame.cluster.ID;
|
|
75
|
-
const payload = newRequest.frame.payload;
|
|
76
|
-
const commandID = newRequest.frame.command.ID;
|
|
77
|
-
|
|
78
|
-
logger.debug(
|
|
79
|
-
`Request Queue (${this.deviceIeeeAddress}/${this.id}): ZCL ${newRequest.frame.command.name} ` +
|
|
80
|
-
`command, filter requests. Before: ${this.size}`,
|
|
81
|
-
NS,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
for (const request of this) {
|
|
85
|
-
if (request?.frame?.cluster?.ID === undefined || !request.frame.command) {
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (request.sendPolicy === "bulk" || request.sendPolicy === "queue" || request.sendPolicy === "immediate") {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (request.frame.cluster.ID === clusterID && request.frame.command.ID === commandID) {
|
|
94
|
-
if (newRequest.sendPolicy === "keep-payload" && JSON.stringify(request.frame.payload) === JSON.stringify(payload)) {
|
|
95
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): Merge duplicate request`, NS);
|
|
96
|
-
this.delete(request);
|
|
97
|
-
newRequest.moveCallbacks(request);
|
|
98
|
-
} else if (
|
|
99
|
-
(newRequest.sendPolicy === "keep-command" || newRequest.sendPolicy === "keep-cmd-undiv") &&
|
|
100
|
-
Array.isArray(request.frame.payload)
|
|
101
|
-
) {
|
|
102
|
-
const filteredPayload = request.frame.payload.filter(
|
|
103
|
-
(oldEl: {attrId: number}) => !payload.find((newEl: {attrId: number}) => oldEl.attrId === newEl.attrId),
|
|
104
|
-
);
|
|
105
|
-
if (filteredPayload.length === 0) {
|
|
106
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): Remove & reject request`, NS);
|
|
107
|
-
if (JSON.stringify(request.frame.payload) === JSON.stringify(payload)) {
|
|
108
|
-
newRequest.moveCallbacks(request);
|
|
109
|
-
} else {
|
|
110
|
-
request.reject();
|
|
111
|
-
}
|
|
112
|
-
this.delete(request);
|
|
113
|
-
} else if (newRequest.sendPolicy !== "keep-cmd-undiv") {
|
|
114
|
-
// remove all duplicate attributes if we shall not write undivided
|
|
115
|
-
(request.frame as Mutable<Zcl.Frame>).payload = filteredPayload;
|
|
116
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): Remove commands from request`, NS);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.id}): After: ${this.size}`, NS);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export default RequestQueue;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import * as Zcl from "../../zspec/zcl";
|
|
2
|
-
import type {TFoundation} from "../../zspec/zcl/definition/clusters-types";
|
|
3
|
-
import type {Cluster, CustomClusters} from "../../zspec/zcl/definition/tstype";
|
|
4
|
-
import type {ClusterOrRawWriteAttributes, TCustomCluster} from "../tstype";
|
|
5
|
-
|
|
6
|
-
// Legrand devices (e.g. 4129) fail to set the manufacturerSpecific flag and
|
|
7
|
-
// manufacturerCode in the frame header, despite using specific attributes.
|
|
8
|
-
// This leads to incorrect reported attribute names.
|
|
9
|
-
// Remap the attributes using the target device's manufacturer ID
|
|
10
|
-
// if the header is lacking the information.
|
|
11
|
-
function getCluster(frame: Zcl.Frame, deviceManufacturerID: number | undefined, customClusters: CustomClusters): Cluster {
|
|
12
|
-
let cluster = frame.cluster;
|
|
13
|
-
if (!frame?.header?.manufacturerCode && frame?.cluster && deviceManufacturerID === Zcl.ManufacturerCode.LEGRAND_GROUP) {
|
|
14
|
-
cluster = Zcl.Utils.getCluster(frame.cluster.ID, deviceManufacturerID, customClusters);
|
|
15
|
-
}
|
|
16
|
-
return cluster;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function attributeKeyValue<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined>(
|
|
20
|
-
frame: Zcl.Frame,
|
|
21
|
-
deviceManufacturerID: number | undefined,
|
|
22
|
-
customClusters: CustomClusters,
|
|
23
|
-
): ClusterOrRawWriteAttributes<Cl, Custom> {
|
|
24
|
-
const payload: Record<string | number, unknown> = {};
|
|
25
|
-
const cluster = getCluster(frame, deviceManufacturerID, customClusters);
|
|
26
|
-
|
|
27
|
-
// TODO: remove this type once Zcl.Frame is typed
|
|
28
|
-
for (const item of frame.payload as TFoundation["report" | "write" | "readRsp"]) {
|
|
29
|
-
payload[cluster.getAttribute(item.attrId)?.name ?? item.attrId] = item.attrData;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return payload as ClusterOrRawWriteAttributes<Cl, Custom>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function attributeList(frame: Zcl.Frame, deviceManufacturerID: number | undefined, customClusters: CustomClusters): Array<string | number> {
|
|
36
|
-
const payload: Array<string | number> = [];
|
|
37
|
-
const cluster = getCluster(frame, deviceManufacturerID, customClusters);
|
|
38
|
-
|
|
39
|
-
// TODO: remove this type once Zcl.Frame is typed
|
|
40
|
-
for (const item of frame.payload as TFoundation["read"]) {
|
|
41
|
-
payload.push(cluster.getAttribute(item.attrId)?.name ?? item.attrId);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return payload;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export {attributeKeyValue, attributeList};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
class ZclTransactionSequenceNumber {
|
|
2
|
-
private number = 1;
|
|
3
|
-
|
|
4
|
-
get current() {
|
|
5
|
-
return this.number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
public next(): number {
|
|
9
|
-
this.number++;
|
|
10
|
-
|
|
11
|
-
if (this.number > 255) {
|
|
12
|
-
this.number = 1;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return this.number;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default new ZclTransactionSequenceNumber();
|