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