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,1307 +0,0 @@
1
- import {randomBytes} from "node:crypto";
2
- import {mkdirSync, rmSync, writeFileSync} from "node:fs";
3
- import {join} from "node:path";
4
-
5
- import {afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
6
- import {encodeSpinelFrame, SPINEL_HEADER_FLG_SPINEL} from "zigbee-on-host/dist/spinel/spinel";
7
- import {SpinelStatus} from "zigbee-on-host/dist/spinel/statuses";
8
- import type {MACCapabilities} from "zigbee-on-host/dist/zigbee/mac";
9
- import type {ZigbeeNWKLinkStatus} from "zigbee-on-host/dist/zigbee/zigbee-nwk";
10
-
11
- import {bigUInt64ToHexBE} from "../../../src/adapter/zoh/adapter/utils";
12
- import {ZoHAdapter} from "../../../src/adapter/zoh/adapter/zohAdapter";
13
- import * as ZSpec from "../../../src/zspec";
14
- import * as Zcl from "../../../src/zspec/zcl";
15
- import * as Zdo from "../../../src/zspec/zdo";
16
-
17
- const TEMP_PATH = "zoh-tmp";
18
- const TEMP_PATH_SAVE = join(TEMP_PATH, "zoh.save");
19
- const DEFAULT_PAN_ID = 0x1a62;
20
- const DEFAULT_EXT_PAN_ID = [0xdd, 0x11, 0x22, 0xdd, 0xdd, 0x33, 0x44, 0xdd];
21
- const DEFAULT_CHANNEL = 11;
22
- const DEFAULT_NETWORK_KEY = [0x11, 0x03, 0x15, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x00, 0x02, 0x04, 0x06, 0x08, 0x1a, 0x1c, 0x1d];
23
- const DEFAULT_STATE_FILE_HEX =
24
- "5a6f486f6e5a324d621add1122dddd3344dd0b001311031507090b0d0f00020406081a1c1d00040000005a6967426565416c6c69616e636530390004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
25
-
26
- // biome-ignore lint/correctness/noUnusedVariables: dev
27
- const randomBigInt = (): bigint => BigInt(`0x${randomBytes(8).toString("hex")}`);
28
-
29
- /** SL-OPENTHREAD/2.5.2.0_GitHub-1fceb225b; EFR32; Mar 19 2025 13:45:44 */
30
- const START_FRAMES_SILABS = {
31
- protocolVersion: "7e8106010403db0a7e",
32
- ncpVersion:
33
- "7e820602534c2d4f50454e5448524541442f322e352e322e305f4769744875622d3166636562323235623b2045465233323b204d617220313920323032352031333a34353a343400b5dc7e",
34
- interfaceType: "7e83060303573a7e",
35
- rcpAPIVersion: "7e8406b0010a681f7e",
36
- rcpMinHostAPIVersion: "7e8506b101048ea77e",
37
- resetPowerOn: "7e80060070ee747e",
38
- };
39
- /** SL-OPENTHREAD/2.5.2.0_GitHub-1fceb225b; EFR32; Mar 19 2025 13:45:44 */
40
- const FORM_FRAMES_SILABS = {
41
- phyEnabled: "7e87062001f2627e",
42
- phyChan: "7e88062114ff8e7e",
43
- phyTxPowerSet: "7e8906257d339b817e",
44
- mac154LAddr: "7e8a06344d325a6e6f486f5a8f327e",
45
- mac154SAddr: "7e8b0635000047f67e",
46
- mac154PANId: "7e8c0636d98579727e",
47
- macRxOnWhenIdleMode: "7e8d060000e68c7e",
48
- macRawStreamEnabled: "7e8e06370108437e",
49
- phyTxPowerGet: "7e8106257d3343647e",
50
- phyRSSIGet: "7e820626983d517e",
51
- phyRXSensitivityGet: "7e8306279c7a127e",
52
- phyCCAThresholdGet: "7e840624b5f0d37e",
53
- };
54
- // /** SL-OPENTHREAD/2.5.2.0_GitHub-1fceb225b; EFR32; Mar 19 2025 13:45:44 */
55
- // const STOP_FRAMES_SILABS = {
56
- // macRawStreamEnabled: "7e8b063700d63c7e",
57
- // phyEnabled: "7e8c0620006eb37e",
58
- // }
59
- const COMMON_FFD_MAC_CAP: MACCapabilities = {
60
- alternatePANCoordinator: false,
61
- deviceType: 1,
62
- powerSource: 1,
63
- rxOnWhenIdle: true,
64
- securityCapability: false,
65
- allocateAddress: true,
66
- };
67
- const COMMON_RFD_MAC_CAP: MACCapabilities = {
68
- alternatePANCoordinator: false,
69
- deviceType: 0,
70
- powerSource: 0,
71
- rxOnWhenIdle: false,
72
- securityCapability: false,
73
- allocateAddress: true,
74
- };
75
-
76
- describe("ZigBee on Host", () => {
77
- let adapter: ZoHAdapter;
78
- let nextTidFromStartup = 1;
79
-
80
- const deleteZoHSave = () => {
81
- rmSync(TEMP_PATH_SAVE, {force: true});
82
- };
83
-
84
- const makeSpinelLastStatus = (tid: number, status: SpinelStatus = SpinelStatus.OK): Buffer => {
85
- const respSpinelFrame = {
86
- header: {
87
- tid,
88
- nli: 0,
89
- flg: SPINEL_HEADER_FLG_SPINEL,
90
- },
91
- commandId: 6 /* PROP_VALUE_IS */,
92
- payload: Buffer.from([0 /* LAST_STATUS */, status]),
93
- };
94
- const encRespHdlcFrame = encodeSpinelFrame(respSpinelFrame);
95
-
96
- return Buffer.from(encRespHdlcFrame.data.subarray(0, encRespHdlcFrame.length));
97
- };
98
-
99
- // biome-ignore lint/correctness/noUnusedVariables: dev
100
- const makeSpinelStreamRaw = (tid: number, macFrame: Buffer, spinelMeta?: Buffer): Buffer => {
101
- const spinelFrame = {
102
- header: {
103
- tid,
104
- nli: 0,
105
- flg: SPINEL_HEADER_FLG_SPINEL,
106
- },
107
- commandId: 6 /* PROP_VALUE_IS */,
108
- payload: Buffer.from([
109
- 113 /* STREAM_RAW */,
110
- macFrame.byteLength & 0xff,
111
- (macFrame.byteLength >> 8) & 0xff,
112
- ...macFrame,
113
- ...(spinelMeta || []),
114
- ]),
115
- };
116
- const encHdlcFrame = encodeSpinelFrame(spinelFrame);
117
-
118
- return Buffer.from(encHdlcFrame.data.subarray(0, encHdlcFrame.length));
119
- };
120
-
121
- const mockStart = async (loadState = true, frames = START_FRAMES_SILABS) => {
122
- if (adapter.driver) {
123
- let loadStateSpy: ReturnType<typeof vi.spyOn> | undefined;
124
-
125
- if (!loadState) {
126
- loadStateSpy = vi.spyOn(adapter.driver, "loadState").mockResolvedValue(undefined);
127
- }
128
-
129
- let i = -1;
130
- const orderedFrames = [
131
- frames.protocolVersion,
132
- frames.ncpVersion,
133
- frames.interfaceType,
134
- frames.rcpAPIVersion,
135
- frames.rcpMinHostAPIVersion,
136
- frames.resetPowerOn,
137
- ];
138
-
139
- const reply = async () => {
140
- await vi.advanceTimersByTimeAsync(5);
141
-
142
- // skip cancel byte
143
- if (i >= 0) {
144
- adapter.driver.parser._transform(Buffer.from(orderedFrames[i], "hex"), "utf8", () => {});
145
- await vi.advanceTimersByTimeAsync(5);
146
- }
147
-
148
- i++;
149
-
150
- if (i === orderedFrames.length) {
151
- adapter.driver.writer.removeListener("data", reply);
152
- }
153
- };
154
-
155
- adapter.driver.writer.on("data", reply);
156
- await adapter.driver.start();
157
- loadStateSpy?.mockRestore();
158
- await vi.advanceTimersByTimeAsync(100); // flush
159
-
160
- nextTidFromStartup = adapter.driver.currentSpinelTID + 1;
161
- }
162
- };
163
-
164
- const mockStop = async (expectThrow?: string) => {
165
- if (adapter.driver) {
166
- const setPropertySpy = vi.spyOn(adapter.driver, "setProperty").mockResolvedValue();
167
-
168
- if (expectThrow !== undefined) {
169
- await expect(adapter.driver.stop()).rejects.toThrow();
170
- } else {
171
- await adapter.driver.stop();
172
- }
173
-
174
- setPropertySpy.mockRestore();
175
-
176
- await vi.advanceTimersByTimeAsync(100); // flush
177
- }
178
-
179
- nextTidFromStartup = 1;
180
- };
181
-
182
- const mockFormNetwork = async (registerTimers = false, frames = FORM_FRAMES_SILABS) => {
183
- if (adapter.driver) {
184
- let i = 0;
185
- const orderedFrames = [
186
- frames.phyEnabled,
187
- frames.phyChan,
188
- frames.phyTxPowerSet,
189
- frames.mac154LAddr,
190
- frames.mac154SAddr,
191
- frames.mac154PANId,
192
- frames.macRxOnWhenIdleMode,
193
- frames.macRawStreamEnabled,
194
- frames.phyTxPowerGet,
195
- frames.phyRSSIGet,
196
- frames.phyRXSensitivityGet,
197
- frames.phyCCAThresholdGet,
198
- ];
199
-
200
- const reply = async () => {
201
- await vi.advanceTimersByTimeAsync(5);
202
- adapter.driver.parser._transform(Buffer.from(orderedFrames[i], "hex"), "utf8", () => {});
203
- await vi.advanceTimersByTimeAsync(5);
204
-
205
- i++;
206
-
207
- if (i === orderedFrames.length) {
208
- adapter.driver.writer.removeListener("data", reply);
209
- }
210
- };
211
-
212
- adapter.driver.writer.on("data", reply);
213
-
214
- let registerTimersSpy: ReturnType<typeof vi.spyOn> | undefined;
215
-
216
- if (registerTimers) {
217
- await mockRegisterTimers();
218
- } else {
219
- registerTimersSpy = vi.spyOn(adapter.driver, "registerTimers").mockResolvedValue();
220
- }
221
-
222
- await adapter.driver.formNetwork();
223
-
224
- registerTimersSpy?.mockRestore();
225
-
226
- await vi.advanceTimersByTimeAsync(100); // flush
227
-
228
- nextTidFromStartup = adapter.driver.currentSpinelTID + 1;
229
- }
230
- };
231
-
232
- const mockRegisterTimers = async () => {
233
- if (adapter.driver) {
234
- let linksSpy: ZigbeeNWKLinkStatus[] | undefined;
235
- let manyToOneSpy: number | undefined;
236
- let destination16Spy: number | undefined;
237
-
238
- // creates a bottleneck with vitest & promises, noop it
239
- const savePeriodicStateSpy = vi.spyOn(adapter.driver, "savePeriodicState").mockResolvedValue();
240
- const sendZigbeeNWKLinkStatusSpy = vi.spyOn(adapter.driver, "sendZigbeeNWKLinkStatus").mockImplementationOnce(async (links) => {
241
- linksSpy = links;
242
- const p = adapter.driver.sendZigbeeNWKLinkStatus(links);
243
- // LINK_STATUS => OK
244
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup), "utf8", () => {});
245
- await vi.advanceTimersByTimeAsync(10);
246
- await p;
247
- });
248
- const sendZigbeeNWKRouteReqSpy = vi
249
- .spyOn(adapter.driver, "sendZigbeeNWKRouteReq")
250
- .mockImplementationOnce(async (manyToOne, destination16) => {
251
- manyToOneSpy = manyToOne;
252
- destination16Spy = destination16;
253
- const p = adapter.driver.sendZigbeeNWKRouteReq(manyToOne, destination16);
254
- // ROUTE_REQ => OK
255
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup + 1), "utf8", () => {});
256
- await vi.advanceTimersByTimeAsync(10);
257
- return await p;
258
- });
259
- await adapter.driver.registerTimers();
260
- await vi.advanceTimersByTimeAsync(100); // flush
261
-
262
- expect(savePeriodicStateSpy).toHaveBeenCalledTimes(1);
263
- expect(sendZigbeeNWKLinkStatusSpy).toHaveBeenCalledTimes(1 + 1); // *2 by spy mock
264
- expect(sendZigbeeNWKRouteReqSpy).toHaveBeenCalledTimes(1 + 1); // *2 by spy mock
265
-
266
- nextTidFromStartup = adapter.driver.currentSpinelTID + 1;
267
-
268
- return [linksSpy, manyToOneSpy, destination16Spy];
269
- }
270
-
271
- return [undefined, undefined, undefined];
272
- };
273
-
274
- beforeAll(() => {
275
- vi.useFakeTimers();
276
-
277
- rmSync(TEMP_PATH, {force: true, recursive: true});
278
- mkdirSync(TEMP_PATH, {recursive: true});
279
- });
280
-
281
- afterAll(() => {
282
- vi.useRealTimers();
283
-
284
- rmSync(TEMP_PATH, {force: true, recursive: true});
285
- });
286
-
287
- beforeEach(() => {
288
- deleteZoHSave();
289
-
290
- adapter = new ZoHAdapter(
291
- {
292
- panID: DEFAULT_PAN_ID,
293
- extendedPanID: DEFAULT_EXT_PAN_ID,
294
- channelList: [DEFAULT_CHANNEL],
295
- networkKey: DEFAULT_NETWORK_KEY,
296
- networkKeyDistribute: false,
297
- },
298
- {
299
- baudRate: 460800,
300
- rtscts: true,
301
- path: "/dev/serial/by-id/mock-adapter",
302
- adapter: "zoh",
303
- },
304
- join(TEMP_PATH, "ember_coordinator_backup.json"),
305
- {
306
- concurrent: 8,
307
- disableLED: false,
308
- transmitPower: 19,
309
- },
310
- );
311
-
312
- vi.spyOn(adapter, "initPort").mockImplementation(async () => {});
313
- vi.spyOn(adapter.driver, "start").mockImplementationOnce(async () => {
314
- await mockStart();
315
- });
316
- vi.spyOn(adapter.driver, "formNetwork").mockImplementationOnce(async () => {
317
- await mockFormNetwork();
318
- });
319
- vi.spyOn(adapter.driver, "stop").mockImplementationOnce(async () => {
320
- await mockStop();
321
- });
322
- vi.spyOn(adapter.driver.writer, "pipe").mockImplementation(
323
- // @ts-expect-error mock noop
324
- () => {},
325
- );
326
-
327
- adapter.driver.parser.on("data", adapter.driver.onFrame.bind(adapter.driver));
328
- });
329
-
330
- afterEach(async () => {
331
- await adapter.stop();
332
- });
333
-
334
- it("Adapter impl: gets state", async () => {
335
- await expect(adapter.start()).resolves.toStrictEqual("reset");
336
- await expect(adapter.getCoordinatorIEEE()).resolves.toStrictEqual("0x4d325a6e6f486f5a");
337
- await expect(adapter.getCoordinatorVersion()).resolves.toStrictEqual({
338
- type: "ZigBee on Host",
339
- meta: {
340
- major: 4,
341
- minor: 3,
342
- apiVersion: 10,
343
- version: "SL-OPENTHREAD/2.5.2.0_GitHub-1fceb225b; EFR32; Mar 19 2025 13:45:44",
344
- revision: "https://github.com/Nerivec/zigbee-on-host (using: SL-OPENTHREAD/2.5.2.0_GitHub-1fceb225b; EFR32; Mar 19 2025 13:45:44)",
345
- },
346
- });
347
- await expect(adapter.getNetworkParameters()).resolves.toStrictEqual({
348
- panID: DEFAULT_PAN_ID,
349
- extendedPanID: `0x${bigUInt64ToHexBE(Buffer.from(DEFAULT_EXT_PAN_ID).readBigUint64LE())}`,
350
- channel: DEFAULT_CHANNEL,
351
- nwkUpdateID: 0,
352
- });
353
- });
354
-
355
- it("Adapter impl: sendZdo to device", async () => {
356
- await adapter.start();
357
-
358
- await adapter.driver.associate(0x2211, BigInt("0x0807060504030201"), true, structuredClone(COMMON_FFD_MAC_CAP), true, false, true);
359
-
360
- const p1 = adapter.sendZdo(
361
- "0x0807060504030201",
362
- 0x2211,
363
- Zdo.ClusterId.IEEE_ADDRESS_REQUEST,
364
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.IEEE_ADDRESS_REQUEST, 0x2211, false, 0),
365
- false,
366
- );
367
-
368
- await vi.advanceTimersByTimeAsync(10);
369
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup, SpinelStatus.OK), "utf8", () => {});
370
- await vi.advanceTimersByTimeAsync(10);
371
- adapter.driver.emit(
372
- "frame",
373
- 0x2211,
374
- BigInt("0x0807060504030201"),
375
- {
376
- frameControl: {
377
- frameType: 0 /* DATA */,
378
- deliveryMode: 0 /* UNICAST */,
379
- ackFormat: false,
380
- security: false,
381
- ackRequest: false,
382
- extendedHeader: false,
383
- },
384
- profileId: 0x0,
385
- clusterId: Zdo.ClusterId.IEEE_ADDRESS_RESPONSE,
386
- sourceEndpoint: 0x0,
387
- destEndpoint: 0x0,
388
- },
389
- Buffer.from([1, 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x11, 0x22]),
390
- 150,
391
- );
392
- await vi.advanceTimersByTimeAsync(10);
393
-
394
- await expect(p1).resolves.toStrictEqual([
395
- 0,
396
- {
397
- eui64: "0x0807060504030201",
398
- nwkAddress: 0x2211,
399
- startIndex: 0,
400
- assocDevList: [],
401
- },
402
- ]);
403
-
404
- const p2 = adapter.sendZdo(
405
- "0x0807060504030201",
406
- 0x2211,
407
- Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
408
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x0807060504030201", false, 0),
409
- false,
410
- );
411
-
412
- await vi.advanceTimersByTimeAsync(10);
413
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup + 1, SpinelStatus.OK), "utf8", () => {});
414
- await vi.advanceTimersByTimeAsync(10);
415
- adapter.driver.emit(
416
- "frame",
417
- 0x2211,
418
- BigInt("0x0807060504030201"),
419
- {
420
- frameControl: {
421
- frameType: 0 /* DATA */,
422
- deliveryMode: 0 /* UNICAST */,
423
- ackFormat: false,
424
- security: false,
425
- ackRequest: false,
426
- extendedHeader: false,
427
- },
428
- profileId: 0x0,
429
- clusterId: Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE,
430
- sourceEndpoint: 0x0,
431
- destEndpoint: 0x0,
432
- },
433
- Buffer.from([2, 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x11, 0x22]),
434
- 150,
435
- );
436
- await vi.advanceTimersByTimeAsync(10);
437
-
438
- await expect(p2).resolves.toStrictEqual([
439
- 0,
440
- {
441
- eui64: "0x0807060504030201",
442
- nwkAddress: 0x2211,
443
- startIndex: 0,
444
- assocDevList: [],
445
- },
446
- ]);
447
- });
448
-
449
- it("Adapter impl: sendZdo to coordinator", async () => {
450
- await adapter.start();
451
-
452
- const emitSpy = vi.spyOn(adapter, "emit");
453
-
454
- await adapter.sendZdo(
455
- `0x${bigUInt64ToHexBE(adapter.driver.netParams.eui64)}`,
456
- 0x0000,
457
- Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST,
458
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST, 0x0000),
459
- false,
460
- );
461
-
462
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.NODE_DESCRIPTOR_RESPONSE, [
463
- 0,
464
- expect.objectContaining({
465
- nwkAddress: 0x0000,
466
- logicalType: 0x00,
467
- manufacturerCode: Zcl.ManufacturerCode.CONNECTIVITY_STANDARDS_ALLIANCE,
468
- serverMask: expect.objectContaining({primaryTrustCenter: 1, stackComplianceRevision: 22}),
469
- }),
470
- ]);
471
-
472
- await adapter.sendZdo(
473
- `0x${bigUInt64ToHexBE(adapter.driver.netParams.eui64)}`,
474
- 0x0000,
475
- Zdo.ClusterId.POWER_DESCRIPTOR_REQUEST,
476
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.POWER_DESCRIPTOR_REQUEST, 0x0000),
477
- false,
478
- );
479
-
480
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.POWER_DESCRIPTOR_RESPONSE, [
481
- 0,
482
- expect.objectContaining({nwkAddress: 0x0000}),
483
- ]);
484
-
485
- await adapter.sendZdo(
486
- `0x${bigUInt64ToHexBE(adapter.driver.netParams.eui64)}`,
487
- 0x0000,
488
- Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST,
489
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST, 0x0000, 1),
490
- false,
491
- );
492
-
493
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.SIMPLE_DESCRIPTOR_RESPONSE, [
494
- 0,
495
- expect.objectContaining({endpoint: 1, profileId: ZSpec.HA_PROFILE_ID}),
496
- ]);
497
-
498
- await adapter.sendZdo(
499
- `0x${bigUInt64ToHexBE(adapter.driver.netParams.eui64)}`,
500
- 0x0000,
501
- Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST,
502
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST, 0x0000),
503
- false,
504
- );
505
-
506
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.ACTIVE_ENDPOINTS_RESPONSE, [
507
- 0,
508
- {nwkAddress: 0, endpointList: [1, 242]},
509
- ]);
510
-
511
- await expect(
512
- adapter.sendZdo(
513
- `0x${bigUInt64ToHexBE(adapter.driver.netParams.eui64)}`,
514
- 0x0000,
515
- Zdo.ClusterId.PARENT_ANNOUNCE,
516
- Zdo.Buffalo.buildRequest(true, Zdo.ClusterId.PARENT_ANNOUNCE, []),
517
- false,
518
- ),
519
- ).rejects.toThrow(`Coordinator does not support ZDO cluster ${Zdo.ClusterId.PARENT_ANNOUNCE}`);
520
- });
521
-
522
- it("Adapter impl: permitJoin", async () => {
523
- await adapter.start();
524
-
525
- const sendZdoSpy = vi.spyOn(adapter, "sendZdo");
526
- const allowJoinsSpy = vi.spyOn(adapter.driver, "allowJoins");
527
- const gpEnterCommissioningModeSpy = vi.spyOn(adapter.driver, "gpEnterCommissioningMode");
528
-
529
- sendZdoSpy.mockImplementationOnce(async () => [0, undefined]);
530
- await adapter.permitJoin(254);
531
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(254, true);
532
- expect(gpEnterCommissioningModeSpy).toHaveBeenLastCalledWith(254);
533
-
534
- sendZdoSpy.mockImplementationOnce(async () => [0, undefined]);
535
- await adapter.permitJoin(0);
536
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(0, true);
537
- expect(gpEnterCommissioningModeSpy).toHaveBeenLastCalledWith(0);
538
-
539
- await adapter.permitJoin(200, 0x0000);
540
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(200, true);
541
- expect(gpEnterCommissioningModeSpy).toHaveBeenLastCalledWith(200);
542
-
543
- sendZdoSpy.mockImplementationOnce(async () => [0, undefined]);
544
- await adapter.permitJoin(0);
545
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(0, true);
546
- expect(gpEnterCommissioningModeSpy).toHaveBeenLastCalledWith(0);
547
- expect(gpEnterCommissioningModeSpy).toHaveBeenCalledTimes(4);
548
-
549
- sendZdoSpy.mockImplementationOnce(async () => [0, undefined]);
550
- await adapter.permitJoin(150, 0x1234);
551
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(150, false);
552
- expect(gpEnterCommissioningModeSpy).toHaveBeenCalledTimes(4);
553
-
554
- sendZdoSpy.mockImplementationOnce(async () => [0, undefined]);
555
- await adapter.permitJoin(0);
556
- expect(allowJoinsSpy).toHaveBeenLastCalledWith(0, true);
557
- expect(gpEnterCommissioningModeSpy).toHaveBeenLastCalledWith(0);
558
- expect(gpEnterCommissioningModeSpy).toHaveBeenCalledTimes(5);
559
- });
560
-
561
- it("Adapter impl: sendZclFrameToEndpoint", async () => {
562
- await adapter.start();
563
-
564
- await adapter.driver.associate(0x9876, BigInt("0x00000000000004d2"), true, structuredClone(COMMON_FFD_MAC_CAP), true, false, true);
565
-
566
- const sendUnicastSpy = vi.spyOn(adapter.driver, "sendUnicast");
567
-
568
- const zclPayload = Buffer.from([16, 123, Zcl.Foundation.read.ID]);
569
- const zclFrame = Zcl.Frame.fromBuffer(Zcl.Clusters.genGroups.ID, Zcl.Header.fromBuffer(zclPayload), zclPayload, {});
570
-
571
- const p1 = adapter.sendZclFrameToEndpoint("0x00000000000004d2", 0x9876, 1, zclFrame, 10000, false, false, 2);
572
-
573
- await vi.advanceTimersByTimeAsync(10);
574
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup, SpinelStatus.OK), "utf8", () => {});
575
- await vi.advanceTimersByTimeAsync(10);
576
- adapter.driver.emit(
577
- "frame",
578
- 0x9876,
579
- undefined,
580
- {
581
- frameControl: {
582
- frameType: 0 /* DATA */,
583
- deliveryMode: 0 /* UNICAST */,
584
- ackFormat: false,
585
- security: false,
586
- ackRequest: false,
587
- extendedHeader: false,
588
- },
589
- profileId: ZSpec.HA_PROFILE_ID,
590
- clusterId: Zcl.Clusters.genGroups.ID,
591
- sourceEndpoint: 0x1,
592
- destEndpoint: 0x2,
593
- },
594
- Buffer.from([0, 123, Zcl.Foundation.read.response!, 0x01, 0xff]),
595
- 215,
596
- );
597
- await expect(p1).resolves.toStrictEqual({
598
- address: 0x9876,
599
- clusterID: Zcl.Clusters.genGroups.ID,
600
- data: Buffer.from([0, 123, Zcl.Foundation.read.response!, 0x01, 0xff]),
601
- destinationEndpoint: 2,
602
- endpoint: 1,
603
- groupID: undefined,
604
- header: expect.objectContaining({
605
- commandIdentifier: 1,
606
- frameControl: {
607
- direction: 0,
608
- disableDefaultResponse: false,
609
- frameType: 0,
610
- manufacturerSpecific: false,
611
- reservedBits: 0,
612
- },
613
- manufacturerCode: undefined,
614
- transactionSequenceNumber: 123,
615
- }),
616
- linkquality: 215,
617
- wasBroadcast: false,
618
- });
619
- expect(sendUnicastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genGroups.ID, 0x9876, undefined, 1, 2);
620
-
621
- sendUnicastSpy.mockResolvedValueOnce(2);
622
-
623
- const p2 = adapter.sendZclFrameToEndpoint("0x00000000000004d2", 0x9876, 1, zclFrame, 10000, true, false);
624
-
625
- await vi.advanceTimersByTimeAsync(10);
626
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup + 1, SpinelStatus.OK), "utf8", () => {});
627
- await vi.advanceTimersByTimeAsync(10);
628
- await expect(p2).resolves.toStrictEqual(undefined);
629
- expect(sendUnicastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genGroups.ID, 0x9876, undefined, 1, 1);
630
-
631
- const zclPayloadDefRsp = Buffer.from([0, 123, Zcl.Foundation.read.ID]);
632
- const zclFrameDefRsp = Zcl.Frame.fromBuffer(Zcl.Clusters.genGroups.ID, Zcl.Header.fromBuffer(zclPayloadDefRsp), zclPayloadDefRsp, {});
633
-
634
- sendUnicastSpy.mockResolvedValueOnce(3);
635
-
636
- const p3 = adapter.sendZclFrameToEndpoint("0x00000000000004d2", 0x9876, 1, zclFrameDefRsp, 10000, true, false, 2);
637
-
638
- await vi.advanceTimersByTimeAsync(10);
639
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup + 2, SpinelStatus.OK), "utf8", () => {});
640
- await vi.advanceTimersByTimeAsync(10);
641
- adapter.driver.emit(
642
- "frame",
643
- 0x9876,
644
- undefined,
645
- {
646
- frameControl: {
647
- frameType: 0 /* DATA */,
648
- deliveryMode: 0 /* UNICAST */,
649
- ackFormat: false,
650
- security: false,
651
- ackRequest: false,
652
- extendedHeader: false,
653
- },
654
- profileId: ZSpec.HA_PROFILE_ID,
655
- clusterId: Zcl.Clusters.genGroups.ID,
656
- sourceEndpoint: 0x1,
657
- destEndpoint: 0x2,
658
- },
659
- Buffer.from([0, 123, Zcl.Foundation.defaultRsp.ID, 0x01, 0xff]),
660
- 125,
661
- );
662
- await expect(p3).resolves.toStrictEqual({
663
- address: 0x9876,
664
- clusterID: Zcl.Clusters.genGroups.ID,
665
- data: Buffer.from([0, 123, Zcl.Foundation.defaultRsp.ID, 0x01, 0xff]),
666
- destinationEndpoint: 2,
667
- endpoint: 1,
668
- groupID: undefined,
669
- header: expect.objectContaining({
670
- commandIdentifier: Zcl.Foundation.defaultRsp.ID,
671
- frameControl: {
672
- direction: 0,
673
- disableDefaultResponse: false,
674
- frameType: 0,
675
- manufacturerSpecific: false,
676
- reservedBits: 0,
677
- },
678
- manufacturerCode: undefined,
679
- transactionSequenceNumber: 123,
680
- }),
681
- linkquality: 125,
682
- wasBroadcast: false,
683
- });
684
- expect(sendUnicastSpy).toHaveBeenLastCalledWith(
685
- zclFrameDefRsp.toBuffer(),
686
- ZSpec.HA_PROFILE_ID,
687
- Zcl.Clusters.genGroups.ID,
688
- 0x9876,
689
- undefined,
690
- 1,
691
- 2,
692
- );
693
-
694
- sendUnicastSpy.mockClear();
695
- sendUnicastSpy.mockRejectedValueOnce(new Error("Failed")).mockResolvedValueOnce(2);
696
-
697
- const p4 = adapter.sendZclFrameToEndpoint("0x00000000000004d2", 0x9876, 1, zclFrame, 10000, false, false, 2);
698
-
699
- await vi.advanceTimersByTimeAsync(10);
700
- adapter.driver.parser._transform(makeSpinelLastStatus(nextTidFromStartup + 3, SpinelStatus.OK), "utf8", () => {});
701
- await vi.advanceTimersByTimeAsync(10);
702
- adapter.driver.emit(
703
- "frame",
704
- 0x9876,
705
- undefined,
706
- {
707
- frameControl: {
708
- frameType: 0 /* DATA */,
709
- deliveryMode: 0 /* UNICAST */,
710
- ackFormat: false,
711
- security: false,
712
- ackRequest: false,
713
- extendedHeader: false,
714
- },
715
- profileId: ZSpec.HA_PROFILE_ID,
716
- clusterId: Zcl.Clusters.genGroups.ID,
717
- sourceEndpoint: 0x1,
718
- destEndpoint: 0x2,
719
- },
720
- Buffer.from([0, 123, Zcl.Foundation.read.response!, 0x01, 0xff]),
721
- 225,
722
- );
723
- await expect(p4).resolves.toStrictEqual({
724
- address: 0x9876,
725
- clusterID: Zcl.Clusters.genGroups.ID,
726
- data: Buffer.from([0, 123, Zcl.Foundation.read.response!, 0x01, 0xff]),
727
- destinationEndpoint: 2,
728
- endpoint: 1,
729
- groupID: undefined,
730
- header: expect.objectContaining({
731
- commandIdentifier: 1,
732
- frameControl: {
733
- direction: 0,
734
- disableDefaultResponse: false,
735
- frameType: 0,
736
- manufacturerSpecific: false,
737
- reservedBits: 0,
738
- },
739
- manufacturerCode: undefined,
740
- transactionSequenceNumber: 123,
741
- }),
742
- linkquality: 225,
743
- wasBroadcast: false,
744
- });
745
- expect(sendUnicastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genGroups.ID, 0x9876, undefined, 1, 2);
746
- expect(sendUnicastSpy).toHaveBeenCalledTimes(2);
747
-
748
- sendUnicastSpy.mockClear();
749
- sendUnicastSpy.mockRejectedValueOnce(new Error("Failed")).mockRejectedValueOnce(new Error("Failed"));
750
-
751
- await expect(adapter.sendZclFrameToEndpoint("0x00000000000004d2", 0x9876, 1, zclFrame, 10000, false, false, 2)).rejects.toThrow("Failed");
752
- expect(sendUnicastSpy).toHaveBeenCalledTimes(2);
753
-
754
- const zclFrameGP = Zcl.Frame.fromBuffer(Zcl.Clusters.greenPower.ID, Zcl.Header.fromBuffer(zclPayload), zclPayload, {});
755
-
756
- sendUnicastSpy.mockClear();
757
-
758
- await expect(
759
- adapter.sendZclFrameToEndpoint("0xb43a31fffe0f6aae", 57129, ZSpec.GP_ENDPOINT, zclFrameGP, 10000, true, false, ZSpec.GP_ENDPOINT),
760
- ).rejects.toThrow("Unknown destination");
761
- expect(sendUnicastSpy).toHaveBeenCalledTimes(2);
762
- });
763
-
764
- it("Adapter impl: sendZclFrameToGroup", async () => {
765
- await adapter.start();
766
-
767
- const sendGroupcastSpy = vi.spyOn(adapter.driver, "sendGroupcast").mockResolvedValueOnce(1).mockResolvedValueOnce(1).mockResolvedValueOnce(1);
768
-
769
- const zclPayload = Buffer.from([0, 123, Zcl.Foundation.read.ID]);
770
- const zclFrame = Zcl.Frame.fromBuffer(Zcl.Clusters.genGroups.ID, Zcl.Header.fromBuffer(zclPayload), zclPayload, {});
771
-
772
- const p1 = adapter.sendZclFrameToGroup(123, zclFrame, 5);
773
-
774
- await vi.advanceTimersByTimeAsync(1000);
775
- await expect(p1).resolves.toStrictEqual(undefined);
776
- expect(sendGroupcastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genGroups.ID, 123, 5);
777
-
778
- const p2 = adapter.sendZclFrameToGroup(123, zclFrame);
779
-
780
- await vi.advanceTimersByTimeAsync(1000);
781
- await expect(p2).resolves.toStrictEqual(undefined);
782
- expect(sendGroupcastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genGroups.ID, 123, 1);
783
- });
784
-
785
- it("Adapter impl: sendZclFrameToAll", async () => {
786
- await adapter.start();
787
-
788
- const sendBroadcastSpy = vi.spyOn(adapter.driver, "sendBroadcast").mockResolvedValueOnce(1).mockResolvedValueOnce(1);
789
-
790
- const zclPayload = Buffer.from([0, 123, Zcl.Foundation.read.ID]);
791
- const zclFrame = Zcl.Frame.fromBuffer(Zcl.Clusters.genAlarms.ID, Zcl.Header.fromBuffer(zclPayload), zclPayload, {});
792
-
793
- const p = adapter.sendZclFrameToAll(3, zclFrame, 1, 0xfffc);
794
-
795
- await vi.advanceTimersByTimeAsync(1000);
796
- await expect(p).resolves.toStrictEqual(undefined);
797
- expect(sendBroadcastSpy).toHaveBeenLastCalledWith(zclFrame.toBuffer(), ZSpec.HA_PROFILE_ID, Zcl.Clusters.genAlarms.ID, 0xfffc, 3, 1);
798
-
799
- const p2 = adapter.sendZclFrameToAll(ZSpec.GP_ENDPOINT, zclFrame, ZSpec.GP_ENDPOINT, 0xfffc);
800
-
801
- await vi.advanceTimersByTimeAsync(1000);
802
- await expect(p2).resolves.toStrictEqual(undefined);
803
- expect(sendBroadcastSpy).toHaveBeenLastCalledWith(
804
- zclFrame.toBuffer(),
805
- ZSpec.GP_PROFILE_ID,
806
- Zcl.Clusters.genAlarms.ID,
807
- 0xfffc,
808
- ZSpec.GP_ENDPOINT,
809
- ZSpec.GP_ENDPOINT,
810
- );
811
- });
812
-
813
- it("receives ZDO frame", async () => {
814
- await adapter.start();
815
-
816
- const emitSpy = vi.spyOn(adapter, "emit");
817
-
818
- adapter.driver.emit(
819
- "frame",
820
- 0x2211,
821
- 578437695752307201n,
822
- {
823
- frameControl: {
824
- frameType: 0 /* DATA */,
825
- deliveryMode: 0 /* UNICAST */,
826
- ackFormat: false,
827
- security: false,
828
- ackRequest: false,
829
- extendedHeader: false,
830
- },
831
- profileId: 0x0,
832
- clusterId: Zdo.ClusterId.IEEE_ADDRESS_RESPONSE,
833
- sourceEndpoint: 0x0,
834
- destEndpoint: 0x0,
835
- },
836
- Buffer.from([1, 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x11, 0x22]),
837
- -50,
838
- );
839
-
840
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.IEEE_ADDRESS_RESPONSE, [
841
- 0,
842
- {
843
- eui64: "0x0807060504030201",
844
- nwkAddress: 0x2211,
845
- startIndex: 0,
846
- assocDevList: [],
847
- },
848
- ]);
849
-
850
- // NETWORK_ADDRESS_RESPONSE codepath
851
- adapter.driver.emit(
852
- "frame",
853
- 0x2211,
854
- 578437695752307201n,
855
- {
856
- frameControl: {
857
- frameType: 0 /* DATA */,
858
- deliveryMode: 0 /* UNICAST */,
859
- ackFormat: false,
860
- security: false,
861
- ackRequest: false,
862
- extendedHeader: false,
863
- },
864
- profileId: 0x0,
865
- clusterId: Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE,
866
- sourceEndpoint: 0x0,
867
- destEndpoint: 0x0,
868
- },
869
- Buffer.from([1, 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x11, 0x22]),
870
- -50,
871
- );
872
-
873
- expect(emitSpy).toHaveBeenLastCalledWith("zdoResponse", Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE, [
874
- 0,
875
- {
876
- eui64: "0x0807060504030201",
877
- nwkAddress: 0x2211,
878
- startIndex: 0,
879
- assocDevList: [],
880
- },
881
- ]);
882
- });
883
-
884
- it("receives ZCL frame", async () => {
885
- await adapter.start();
886
-
887
- const emitSpy = vi.spyOn(adapter, "emit");
888
-
889
- adapter.driver.emit(
890
- "frame",
891
- 0x9876,
892
- undefined,
893
- {
894
- frameControl: {
895
- frameType: 0 /* DATA */,
896
- deliveryMode: 0 /* UNICAST */,
897
- ackFormat: false,
898
- security: false,
899
- ackRequest: false,
900
- extendedHeader: false,
901
- },
902
- profileId: ZSpec.HA_PROFILE_ID,
903
- clusterId: Zcl.Clusters.genAlarms.ID,
904
- sourceEndpoint: 0x1,
905
- destEndpoint: 0x1,
906
- },
907
- Buffer.from([0, 123, Zcl.Foundation.read.ID, 0x01, 0xff]),
908
- 125,
909
- );
910
-
911
- expect(emitSpy).toHaveBeenLastCalledWith("zclPayload", {
912
- address: 0x9876,
913
- clusterID: Zcl.Clusters.genAlarms.ID,
914
- data: Buffer.from([0, 123, Zcl.Foundation.read.ID, 0x01, 0xff]),
915
- destinationEndpoint: 1,
916
- endpoint: 1,
917
- groupID: undefined,
918
- header: {
919
- commandIdentifier: Zcl.Foundation.read.ID,
920
- frameControl: {
921
- direction: 0,
922
- disableDefaultResponse: false,
923
- frameType: 0,
924
- manufacturerSpecific: false,
925
- reservedBits: 0,
926
- },
927
- manufacturerCode: undefined,
928
- transactionSequenceNumber: 123,
929
- },
930
- linkquality: 125,
931
- wasBroadcast: false,
932
- });
933
-
934
- adapter.driver.emit(
935
- "frame",
936
- 0x9876,
937
- 1234n,
938
- {
939
- frameControl: {
940
- frameType: 0 /* DATA */,
941
- deliveryMode: 0 /* UNICAST */,
942
- ackFormat: false,
943
- security: false,
944
- ackRequest: false,
945
- extendedHeader: false,
946
- },
947
- profileId: ZSpec.HA_PROFILE_ID,
948
- clusterId: Zcl.Clusters.genIdentify.ID,
949
- sourceEndpoint: 0x1,
950
- destEndpoint: 0x1,
951
- },
952
- Buffer.from([0, 123, 0x00, 0x01, 0xff]),
953
- 155,
954
- );
955
-
956
- expect(emitSpy).toHaveBeenLastCalledWith("zclPayload", {
957
- address: "0x00000000000004d2",
958
- clusterID: Zcl.Clusters.genIdentify.ID,
959
- data: Buffer.from([0, 123, 0x00, 0x01, 0xff]),
960
- destinationEndpoint: 1,
961
- endpoint: 1,
962
- groupID: undefined,
963
- header: {
964
- commandIdentifier: 0,
965
- frameControl: {
966
- direction: 0,
967
- disableDefaultResponse: false,
968
- frameType: 0,
969
- manufacturerSpecific: false,
970
- reservedBits: 0,
971
- },
972
- manufacturerCode: undefined,
973
- transactionSequenceNumber: 123,
974
- },
975
- linkquality: 155,
976
- wasBroadcast: false,
977
- });
978
-
979
- adapter.driver.emit(
980
- "frame",
981
- 57129,
982
- undefined,
983
- {
984
- frameControl: {
985
- frameType: 0 /* DATA */,
986
- deliveryMode: 0 /* UNICAST */,
987
- ackFormat: false,
988
- security: false,
989
- ackRequest: false,
990
- extendedHeader: false,
991
- },
992
- profileId: ZSpec.GP_PROFILE_ID,
993
- clusterId: Zcl.Clusters.greenPower.ID,
994
- sourceEndpoint: ZSpec.GP_ENDPOINT,
995
- destEndpoint: ZSpec.GP_ENDPOINT,
996
- },
997
- Buffer.from("1102040008d755550114000000e01f0785f256b8e010b32e6921aca5d18ab7b7d44d0f063d4d140300001002050229dfe2", "hex"),
998
- 245,
999
- );
1000
-
1001
- expect(emitSpy).toHaveBeenLastCalledWith("zclPayload", {
1002
- address: 57129,
1003
- clusterID: Zcl.Clusters.greenPower.ID,
1004
- data: Buffer.from("1102040008d755550114000000e01f0785f256b8e010b32e6921aca5d18ab7b7d44d0f063d4d140300001002050229dfe2", "hex"),
1005
- destinationEndpoint: ZSpec.GP_ENDPOINT,
1006
- endpoint: ZSpec.GP_ENDPOINT,
1007
- groupID: undefined,
1008
- header: {
1009
- commandIdentifier: 4,
1010
- frameControl: {
1011
- direction: 0,
1012
- disableDefaultResponse: true,
1013
- frameType: 1,
1014
- manufacturerSpecific: false,
1015
- reservedBits: 0,
1016
- },
1017
- manufacturerCode: undefined,
1018
- transactionSequenceNumber: 2,
1019
- },
1020
- linkquality: 245,
1021
- wasBroadcast: false,
1022
- });
1023
- });
1024
-
1025
- it("receives GP frame", async () => {
1026
- await adapter.start();
1027
-
1028
- const emitSpy = vi.spyOn(adapter, "emit");
1029
-
1030
- adapter.driver.emit(
1031
- "gpFrame",
1032
- 0xe0,
1033
- Buffer.from([
1034
- 0x2, 0x85, 0xf2, 0xc9, 0x25, 0x82, 0x1d, 0xf4, 0x6f, 0x45, 0x8c, 0xf0, 0xe6, 0x37, 0xaa, 0xc3, 0xba, 0xb6, 0xaa, 0x45, 0x83, 0x1a,
1035
- 0x11, 0x46, 0x23, 0x0, 0x0, 0x4, 0x16, 0x10, 0x11, 0x22, 0x23, 0x18, 0x19, 0x14, 0x15, 0x12, 0x13, 0x64, 0x65, 0x62, 0x63, 0x1e, 0x1f,
1036
- 0x1c, 0x1d, 0x1a, 0x1b, 0x16, 0x17,
1037
- ]),
1038
- {
1039
- frameControl: {
1040
- frameType: 0x1,
1041
- securityEnabled: false,
1042
- framePending: false,
1043
- ackRequest: false,
1044
- panIdCompression: false,
1045
- seqNumSuppress: false,
1046
- iePresent: false,
1047
- destAddrMode: 0x2,
1048
- frameVersion: 0,
1049
- sourceAddrMode: 0x0,
1050
- },
1051
- sequenceNumber: 70,
1052
- destinationPANId: 0xffff,
1053
- destination16: 0xffff,
1054
- sourcePANId: 0xffff,
1055
- fcs: 0xffff,
1056
- },
1057
- {
1058
- frameControl: {
1059
- frameType: 0x0,
1060
- protocolVersion: 3,
1061
- autoCommissioning: false,
1062
- nwkFrameControlExtension: false,
1063
- },
1064
- sourceId: 0x0155f47a,
1065
- micSize: 0,
1066
- payloadLength: 52,
1067
- },
1068
- 0,
1069
- );
1070
-
1071
- const data = Buffer.from([
1072
- 1, 70, 4, 0, 0, 122, 244, 85, 1, 0, 0, 0, 0, 0xe0, 51, 0x2, 0x85, 0xf2, 0xc9, 0x25, 0x82, 0x1d, 0xf4, 0x6f, 0x45, 0x8c, 0xf0, 0xe6, 0x37,
1073
- 0xaa, 0xc3, 0xba, 0xb6, 0xaa, 0x45, 0x83, 0x1a, 0x11, 0x46, 0x23, 0x0, 0x0, 0x4, 0x16, 0x10, 0x11, 0x22, 0x23, 0x18, 0x19, 0x14, 0x15,
1074
- 0x12, 0x13, 0x64, 0x65, 0x62, 0x63, 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x16, 0x17,
1075
- ]);
1076
- const header = Zcl.Header.fromBuffer(data)!;
1077
-
1078
- expect(emitSpy).toHaveBeenLastCalledWith("zclPayload", {
1079
- address: 0x0155f47a & 0xffff,
1080
- clusterID: Zcl.Clusters.greenPower.ID,
1081
- data,
1082
- destinationEndpoint: 242,
1083
- endpoint: 242,
1084
- groupID: ZSpec.GP_GROUP_ID,
1085
- header,
1086
- linkquality: 0,
1087
- wasBroadcast: true,
1088
- });
1089
-
1090
- const frame = Zcl.Frame.fromBuffer(Zcl.Clusters.greenPower.ID, header, data, {});
1091
-
1092
- expect(frame).toMatchObject({
1093
- header: {
1094
- frameControl: {
1095
- frameType: 1,
1096
- manufacturerSpecific: false,
1097
- direction: 0,
1098
- disableDefaultResponse: false,
1099
- reservedBits: 0,
1100
- },
1101
- manufacturerCode: undefined,
1102
- transactionSequenceNumber: 70,
1103
- commandIdentifier: 4,
1104
- },
1105
- payload: {
1106
- options: 0,
1107
- srcID: 22410362,
1108
- frameCounter: 0,
1109
- commandID: 0xe0,
1110
- payloadSize: 51,
1111
- commandFrame: {
1112
- deviceID: 2,
1113
- options: 133,
1114
- extendedOptions: 242,
1115
- securityKey: Buffer.from("c925821df46f458cf0e637aac3bab6aa", "hex"),
1116
- keyMic: 286950213,
1117
- outgoingCounter: 9030,
1118
- applicationInfo: 4,
1119
- manufacturerID: 0,
1120
- modelID: 0,
1121
- numGpdCommands: 22,
1122
- gpdCommandIdList: Buffer.from("10112223181914151213646562631e1f1c1d1a1b1617", "hex"),
1123
- numServerClusters: 0,
1124
- numClientClusters: 0,
1125
- gpdServerClusters: Buffer.alloc(0),
1126
- gpdClientClusters: Buffer.alloc(0),
1127
- },
1128
- },
1129
- cluster: {
1130
- ID: 0x21,
1131
- name: "greenPower",
1132
- },
1133
- command: {
1134
- ID: 0x04,
1135
- name: "commissioningNotification",
1136
- },
1137
- });
1138
-
1139
- adapter.driver.emit(
1140
- "gpFrame",
1141
- 0x10,
1142
- Buffer.from([]),
1143
- {
1144
- frameControl: {
1145
- frameType: 0x1,
1146
- securityEnabled: false,
1147
- framePending: false,
1148
- ackRequest: false,
1149
- panIdCompression: false,
1150
- seqNumSuppress: false,
1151
- iePresent: false,
1152
- destAddrMode: 0x2,
1153
- frameVersion: 0,
1154
- sourceAddrMode: 0x0,
1155
- },
1156
- sequenceNumber: 185,
1157
- destinationPANId: 0xffff,
1158
- destination16: 0xffff,
1159
- sourcePANId: 0xffff,
1160
- fcs: 0xffff,
1161
- },
1162
- {
1163
- frameControl: {
1164
- frameType: 0x0,
1165
- protocolVersion: 3,
1166
- autoCommissioning: false,
1167
- nwkFrameControlExtension: true,
1168
- },
1169
- frameControlExt: {
1170
- appId: 0,
1171
- direction: 0,
1172
- rxAfterTx: false,
1173
- securityKey: true,
1174
- securityLevel: 2,
1175
- },
1176
- sourceId: 24221335,
1177
- securityFrameCounter: 185,
1178
- micSize: 4,
1179
- payloadLength: 1,
1180
- mic: 3523079166,
1181
- },
1182
- 0,
1183
- );
1184
-
1185
- const data2 = Buffer.from([1, 185, 0, 0b10000000, 0, 151, 150, 113, 1, 185, 0, 0, 0, 0x10, 0]);
1186
- const header2 = Zcl.Header.fromBuffer(data2)!;
1187
-
1188
- expect(emitSpy).toHaveBeenLastCalledWith("zclPayload", {
1189
- address: 24221335 & 0xffff,
1190
- clusterID: Zcl.Clusters.greenPower.ID,
1191
- data: data2,
1192
- destinationEndpoint: 242,
1193
- endpoint: 242,
1194
- groupID: ZSpec.GP_GROUP_ID,
1195
- header: header2,
1196
- linkquality: 0,
1197
- wasBroadcast: true,
1198
- });
1199
-
1200
- const frame2 = Zcl.Frame.fromBuffer(Zcl.Clusters.greenPower.ID, header2, data2, {});
1201
-
1202
- expect(frame2).toMatchObject({
1203
- header: {
1204
- frameControl: {
1205
- frameType: 1,
1206
- manufacturerSpecific: false,
1207
- direction: 0,
1208
- disableDefaultResponse: false,
1209
- reservedBits: 0,
1210
- },
1211
- manufacturerCode: undefined,
1212
- transactionSequenceNumber: 185,
1213
- commandIdentifier: 0,
1214
- },
1215
- payload: {
1216
- options: 0b10000000,
1217
- srcID: 24221335,
1218
- frameCounter: 185,
1219
- commandID: 0x10,
1220
- payloadSize: 0,
1221
- commandFrame: {},
1222
- },
1223
- cluster: {
1224
- ID: 0x21,
1225
- name: "greenPower",
1226
- },
1227
- command: {
1228
- ID: 0x00,
1229
- name: "notification",
1230
- },
1231
- });
1232
- });
1233
-
1234
- it("receives device events", async () => {
1235
- await adapter.start();
1236
-
1237
- const emitSpy = vi.spyOn(adapter, "emit");
1238
-
1239
- adapter.driver.emit("deviceJoined", 0x123, 4321n, structuredClone(COMMON_FFD_MAC_CAP));
1240
- expect(emitSpy).toHaveBeenNthCalledWith(1, "deviceJoined", {networkAddress: 0x123, ieeeAddr: "0x00000000000010e1"});
1241
-
1242
- adapter.driver.emit("deviceJoined", 0x321, 1234n, structuredClone(COMMON_RFD_MAC_CAP));
1243
- expect(emitSpy).toHaveBeenCalledTimes(1);
1244
- await vi.advanceTimersByTimeAsync(5500);
1245
- expect(emitSpy).toHaveBeenNthCalledWith(2, "deviceJoined", {networkAddress: 0x321, ieeeAddr: "0x00000000000004d2"});
1246
-
1247
- adapter.driver.emit("deviceRejoined", 0x987, 4321n, structuredClone(COMMON_FFD_MAC_CAP));
1248
- expect(emitSpy).toHaveBeenLastCalledWith("deviceJoined", {networkAddress: 0x987, ieeeAddr: "0x00000000000010e1"});
1249
-
1250
- adapter.driver.emit("deviceLeft", 0x123, 4321n);
1251
- expect(emitSpy).toHaveBeenLastCalledWith("deviceLeave", {networkAddress: 0x123, ieeeAddr: "0x00000000000010e1"});
1252
-
1253
- // adapter.driver.emit('deviceAuthorized', 0x123, 4321n);
1254
- });
1255
-
1256
- it("resumes network", async () => {
1257
- // create default
1258
- writeFileSync(TEMP_PATH_SAVE, Buffer.from(DEFAULT_STATE_FILE_HEX, "hex"));
1259
-
1260
- await expect(adapter.start()).resolves.toStrictEqual("resumed");
1261
- expect(adapter.driver.netParams.networkKeyFrameCounter).toStrictEqual(1024); // jump means it loaded from saved state
1262
- });
1263
-
1264
- it("resets network on mismatch PAN ID", async () => {
1265
- // create default
1266
- const state = Buffer.from(DEFAULT_STATE_FILE_HEX, "hex");
1267
-
1268
- state.writeUInt16LE(0x1234, 8); // right after EUI64
1269
- writeFileSync(TEMP_PATH_SAVE, state);
1270
-
1271
- const currentNetParams = await adapter.driver.readNetworkState();
1272
-
1273
- expect(currentNetParams?.panId).toStrictEqual(0x1234);
1274
- await expect(adapter.start()).resolves.toStrictEqual("reset");
1275
- expect(adapter.driver.netParams.panId).toStrictEqual(DEFAULT_PAN_ID);
1276
- });
1277
-
1278
- it("resets network on mismatch extended PAN ID", async () => {
1279
- // create default
1280
- const state = Buffer.from(DEFAULT_STATE_FILE_HEX, "hex");
1281
-
1282
- state.write("0011001100110011", 10, "hex"); // right after PAN ID
1283
- writeFileSync(TEMP_PATH_SAVE, state);
1284
-
1285
- const currentNetParams = await adapter.driver.readNetworkState();
1286
-
1287
- expect(currentNetParams?.extendedPANId).toStrictEqual(Buffer.from("0011001100110011", "hex").readBigUInt64LE());
1288
-
1289
- await expect(adapter.start()).resolves.toStrictEqual("reset");
1290
- expect(adapter.driver.netParams.extendedPANId).toStrictEqual(Buffer.from(DEFAULT_EXT_PAN_ID).readBigUInt64LE());
1291
- });
1292
-
1293
- it("resets network on mismatch network key", async () => {
1294
- // create default
1295
- const state = Buffer.from(DEFAULT_STATE_FILE_HEX, "hex");
1296
-
1297
- state.write("00110011001100110011001100110011", 21, "hex"); // right after tx power
1298
- writeFileSync(TEMP_PATH_SAVE, state);
1299
-
1300
- const currentNetParams = await adapter.driver.readNetworkState();
1301
-
1302
- expect(currentNetParams?.networkKey).toStrictEqual(Buffer.from("00110011001100110011001100110011", "hex"));
1303
-
1304
- await expect(adapter.start()).resolves.toStrictEqual("reset");
1305
- expect(adapter.driver.netParams.networkKey).toStrictEqual(Buffer.from(DEFAULT_NETWORK_KEY));
1306
- });
1307
- });