zigbee-herdsman 6.0.1 → 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 +16 -0
- package/dist/adapter/ezsp/driver/uart.js +1 -1
- package/dist/adapter/ezsp/driver/uart.js.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +4 -4
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.js +4 -4
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
- package/dist/controller/model/device.d.ts.map +1 -1
- package/dist/controller/model/device.js +1 -0
- package/dist/controller/model/device.js.map +1 -1
- package/package.json +14 -6
- package/.github/ISSUE_TEMPLATE/config.yml +0 -5
- package/.github/dependabot.yml +0 -22
- package/.github/workflows/ci.yml +0 -64
- 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 -1248
- 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/buffalo.test.ts +0 -431
- package/test/controller.bench.ts +0 -193
- 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 -206
- 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 -27
- 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,753 +0,0 @@
|
|
|
1
|
-
/* v8 ignore start */
|
|
2
|
-
|
|
3
|
-
import {EventEmitter} from "node:events";
|
|
4
|
-
import {Buffalo} from "../../../buffalo";
|
|
5
|
-
import {logger} from "../../../utils/logger";
|
|
6
|
-
import * as Zdo from "../../../zspec/zdo";
|
|
7
|
-
import {
|
|
8
|
-
ApsAddressMode,
|
|
9
|
-
type ApsRequest,
|
|
10
|
-
ApsStatusCode,
|
|
11
|
-
type Command,
|
|
12
|
-
CommandStatus,
|
|
13
|
-
type DataStateResponse,
|
|
14
|
-
FirmwareCommand,
|
|
15
|
-
type GpDataInd,
|
|
16
|
-
ParamId,
|
|
17
|
-
type ReceivedDataResponse,
|
|
18
|
-
type Request,
|
|
19
|
-
} from "./constants";
|
|
20
|
-
import {apsBusyQueue, busyQueue} from "./driver";
|
|
21
|
-
|
|
22
|
-
const NS = "zh:deconz:frameparser";
|
|
23
|
-
|
|
24
|
-
const littleEndian = true;
|
|
25
|
-
const lastReceivedGpInd = {srcId: 0, commandId: 0, frameCounter: 0};
|
|
26
|
-
export const frameParserEvents = new EventEmitter();
|
|
27
|
-
|
|
28
|
-
function parseReadParameterResponse(view: DataView): Command | null {
|
|
29
|
-
const seqNumber = view.getUint8(1);
|
|
30
|
-
const status = view.getUint8(2);
|
|
31
|
-
const parameterId = view.getUint8(7);
|
|
32
|
-
let pos = 8;
|
|
33
|
-
let result = null;
|
|
34
|
-
|
|
35
|
-
if (status !== CommandStatus.Success) {
|
|
36
|
-
if (parameterId in ParamId) {
|
|
37
|
-
logger.debug(`Received read parameter response for ${ParamId[parameterId]}, seq: ${seqNumber}, status: ${status}`, NS);
|
|
38
|
-
}
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
switch (parameterId) {
|
|
43
|
-
case ParamId.MAC_ADDRESS: {
|
|
44
|
-
result = view.getBigUint64(pos, littleEndian);
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
case ParamId.APS_TRUST_CENTER_ADDRESS: {
|
|
48
|
-
result = view.getBigUint64(pos, littleEndian);
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
case ParamId.NWK_PANID: {
|
|
52
|
-
result = view.getUint16(pos, littleEndian);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
case ParamId.STK_PROTOCOL_VERSION: {
|
|
56
|
-
result = view.getUint16(pos, littleEndian);
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case ParamId.NWK_NETWORK_ADDRESS: {
|
|
60
|
-
result = view.getUint16(pos, littleEndian);
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
case ParamId.NWK_EXTENDED_PANID: {
|
|
64
|
-
result = view.getBigUint64(pos, littleEndian);
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
case ParamId.APS_USE_EXTENDED_PANID: {
|
|
68
|
-
result = view.getBigUint64(pos, littleEndian);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
case ParamId.STK_NETWORK_KEY: {
|
|
72
|
-
result = Buffer.alloc(16);
|
|
73
|
-
pos += 1; // key index
|
|
74
|
-
for (let i = 0; i < 16; i++) {
|
|
75
|
-
result[i] = view.getUint8(pos);
|
|
76
|
-
pos += 1;
|
|
77
|
-
}
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
case ParamId.STK_CURRENT_CHANNEL: {
|
|
81
|
-
result = view.getUint8(pos);
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
case ParamId.STK_ENDPOINT: {
|
|
85
|
-
result = Buffer.alloc(view.byteLength - pos);
|
|
86
|
-
for (let i = 0; pos < view.byteLength; i++, pos++) {
|
|
87
|
-
result[i] = view.getUint8(pos);
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
case ParamId.APS_CHANNEL_MASK: {
|
|
92
|
-
result = view.getUint32(pos, littleEndian);
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
case ParamId.STK_FRAME_COUNTER: {
|
|
96
|
-
result = view.getUint32(pos, littleEndian);
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
case ParamId.STK_PERMIT_JOIN: {
|
|
100
|
-
result = view.getUint8(pos);
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
case ParamId.DEV_WATCHDOG_TTL: {
|
|
104
|
-
result = view.getUint32(pos, littleEndian);
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
case ParamId.STK_NWK_UPDATE_ID: {
|
|
108
|
-
result = view.getUint8(pos);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
default:
|
|
112
|
-
//throw new Error(`unknown parameter id ${parameterId}`);
|
|
113
|
-
logger.debug(`unknown parameter id ${parameterId}`, NS);
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (parameterId in ParamId) {
|
|
118
|
-
let p: Command | string | null = result;
|
|
119
|
-
if (parameterId === ParamId.STK_NETWORK_KEY) {
|
|
120
|
-
// don't show in logs
|
|
121
|
-
p = "<hidden>";
|
|
122
|
-
} else if (typeof result === "bigint") {
|
|
123
|
-
p = `0x${result.toString(16).padStart(16, "0")}`;
|
|
124
|
-
}
|
|
125
|
-
logger.debug(`Received read parameter response for ${ParamId[parameterId]}, seq: ${seqNumber}, status: ${status}, parameter: ${p}`, NS);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function parseReadFirmwareResponse(view: DataView): number {
|
|
132
|
-
const fw = view.getUint32(5, littleEndian);
|
|
133
|
-
logger.debug(`read firmware version response - version: 0x${fw.toString(16)}`, NS);
|
|
134
|
-
return fw;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function parseDeviceStateResponse(view: DataView): number {
|
|
138
|
-
const deviceState = view.getUint8(5);
|
|
139
|
-
frameParserEvents.emit("deviceStateUpdated", deviceState);
|
|
140
|
-
return deviceState;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function parseChangeNetworkStateResponse(view: DataView): number {
|
|
144
|
-
const status = view.getUint8(2);
|
|
145
|
-
const state = view.getUint8(5);
|
|
146
|
-
logger.debug(`change network state - status: ${status} new state: ${state}`, NS);
|
|
147
|
-
return state;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function parseApsConfirmResponse(view: DataView): DataStateResponse | null {
|
|
151
|
-
const buf = new Buffalo(Buffer.from(view.buffer));
|
|
152
|
-
|
|
153
|
-
const commandId = buf.readUInt8();
|
|
154
|
-
const seqNr = buf.readUInt8();
|
|
155
|
-
const status = buf.readUInt8();
|
|
156
|
-
|
|
157
|
-
if (status !== CommandStatus.Success) {
|
|
158
|
-
logger.debug(`Response APS-DATA.confirm seq: ${seqNr} status: ${CommandStatus[status]} (error)`, NS);
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const frameLength = buf.readUInt16();
|
|
163
|
-
const payloadLength = buf.readUInt16();
|
|
164
|
-
// payload
|
|
165
|
-
const deviceState = buf.readUInt8();
|
|
166
|
-
const requestId = buf.readUInt8();
|
|
167
|
-
const destAddrMode = buf.readUInt8();
|
|
168
|
-
|
|
169
|
-
let destAddr64: string | undefined;
|
|
170
|
-
let destAddr16: number | undefined;
|
|
171
|
-
let destEndpoint: number | undefined;
|
|
172
|
-
let destAddr = "";
|
|
173
|
-
|
|
174
|
-
if (destAddrMode === ApsAddressMode.Nwk) {
|
|
175
|
-
destAddr16 = buf.readUInt16();
|
|
176
|
-
destAddr = destAddr16.toString(16).padStart(4, "0");
|
|
177
|
-
destEndpoint = buf.readUInt8();
|
|
178
|
-
} else if (destAddrMode === ApsAddressMode.Group) {
|
|
179
|
-
destAddr16 = buf.readUInt16();
|
|
180
|
-
destAddr = destAddr16.toString(16).padStart(4, "0");
|
|
181
|
-
} else if (destAddrMode === ApsAddressMode.Ieee) {
|
|
182
|
-
destAddr64 = buf.readUInt64().toString(16).padStart(16, "0");
|
|
183
|
-
destAddr = destAddr64;
|
|
184
|
-
destEndpoint = buf.readUInt8();
|
|
185
|
-
} else {
|
|
186
|
-
logger.debug(`Response APS-DATA.confirm seq: ${seqNr} unsupported address mode: ${destAddrMode}`, NS);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const srcEndpoint = buf.readUInt8();
|
|
190
|
-
const confirmStatus = buf.readUInt8();
|
|
191
|
-
|
|
192
|
-
// resolve APS-DATA.request promise
|
|
193
|
-
const i = apsBusyQueue.findIndex((r: ApsRequest) => r.request && r.request.requestId === requestId);
|
|
194
|
-
|
|
195
|
-
if (i < 0) {
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const req: ApsRequest = apsBusyQueue[i];
|
|
200
|
-
|
|
201
|
-
let strstatus = "unknown";
|
|
202
|
-
const hexstatus = `0x${confirmStatus.toString(16).padStart(2, "0")}`;
|
|
203
|
-
if (confirmStatus in ApsStatusCode) {
|
|
204
|
-
strstatus = ApsStatusCode[confirmStatus];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (confirmStatus === ApsStatusCode.Success) {
|
|
208
|
-
req.resolve(confirmStatus);
|
|
209
|
-
} else {
|
|
210
|
-
req.reject(new Error(`Failed APS-DATA.request with confirm status: ${strstatus} (${hexstatus})`));
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
//remove from busyqueue
|
|
214
|
-
apsBusyQueue.splice(i, 1);
|
|
215
|
-
|
|
216
|
-
logger.debug(`APS-DATA.confirm destAddr: 0x${destAddr} APS request id: ${requestId} confirm status: ${strstatus} ${hexstatus}`, NS);
|
|
217
|
-
frameParserEvents.emit("deviceStateUpdated", deviceState);
|
|
218
|
-
|
|
219
|
-
return {
|
|
220
|
-
commandId,
|
|
221
|
-
seqNr,
|
|
222
|
-
status,
|
|
223
|
-
frameLength,
|
|
224
|
-
payloadLength,
|
|
225
|
-
deviceState,
|
|
226
|
-
requestId,
|
|
227
|
-
destAddrMode,
|
|
228
|
-
destAddr16,
|
|
229
|
-
destAddr64,
|
|
230
|
-
destEndpoint,
|
|
231
|
-
srcEndpoint,
|
|
232
|
-
confirmStatus,
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// TODO(mpi): The ../buffalo/buffalo.ts already provides this, so we should reuse it instead of a own implementation?!
|
|
237
|
-
class UDataView {
|
|
238
|
-
littleEndian = true;
|
|
239
|
-
pos = 0;
|
|
240
|
-
view: DataView;
|
|
241
|
-
constructor(view: DataView, littleEndian: boolean) {
|
|
242
|
-
this.view = view;
|
|
243
|
-
this.littleEndian = littleEndian;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
getI8(): number {
|
|
247
|
-
if (this.pos + 1 <= this.view.byteLength) {
|
|
248
|
-
this.pos += 1;
|
|
249
|
-
return this.view.getInt8(this.pos - 1);
|
|
250
|
-
}
|
|
251
|
-
throw new RangeError();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
getU8(): number {
|
|
255
|
-
if (this.pos + 1 <= this.view.byteLength) {
|
|
256
|
-
this.pos += 1;
|
|
257
|
-
return this.view.getUint8(this.pos - 1);
|
|
258
|
-
}
|
|
259
|
-
throw new RangeError();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
getU16(): number {
|
|
263
|
-
if (this.pos + 2 <= this.view.byteLength) {
|
|
264
|
-
this.pos += 2;
|
|
265
|
-
return this.view.getUint16(this.pos - 2, this.littleEndian);
|
|
266
|
-
}
|
|
267
|
-
throw new RangeError();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
getU32(): number {
|
|
271
|
-
if (this.pos + 4 <= this.view.byteLength) {
|
|
272
|
-
this.pos += 4;
|
|
273
|
-
return this.view.getUint16(this.pos - 4, this.littleEndian);
|
|
274
|
-
}
|
|
275
|
-
throw new RangeError();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
getU64(): bigint {
|
|
279
|
-
if (this.pos + 8 <= this.view.byteLength) {
|
|
280
|
-
this.pos += 8;
|
|
281
|
-
return this.view.getBigUint64(this.pos - 8, this.littleEndian);
|
|
282
|
-
}
|
|
283
|
-
throw new RangeError();
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function parseApsDataIndicationResponse(inview: DataView): ReceivedDataResponse | null {
|
|
288
|
-
// min 28 bytelength
|
|
289
|
-
try {
|
|
290
|
-
const uview = new UDataView(inview, true);
|
|
291
|
-
|
|
292
|
-
const commandId = uview.getU8();
|
|
293
|
-
const seqNr = uview.getU8();
|
|
294
|
-
const status = uview.getU8();
|
|
295
|
-
|
|
296
|
-
if (status !== CommandStatus.Success) {
|
|
297
|
-
logger.debug(`Response APS-DATA.indication seq: ${seqNr} status: ${CommandStatus[status]}`, NS);
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const frameLength = uview.getU16();
|
|
302
|
-
const payloadLength = uview.getU16();
|
|
303
|
-
//------ start of payload ----------------------------------
|
|
304
|
-
const deviceState = uview.getU8();
|
|
305
|
-
const destAddrMode = uview.getU8();
|
|
306
|
-
|
|
307
|
-
let destAddr64: string | undefined;
|
|
308
|
-
let destAddr16: number | undefined;
|
|
309
|
-
let destAddr: string | number;
|
|
310
|
-
|
|
311
|
-
if (destAddrMode === ApsAddressMode.Ieee) {
|
|
312
|
-
destAddr64 = uview.getU64().toString(16).padStart(16, "0");
|
|
313
|
-
destAddr16 = 0xfffe;
|
|
314
|
-
destAddr = destAddr64;
|
|
315
|
-
} else if (destAddrMode === ApsAddressMode.Nwk || destAddrMode === ApsAddressMode.Group) {
|
|
316
|
-
destAddr16 = uview.getU16();
|
|
317
|
-
destAddr = destAddr16.toString(16);
|
|
318
|
-
} else {
|
|
319
|
-
throw new Error(`unsupported destination address mode: ${destAddrMode}`);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const destEndpoint = uview.getU8();
|
|
323
|
-
const srcAddrMode = uview.getU8();
|
|
324
|
-
|
|
325
|
-
let srcAddr64: string | undefined;
|
|
326
|
-
let srcAddr16 = 0xfffe;
|
|
327
|
-
let srcAddr: string | number;
|
|
328
|
-
|
|
329
|
-
if (srcAddrMode === ApsAddressMode.Nwk || srcAddrMode === ApsAddressMode.NwkAndIeee) {
|
|
330
|
-
srcAddr16 = uview.getU16();
|
|
331
|
-
srcAddr = srcAddr16.toString(16);
|
|
332
|
-
|
|
333
|
-
if (srcAddrMode === ApsAddressMode.NwkAndIeee) {
|
|
334
|
-
srcAddr64 = uview.getU64().toString(16).padStart(16, "0");
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
throw new Error(`unsupported source address mode: ${srcAddrMode}`);
|
|
338
|
-
}
|
|
339
|
-
// else if (srcAddrMode === PARAM.PARAM.addressMode.IEEE_ADDR) {
|
|
340
|
-
// srcAddr64 = uview.getU64().toString(16).padStart(16, '0');
|
|
341
|
-
// srcAddr = srcAddr64;
|
|
342
|
-
// }
|
|
343
|
-
|
|
344
|
-
const srcEndpoint = uview.getU8();
|
|
345
|
-
const profileId = uview.getU16();
|
|
346
|
-
const clusterId = uview.getU16();
|
|
347
|
-
const asduLength = uview.getU16();
|
|
348
|
-
const asdu = new Uint8Array(asduLength);
|
|
349
|
-
for (let i = 0; i < asduLength; i++) {
|
|
350
|
-
asdu[i] = uview.getU8();
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// The following two bytes depends on protocol version 2 or 3
|
|
354
|
-
// for now just discard
|
|
355
|
-
uview.getU16();
|
|
356
|
-
|
|
357
|
-
const lqi = uview.getU8();
|
|
358
|
-
|
|
359
|
-
// version >= 2
|
|
360
|
-
let rssi = 0;
|
|
361
|
-
try {
|
|
362
|
-
rssi = uview.getI8();
|
|
363
|
-
} catch (_) {}
|
|
364
|
-
|
|
365
|
-
logger.debug(
|
|
366
|
-
`Response APS-DATA.indication seq: ${seqNr} srcAddr: 0x${srcAddr} destAddr: 0x${destAddr} profile id: 0x${profileId.toString(16).padStart(4, "0")} cluster id: 0x${clusterId.toString(16).padStart(4, "0")} lqi: ${lqi}`,
|
|
367
|
-
NS,
|
|
368
|
-
);
|
|
369
|
-
//logger.debug(`Response payload: [${Array.from(asdu).map(x =>x.toString(16).padStart(2, '0')).join(' ')}]`, NS);
|
|
370
|
-
frameParserEvents.emit("deviceStateUpdated", deviceState);
|
|
371
|
-
|
|
372
|
-
const asduPayload = Buffer.from(asdu);
|
|
373
|
-
|
|
374
|
-
const response: ReceivedDataResponse = {
|
|
375
|
-
commandId,
|
|
376
|
-
seqNr,
|
|
377
|
-
status,
|
|
378
|
-
frameLength,
|
|
379
|
-
payloadLength,
|
|
380
|
-
deviceState,
|
|
381
|
-
destAddrMode,
|
|
382
|
-
destAddr16,
|
|
383
|
-
destAddr64,
|
|
384
|
-
destEndpoint,
|
|
385
|
-
srcAddrMode,
|
|
386
|
-
srcAddr16,
|
|
387
|
-
srcAddr64,
|
|
388
|
-
srcEndpoint,
|
|
389
|
-
profileId,
|
|
390
|
-
clusterId,
|
|
391
|
-
asduLength,
|
|
392
|
-
asduPayload,
|
|
393
|
-
lqi,
|
|
394
|
-
rssi,
|
|
395
|
-
zdo: profileId === Zdo.ZDO_PROFILE_ID ? Zdo.Buffalo.readResponse(true, clusterId, asduPayload) : undefined,
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
frameParserEvents.emit("receivedDataPayload", response);
|
|
399
|
-
return response;
|
|
400
|
-
} catch (error) {
|
|
401
|
-
logger.debug(`Response APS-DATA.indication error: ${error}`, NS);
|
|
402
|
-
return null;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function parseApsDataRequestResponse(view: DataView): number | null {
|
|
407
|
-
try {
|
|
408
|
-
const status = view.getUint8(2);
|
|
409
|
-
const requestId = view.getUint8(8);
|
|
410
|
-
const deviceState = view.getUint8(7);
|
|
411
|
-
logger.debug(`Response APS-DATA.request APS request id: ${requestId} status: ${CommandStatus[status]}`, NS);
|
|
412
|
-
frameParserEvents.emit("deviceStateUpdated", deviceState);
|
|
413
|
-
return deviceState;
|
|
414
|
-
} catch (error) {
|
|
415
|
-
logger.debug(`parseEnqueueSendDataResponse - ${error}`, NS);
|
|
416
|
-
return null;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
function parseWriteParameterResponse(view: DataView): number | null {
|
|
421
|
-
try {
|
|
422
|
-
const status = view.getUint8(2);
|
|
423
|
-
const parameterId = view.getUint8(7);
|
|
424
|
-
|
|
425
|
-
if (parameterId in ParamId) {
|
|
426
|
-
// should always be true
|
|
427
|
-
logger.debug(`Write parameter response parameter: ${ParamId[parameterId]}, status: ${CommandStatus[status]}`, NS);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return parameterId;
|
|
431
|
-
} catch (error) {
|
|
432
|
-
logger.debug(`parseWriteParameterResponse - ${error}`, NS);
|
|
433
|
-
return null;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
function parseDeviceStateChangedNotification(view: DataView): number | null {
|
|
438
|
-
try {
|
|
439
|
-
const deviceState = view.getUint8(5);
|
|
440
|
-
frameParserEvents.emit("deviceStateUpdated", deviceState);
|
|
441
|
-
return deviceState;
|
|
442
|
-
} catch (error) {
|
|
443
|
-
logger.debug(`parsedeviceStateUpdated - ${error}`, NS);
|
|
444
|
-
return null;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// The ApplicationID sub-field contains the information about the application used by the GPD.
|
|
449
|
-
// ApplicationID = 0b000 indicates the GPD_ID field has the length of 4B and contains the GPD SrcID.
|
|
450
|
-
// ApplicationID = 0b010 indicates the GPD_ID field has the length of 8B and contains the GPD IEEE address.
|
|
451
|
-
enum GpApplicationId {
|
|
452
|
-
SrcId4B = 0,
|
|
453
|
-
Lped = 1,
|
|
454
|
-
Ieee8B = 2,
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
enum GpSecurityLevel {
|
|
458
|
-
NoSecurity = 0,
|
|
459
|
-
// TODO(mpi): "Reserved" is noted in the available spec but the code defined it as follows:
|
|
460
|
-
Reserved = 1, // 0b01 1LSB of frame counter and short (2B) MIC only
|
|
461
|
-
FrameCounter4BMic4B = 2,
|
|
462
|
-
EncryptionFrameCounter4BMic4B = 3,
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
enum ZgpConstants {
|
|
466
|
-
GpNwkProtocolVersion = 3,
|
|
467
|
-
GpNwkDataFrame = 0,
|
|
468
|
-
GpNwkMaintenanceFrame = 1,
|
|
469
|
-
GpMinMsduSize = 1,
|
|
470
|
-
GpAutoCommissioningFlag = 1 << 6,
|
|
471
|
-
GpNwkFrameControlExtensionFlag = 1 << 7,
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function parseGreenPowerDataIndication(view: DataView): GpDataInd | null {
|
|
475
|
-
try {
|
|
476
|
-
let srcId = 0;
|
|
477
|
-
let frameCounter = 0;
|
|
478
|
-
let commandId = 0;
|
|
479
|
-
let commandFrameSize = 0;
|
|
480
|
-
let commandFrame: Buffer | undefined;
|
|
481
|
-
|
|
482
|
-
const buf = new Buffalo(Buffer.from(view.buffer));
|
|
483
|
-
|
|
484
|
-
const _fwCommandId = buf.readUInt8();
|
|
485
|
-
const seqNr = buf.readUInt8();
|
|
486
|
-
const fwStatus = buf.readUInt8();
|
|
487
|
-
|
|
488
|
-
if (fwStatus !== CommandStatus.Success) {
|
|
489
|
-
return null;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
const _frameLength = buf.readUInt16();
|
|
493
|
-
const _payloadLength = buf.readUInt16();
|
|
494
|
-
|
|
495
|
-
// payload
|
|
496
|
-
|
|
497
|
-
// implementation ported from deCONZ GP code
|
|
498
|
-
const nwkFrameControl = buf.readUInt8();
|
|
499
|
-
|
|
500
|
-
// check frame type
|
|
501
|
-
const frameType = nwkFrameControl & 0x03;
|
|
502
|
-
|
|
503
|
-
if (frameType !== ZgpConstants.GpNwkDataFrame && frameType !== ZgpConstants.GpNwkMaintenanceFrame) {
|
|
504
|
-
return null;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// check green power protocol version
|
|
508
|
-
if (((nwkFrameControl >> 2) & 0x03) !== ZgpConstants.GpNwkProtocolVersion) {
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// extended frame control
|
|
513
|
-
let nwkExtFrameControl = 0;
|
|
514
|
-
const hasExtensionFlag = nwkFrameControl & ZgpConstants.GpNwkFrameControlExtensionFlag;
|
|
515
|
-
if (hasExtensionFlag) {
|
|
516
|
-
nwkExtFrameControl = buf.readUInt8();
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
const options = nwkExtFrameControl | (nwkFrameControl << 8);
|
|
520
|
-
|
|
521
|
-
const applicationId = nwkExtFrameControl & 7;
|
|
522
|
-
const securityLevel = (nwkExtFrameControl >> 3) & 3;
|
|
523
|
-
|
|
524
|
-
if (applicationId !== GpApplicationId.SrcId4B && applicationId !== GpApplicationId.Ieee8B) {
|
|
525
|
-
return null; // NOTE: GpApplicationId.Lped (1) should be dropped as per spec
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// The GPDSrcID field is present if the Frame Type sub-field is set to 0b00 and the ApplicationID sub-
|
|
529
|
-
// field of the Extended NWK Frame Control field is set to 0b000 (or not present).
|
|
530
|
-
if (
|
|
531
|
-
applicationId === GpApplicationId.SrcId4B &&
|
|
532
|
-
frameType === ZgpConstants.GpNwkDataFrame /*|| (frameType === ZgpConstants.GpNwkMaintenanceFrame && hasExtensionFlag) */
|
|
533
|
-
) {
|
|
534
|
-
srcId = buf.readUInt32();
|
|
535
|
-
}
|
|
536
|
-
// TODO(mpi): for applicationId == GpApplicationId.Ieee8B:
|
|
537
|
-
// currently Ieee addresses aren't supported, do they actually appear?!
|
|
538
|
-
// these need be extracted from MAC header which we don't have here (this is only the NWK payload).
|
|
539
|
-
|
|
540
|
-
// frame counter filed
|
|
541
|
-
frameCounter = 0;
|
|
542
|
-
let micSize = 0;
|
|
543
|
-
|
|
544
|
-
if (hasExtensionFlag && frameType === ZgpConstants.GpNwkDataFrame) {
|
|
545
|
-
if (applicationId === GpApplicationId.Ieee8B) {
|
|
546
|
-
const _endpoint = buf.readUInt8();
|
|
547
|
-
}
|
|
548
|
-
// If the SecurityLevel is set to 0b00, the SecurityKey sub-field is ignored on reception, and the
|
|
549
|
-
// fields Security frame counter and MIC are not present.
|
|
550
|
-
if (securityLevel === GpSecurityLevel.Reserved) {
|
|
551
|
-
micSize = 2; // TODO(mpi) does this actually exists? Check recent specs!
|
|
552
|
-
} else if (securityLevel === GpSecurityLevel.FrameCounter4BMic4B || securityLevel === GpSecurityLevel.EncryptionFrameCounter4BMic4B) {
|
|
553
|
-
frameCounter = buf.readUInt32();
|
|
554
|
-
micSize = 4;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
if (!buf.isMore()) {
|
|
559
|
-
return null;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
if (applicationId === GpApplicationId.SrcId4B || applicationId === GpApplicationId.Ieee8B) {
|
|
563
|
-
commandId = buf.readUInt8();
|
|
564
|
-
commandFrameSize = buf.getBuffer().length - buf.getPosition() - micSize;
|
|
565
|
-
//logger.debug(`GPD payload length: ${commandFrameSize}, mic size: ${micSize}`, NS);
|
|
566
|
-
if (commandFrameSize < 0) {
|
|
567
|
-
logger.error(`GPD payload length < 0: ${commandFrameSize}`, NS);
|
|
568
|
-
return null;
|
|
569
|
-
}
|
|
570
|
-
commandFrame = Buffer.from(buf.readBuffer(commandFrameSize)); // copy
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
// NOTE(mpi): The old adapter treated (view.byteLength < 30) as notification, larger as commissioning?!
|
|
574
|
-
// The controller thus rejected commissioning frames.
|
|
575
|
-
const id = 0; // 0 = notification, 4 = commissioning
|
|
576
|
-
|
|
577
|
-
if (commandFrame === undefined) {
|
|
578
|
-
logger.debug("GPD discard frame since commandFrame is null?!", NS);
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const ind: GpDataInd = {
|
|
583
|
-
seqNr,
|
|
584
|
-
id,
|
|
585
|
-
options,
|
|
586
|
-
srcId,
|
|
587
|
-
frameCounter,
|
|
588
|
-
commandId,
|
|
589
|
-
commandFrameSize,
|
|
590
|
-
commandFrame,
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
// TODO(mpi): This only tracks one frame, might be a bit optimistic
|
|
594
|
-
if (!(lastReceivedGpInd.srcId === srcId && lastReceivedGpInd.commandId === commandId && lastReceivedGpInd.frameCounter === frameCounter)) {
|
|
595
|
-
lastReceivedGpInd.srcId = srcId;
|
|
596
|
-
lastReceivedGpInd.commandId = commandId;
|
|
597
|
-
lastReceivedGpInd.frameCounter = frameCounter;
|
|
598
|
-
//logger.debug(`GP_DATA_INDICATION - src id: ${srcId} cmd id: ${commandId} frameCounter: ${frameCounter}`, NS);
|
|
599
|
-
logger.debug(
|
|
600
|
-
`GP_DATA_INDICATION - src id: 0x${srcId.toString(16)} cmd id: 0x${commandId.toString(16)} frameCounter: 0x${frameCounter.toString(16)}`,
|
|
601
|
-
NS,
|
|
602
|
-
);
|
|
603
|
-
frameParserEvents.emit("receivedGreenPowerIndication", ind);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
return ind;
|
|
607
|
-
} catch (error) {
|
|
608
|
-
logger.debug(`GREEN_POWER INDICATION - ${error}`, NS);
|
|
609
|
-
return null;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
function parseMacPollCommand(_view: DataView): number {
|
|
614
|
-
//logger.debug("Received command MAC_POLL", NS);
|
|
615
|
-
return FirmwareCommand.MacPollIndication;
|
|
616
|
-
}
|
|
617
|
-
function parseBeaconRequest(_view: DataView): number {
|
|
618
|
-
logger.debug("Received Beacon Request", NS);
|
|
619
|
-
return FirmwareCommand.Beacon;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
function parseDebugLog(view: DataView): null {
|
|
623
|
-
let dbg = "";
|
|
624
|
-
const buf = new Buffalo(Buffer.from(view.buffer));
|
|
625
|
-
|
|
626
|
-
/* const commandId = */ buf.readUInt8();
|
|
627
|
-
/* const seqNr = */ buf.readUInt8();
|
|
628
|
-
const status = buf.readUInt8();
|
|
629
|
-
|
|
630
|
-
if (status !== CommandStatus.Success) {
|
|
631
|
-
// unlikely
|
|
632
|
-
return null;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
/* const frameLength = */ buf.readUInt16();
|
|
636
|
-
const payloadLength = buf.readUInt16();
|
|
637
|
-
|
|
638
|
-
for (let i = 0; i < payloadLength && buf.isMore(); i++) {
|
|
639
|
-
const ch = buf.readUInt8();
|
|
640
|
-
if (ch >= 32 && ch <= 127) {
|
|
641
|
-
dbg += String.fromCharCode(ch);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
if (dbg.length !== 0) {
|
|
646
|
-
logger.debug(`firmware log: ${dbg}`, NS);
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
return null;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function parseUnknownCommand(view: DataView): number {
|
|
653
|
-
const id = view.getUint8(0);
|
|
654
|
-
if (id in FirmwareCommand) {
|
|
655
|
-
logger.debug(`received unsupported command: ${FirmwareCommand[id]} id: 0x${id.toString(16).padStart(2, "0")}`, NS);
|
|
656
|
-
} else {
|
|
657
|
-
logger.debug(`received unknown command: id: 0x${id.toString(16).padStart(2, "0")}`, NS);
|
|
658
|
-
}
|
|
659
|
-
return id;
|
|
660
|
-
}
|
|
661
|
-
function getParserForCommandId(id: number): (view: DataView) => Command | object | number | null {
|
|
662
|
-
switch (id) {
|
|
663
|
-
case FirmwareCommand.ReadParameter:
|
|
664
|
-
return parseReadParameterResponse;
|
|
665
|
-
case FirmwareCommand.WriteParameter:
|
|
666
|
-
return parseWriteParameterResponse;
|
|
667
|
-
case FirmwareCommand.FirmwareVersion:
|
|
668
|
-
return parseReadFirmwareResponse;
|
|
669
|
-
case FirmwareCommand.Status:
|
|
670
|
-
return parseDeviceStateResponse;
|
|
671
|
-
case FirmwareCommand.ApsDataIndication:
|
|
672
|
-
return parseApsDataIndicationResponse;
|
|
673
|
-
case FirmwareCommand.ApsDataRequest:
|
|
674
|
-
return parseApsDataRequestResponse;
|
|
675
|
-
case FirmwareCommand.ApsDataConfirm:
|
|
676
|
-
return parseApsConfirmResponse;
|
|
677
|
-
case FirmwareCommand.StatusChangeIndication:
|
|
678
|
-
return parseDeviceStateChangedNotification;
|
|
679
|
-
case FirmwareCommand.ChangeNetworkState:
|
|
680
|
-
return parseChangeNetworkStateResponse;
|
|
681
|
-
case FirmwareCommand.ZgpDataIndication:
|
|
682
|
-
return parseGreenPowerDataIndication;
|
|
683
|
-
case FirmwareCommand.MacPollIndication:
|
|
684
|
-
return parseMacPollCommand;
|
|
685
|
-
case FirmwareCommand.Beacon:
|
|
686
|
-
return parseBeaconRequest;
|
|
687
|
-
case FirmwareCommand.DebugLog:
|
|
688
|
-
return parseDebugLog;
|
|
689
|
-
default:
|
|
690
|
-
return parseUnknownCommand;
|
|
691
|
-
//throw new Error(`unknown command id ${id}`);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function processFrame(frame: Uint8Array): void {
|
|
696
|
-
const [seqNumber, status, command, commandId] = parseFrame(frame);
|
|
697
|
-
// logger.debug(`Process frame with cmd: 0x${commandId.toString(16).padStart(2,'0')}, seq: ${seqNumber} status: ${status}`, NS);
|
|
698
|
-
|
|
699
|
-
let queue: ApsRequest[] | Request[] = busyQueue;
|
|
700
|
-
|
|
701
|
-
if (commandId === FirmwareCommand.ApsDataRequest) {
|
|
702
|
-
queue = apsBusyQueue;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
const i = queue.findIndex((r: ApsRequest | Request) => r.seqNumber === seqNumber && r.commandId === commandId);
|
|
706
|
-
if (i < 0) {
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
const req: ApsRequest | Request = queue[i];
|
|
711
|
-
|
|
712
|
-
if (commandId === FirmwareCommand.ApsDataRequest) {
|
|
713
|
-
if (status === CommandStatus.Success) {
|
|
714
|
-
// wait for APS-DATA.confirm to arrive
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// TODO(mpi): Within the timeout we should reschedule the APS-DATA.request (given that network state = connected)
|
|
719
|
-
// continue to reject as there will be no APS-DATA.confirm
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
//remove from busyqueue
|
|
723
|
-
queue.splice(i, 1);
|
|
724
|
-
|
|
725
|
-
if (status === CommandStatus.Success) {
|
|
726
|
-
req.resolve(command);
|
|
727
|
-
} else if (status === CommandStatus.Unsupported && commandId === FirmwareCommand.ReadParameter) {
|
|
728
|
-
// resolve anyway to let higher layer handle unsupported
|
|
729
|
-
req.resolve(command);
|
|
730
|
-
} else {
|
|
731
|
-
let cmdName: string;
|
|
732
|
-
if (commandId in FirmwareCommand) {
|
|
733
|
-
cmdName = FirmwareCommand[commandId];
|
|
734
|
-
} else {
|
|
735
|
-
cmdName = `0x${commandId.toString(16).padStart(2, "0")}`;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
req.reject(new Error(`Command ${cmdName} failed with status: ${CommandStatus[status]}`));
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function parseFrame(frame: Uint8Array): [number, number, ReturnType<ReturnType<typeof getParserForCommandId>>, number] {
|
|
743
|
-
// at this point frame.buffer.length is at least 5 bytes long
|
|
744
|
-
const view = new DataView(frame.buffer);
|
|
745
|
-
const commandId = view.getUint8(0);
|
|
746
|
-
const seqNumber = view.getUint8(1);
|
|
747
|
-
const status = view.getUint8(2);
|
|
748
|
-
const parser = getParserForCommandId(commandId);
|
|
749
|
-
|
|
750
|
-
return [seqNumber, status, parser(view), commandId];
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
export default processFrame;
|