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.
Files changed (252) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +12 -3
  3. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  4. package/.github/dependabot.yml +0 -22
  5. package/.github/workflows/ci.yml +0 -69
  6. package/.github/workflows/release-please.yml +0 -18
  7. package/.github/workflows/stale.yml +0 -20
  8. package/.github/workflows/typedoc.yaml +0 -47
  9. package/.release-please-manifest.json +0 -3
  10. package/.vscode/extensions.json +0 -3
  11. package/.vscode/settings.json +0 -11
  12. package/biome.json +0 -98
  13. package/examples/join-and-log.js +0 -24
  14. package/release-please-config.json +0 -9
  15. package/src/adapter/adapter.ts +0 -189
  16. package/src/adapter/adapterDiscovery.ts +0 -666
  17. package/src/adapter/const.ts +0 -12
  18. package/src/adapter/deconz/adapter/deconzAdapter.ts +0 -877
  19. package/src/adapter/deconz/driver/constants.ts +0 -246
  20. package/src/adapter/deconz/driver/driver.ts +0 -1540
  21. package/src/adapter/deconz/driver/frame.ts +0 -11
  22. package/src/adapter/deconz/driver/frameParser.ts +0 -753
  23. package/src/adapter/deconz/driver/parser.ts +0 -45
  24. package/src/adapter/deconz/driver/writer.ts +0 -22
  25. package/src/adapter/deconz/types.d.ts +0 -13
  26. package/src/adapter/ember/adapter/emberAdapter.ts +0 -2265
  27. package/src/adapter/ember/adapter/endpoints.ts +0 -86
  28. package/src/adapter/ember/adapter/oneWaitress.ts +0 -324
  29. package/src/adapter/ember/adapter/tokensManager.ts +0 -782
  30. package/src/adapter/ember/consts.ts +0 -178
  31. package/src/adapter/ember/enums.ts +0 -1746
  32. package/src/adapter/ember/ezsp/buffalo.ts +0 -1392
  33. package/src/adapter/ember/ezsp/consts.ts +0 -148
  34. package/src/adapter/ember/ezsp/enums.ts +0 -1114
  35. package/src/adapter/ember/ezsp/ezsp.ts +0 -9061
  36. package/src/adapter/ember/ezspError.ts +0 -10
  37. package/src/adapter/ember/types.ts +0 -866
  38. package/src/adapter/ember/uart/ash.ts +0 -1960
  39. package/src/adapter/ember/uart/consts.ts +0 -109
  40. package/src/adapter/ember/uart/enums.ts +0 -192
  41. package/src/adapter/ember/uart/parser.ts +0 -48
  42. package/src/adapter/ember/uart/queues.ts +0 -247
  43. package/src/adapter/ember/uart/writer.ts +0 -53
  44. package/src/adapter/ember/utils/initters.ts +0 -58
  45. package/src/adapter/ember/utils/math.ts +0 -73
  46. package/src/adapter/events.ts +0 -21
  47. package/src/adapter/ezsp/adapter/backup.ts +0 -109
  48. package/src/adapter/ezsp/adapter/ezspAdapter.ts +0 -614
  49. package/src/adapter/ezsp/driver/commands.ts +0 -2497
  50. package/src/adapter/ezsp/driver/consts.ts +0 -11
  51. package/src/adapter/ezsp/driver/driver.ts +0 -1002
  52. package/src/adapter/ezsp/driver/ezsp.ts +0 -802
  53. package/src/adapter/ezsp/driver/frame.ts +0 -101
  54. package/src/adapter/ezsp/driver/index.ts +0 -4
  55. package/src/adapter/ezsp/driver/multicast.ts +0 -78
  56. package/src/adapter/ezsp/driver/parser.ts +0 -81
  57. package/src/adapter/ezsp/driver/types/basic.ts +0 -201
  58. package/src/adapter/ezsp/driver/types/index.ts +0 -239
  59. package/src/adapter/ezsp/driver/types/named.ts +0 -2330
  60. package/src/adapter/ezsp/driver/types/struct.ts +0 -844
  61. package/src/adapter/ezsp/driver/uart.ts +0 -460
  62. package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +0 -44
  63. package/src/adapter/ezsp/driver/utils/index.ts +0 -32
  64. package/src/adapter/ezsp/driver/writer.ts +0 -64
  65. package/src/adapter/index.ts +0 -3
  66. package/src/adapter/serialPort.ts +0 -58
  67. package/src/adapter/socketPortUtils.ts +0 -16
  68. package/src/adapter/tstype.ts +0 -78
  69. package/src/adapter/z-stack/adapter/adapter-backup.ts +0 -519
  70. package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +0 -457
  71. package/src/adapter/z-stack/adapter/endpoints.ts +0 -57
  72. package/src/adapter/z-stack/adapter/manager.ts +0 -543
  73. package/src/adapter/z-stack/adapter/tstype.ts +0 -6
  74. package/src/adapter/z-stack/adapter/zStackAdapter.ts +0 -1190
  75. package/src/adapter/z-stack/constants/af.ts +0 -27
  76. package/src/adapter/z-stack/constants/common.ts +0 -285
  77. package/src/adapter/z-stack/constants/dbg.ts +0 -23
  78. package/src/adapter/z-stack/constants/index.ts +0 -11
  79. package/src/adapter/z-stack/constants/mac.ts +0 -128
  80. package/src/adapter/z-stack/constants/sapi.ts +0 -25
  81. package/src/adapter/z-stack/constants/sys.ts +0 -72
  82. package/src/adapter/z-stack/constants/util.ts +0 -82
  83. package/src/adapter/z-stack/constants/utils.ts +0 -14
  84. package/src/adapter/z-stack/constants/zdo.ts +0 -103
  85. package/src/adapter/z-stack/models/startup-options.ts +0 -13
  86. package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +0 -44
  87. package/src/adapter/z-stack/structs/entries/address-manager-table.ts +0 -19
  88. package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +0 -12
  89. package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +0 -21
  90. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +0 -19
  91. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +0 -21
  92. package/src/adapter/z-stack/structs/entries/channel-list.ts +0 -8
  93. package/src/adapter/z-stack/structs/entries/has-configured.ts +0 -16
  94. package/src/adapter/z-stack/structs/entries/index.ts +0 -16
  95. package/src/adapter/z-stack/structs/entries/nib.ts +0 -66
  96. package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +0 -15
  97. package/src/adapter/z-stack/structs/entries/nwk-key.ts +0 -13
  98. package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +0 -8
  99. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +0 -20
  100. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +0 -19
  101. package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +0 -33
  102. package/src/adapter/z-stack/structs/entries/security-manager-table.ts +0 -22
  103. package/src/adapter/z-stack/structs/index.ts +0 -4
  104. package/src/adapter/z-stack/structs/serializable-memory-object.ts +0 -14
  105. package/src/adapter/z-stack/structs/struct.ts +0 -367
  106. package/src/adapter/z-stack/structs/table.ts +0 -198
  107. package/src/adapter/z-stack/unpi/constants.ts +0 -33
  108. package/src/adapter/z-stack/unpi/frame.ts +0 -62
  109. package/src/adapter/z-stack/unpi/index.ts +0 -4
  110. package/src/adapter/z-stack/unpi/parser.ts +0 -56
  111. package/src/adapter/z-stack/unpi/writer.ts +0 -21
  112. package/src/adapter/z-stack/utils/channel-list.ts +0 -40
  113. package/src/adapter/z-stack/utils/index.ts +0 -2
  114. package/src/adapter/z-stack/utils/network-options.ts +0 -26
  115. package/src/adapter/z-stack/znp/buffaloZnp.ts +0 -175
  116. package/src/adapter/z-stack/znp/definition.ts +0 -2713
  117. package/src/adapter/z-stack/znp/index.ts +0 -2
  118. package/src/adapter/z-stack/znp/parameterType.ts +0 -22
  119. package/src/adapter/z-stack/znp/tstype.ts +0 -44
  120. package/src/adapter/z-stack/znp/utils.ts +0 -10
  121. package/src/adapter/z-stack/znp/znp.ts +0 -342
  122. package/src/adapter/z-stack/znp/zpiObject.ts +0 -148
  123. package/src/adapter/zboss/adapter/zbossAdapter.ts +0 -526
  124. package/src/adapter/zboss/commands.ts +0 -1184
  125. package/src/adapter/zboss/consts.ts +0 -9
  126. package/src/adapter/zboss/driver.ts +0 -422
  127. package/src/adapter/zboss/enums.ts +0 -360
  128. package/src/adapter/zboss/frame.ts +0 -227
  129. package/src/adapter/zboss/reader.ts +0 -65
  130. package/src/adapter/zboss/types.ts +0 -0
  131. package/src/adapter/zboss/uart.ts +0 -428
  132. package/src/adapter/zboss/utils.ts +0 -58
  133. package/src/adapter/zboss/writer.ts +0 -49
  134. package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +0 -27
  135. package/src/adapter/zigate/adapter/zigateAdapter.ts +0 -618
  136. package/src/adapter/zigate/driver/LICENSE +0 -17
  137. package/src/adapter/zigate/driver/buffaloZiGate.ts +0 -212
  138. package/src/adapter/zigate/driver/commandType.ts +0 -418
  139. package/src/adapter/zigate/driver/constants.ts +0 -150
  140. package/src/adapter/zigate/driver/frame.ts +0 -197
  141. package/src/adapter/zigate/driver/messageType.ts +0 -287
  142. package/src/adapter/zigate/driver/parameterType.ts +0 -32
  143. package/src/adapter/zigate/driver/ziGateObject.ts +0 -146
  144. package/src/adapter/zigate/driver/zigate.ts +0 -423
  145. package/src/adapter/zoh/adapter/utils.ts +0 -27
  146. package/src/adapter/zoh/adapter/zohAdapter.ts +0 -838
  147. package/src/buffalo/buffalo.ts +0 -342
  148. package/src/buffalo/index.ts +0 -1
  149. package/src/controller/controller.ts +0 -1022
  150. package/src/controller/database.ts +0 -124
  151. package/src/controller/events.ts +0 -52
  152. package/src/controller/greenPower.ts +0 -603
  153. package/src/controller/helpers/index.ts +0 -1
  154. package/src/controller/helpers/installCodes.ts +0 -107
  155. package/src/controller/helpers/request.ts +0 -96
  156. package/src/controller/helpers/requestQueue.ts +0 -125
  157. package/src/controller/helpers/zclFrameConverter.ts +0 -47
  158. package/src/controller/helpers/zclTransactionSequenceNumber.ts +0 -19
  159. package/src/controller/index.ts +0 -6
  160. package/src/controller/model/device.ts +0 -1249
  161. package/src/controller/model/endpoint.ts +0 -1105
  162. package/src/controller/model/entity.ts +0 -23
  163. package/src/controller/model/group.ts +0 -424
  164. package/src/controller/model/index.ts +0 -5
  165. package/src/controller/model/zigbeeEntity.ts +0 -30
  166. package/src/controller/touchlink.ts +0 -189
  167. package/src/controller/tstype.ts +0 -274
  168. package/src/index.ts +0 -12
  169. package/src/models/backup-storage-legacy.ts +0 -48
  170. package/src/models/backup-storage-unified.ts +0 -47
  171. package/src/models/backup.ts +0 -37
  172. package/src/models/index.ts +0 -5
  173. package/src/models/network-options.ts +0 -11
  174. package/src/utils/backup.ts +0 -152
  175. package/src/utils/index.ts +0 -5
  176. package/src/utils/logger.ts +0 -20
  177. package/src/utils/patchBigIntSerialization.ts +0 -8
  178. package/src/utils/queue.ts +0 -76
  179. package/src/utils/types.d.ts +0 -3
  180. package/src/utils/utils.ts +0 -19
  181. package/src/utils/wait.ts +0 -5
  182. package/src/utils/waitress.ts +0 -96
  183. package/src/zspec/consts.ts +0 -84
  184. package/src/zspec/enums.ts +0 -22
  185. package/src/zspec/index.ts +0 -3
  186. package/src/zspec/tstypes.ts +0 -18
  187. package/src/zspec/utils.ts +0 -247
  188. package/src/zspec/zcl/buffaloZcl.ts +0 -1220
  189. package/src/zspec/zcl/definition/cluster.ts +0 -5915
  190. package/src/zspec/zcl/definition/clusters-typegen.ts +0 -588
  191. package/src/zspec/zcl/definition/clusters-types.ts +0 -7331
  192. package/src/zspec/zcl/definition/consts.ts +0 -24
  193. package/src/zspec/zcl/definition/enums.ts +0 -203
  194. package/src/zspec/zcl/definition/foundation.ts +0 -329
  195. package/src/zspec/zcl/definition/manufacturerCode.ts +0 -729
  196. package/src/zspec/zcl/definition/status.ts +0 -69
  197. package/src/zspec/zcl/definition/tstype.ts +0 -377
  198. package/src/zspec/zcl/index.ts +0 -11
  199. package/src/zspec/zcl/utils.ts +0 -321
  200. package/src/zspec/zcl/zclFrame.ts +0 -356
  201. package/src/zspec/zcl/zclHeader.ts +0 -102
  202. package/src/zspec/zcl/zclStatusError.ts +0 -10
  203. package/src/zspec/zdo/buffaloZdo.ts +0 -2336
  204. package/src/zspec/zdo/definition/clusters.ts +0 -722
  205. package/src/zspec/zdo/definition/consts.ts +0 -16
  206. package/src/zspec/zdo/definition/enums.ts +0 -99
  207. package/src/zspec/zdo/definition/status.ts +0 -105
  208. package/src/zspec/zdo/definition/tstypes.ts +0 -1062
  209. package/src/zspec/zdo/index.ts +0 -7
  210. package/src/zspec/zdo/utils.ts +0 -76
  211. package/src/zspec/zdo/zdoStatusError.ts +0 -10
  212. package/test/adapter/adapter.test.ts +0 -1062
  213. package/test/adapter/ember/ash.test.ts +0 -337
  214. package/test/adapter/ember/consts.ts +0 -131
  215. package/test/adapter/ember/emberAdapter.test.ts +0 -3449
  216. package/test/adapter/ember/ezsp.test.ts +0 -385
  217. package/test/adapter/ember/ezspBuffalo.test.ts +0 -93
  218. package/test/adapter/ember/ezspError.test.ts +0 -12
  219. package/test/adapter/ember/math.test.ts +0 -206
  220. package/test/adapter/ezsp/frame.test.ts +0 -30
  221. package/test/adapter/ezsp/uart.test.ts +0 -181
  222. package/test/adapter/z-stack/adapter.test.ts +0 -3984
  223. package/test/adapter/z-stack/constants.test.ts +0 -33
  224. package/test/adapter/z-stack/structs.test.ts +0 -115
  225. package/test/adapter/z-stack/unpi.test.ts +0 -213
  226. package/test/adapter/z-stack/znp.test.ts +0 -1284
  227. package/test/adapter/zboss/fixZdoResponse.test.ts +0 -179
  228. package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +0 -81
  229. package/test/adapter/zigate/zdo.test.ts +0 -187
  230. package/test/adapter/zoh/utils.test.ts +0 -36
  231. package/test/adapter/zoh/zohAdapter.test.ts +0 -1307
  232. package/test/benchOptions.ts +0 -14
  233. package/test/buffalo.test.ts +0 -431
  234. package/test/controller.bench.ts +0 -214
  235. package/test/controller.test.ts +0 -8702
  236. package/test/greenpower.test.ts +0 -1408
  237. package/test/mockAdapters.ts +0 -65
  238. package/test/mockDevices.ts +0 -598
  239. package/test/requests.bench.ts +0 -229
  240. package/test/testUtils.ts +0 -20
  241. package/test/tsconfig.json +0 -9
  242. package/test/utils/math.ts +0 -19
  243. package/test/utils.test.ts +0 -279
  244. package/test/vitest.config.mts +0 -26
  245. package/test/zcl.test.ts +0 -2831
  246. package/test/zspec/utils.test.ts +0 -68
  247. package/test/zspec/zcl/buffalo.test.ts +0 -1374
  248. package/test/zspec/zcl/frame.test.ts +0 -960
  249. package/test/zspec/zcl/utils.test.ts +0 -273
  250. package/test/zspec/zdo/buffalo.test.ts +0 -1850
  251. package/test/zspec/zdo/utils.test.ts +0 -241
  252. 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;