@willieee802/zigbee-herdsman 0.48.3 → 0.49.1

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 (1045) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  2. package/.github/copilot-instructions.md +689 -0
  3. package/.github/dependabot.yml +22 -0
  4. package/.github/prompts/copilot-instructions-blueprint-generator.prompt.md +294 -0
  5. package/.github/prompts/create-agentsmd.prompt.md +249 -0
  6. package/.github/prompts/create-specification.prompt.md +127 -0
  7. package/.github/prompts/review-and-refactor.prompt.md +15 -0
  8. package/.github/prompts/update-specification.prompt.md +127 -0
  9. package/.github/workflows/ci.yml +70 -0
  10. package/.github/workflows/release-please.yml +18 -0
  11. package/.github/workflows/stale.yml +20 -0
  12. package/.github/workflows/typedoc.yaml +47 -0
  13. package/.release-please-manifest.json +2 -2
  14. package/.vscode/extensions.json +3 -0
  15. package/.vscode/settings.json +11 -0
  16. package/AGENTS.md +441 -0
  17. package/CHANGELOG.md +1283 -0
  18. package/README.md +1 -1
  19. package/biome.json +103 -0
  20. package/dist/adapter/adapter.d.ts.map +1 -1
  21. package/dist/adapter/adapterDiscovery.d.ts.map +1 -0
  22. package/dist/adapter/const.d.ts.map +1 -0
  23. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
  24. package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
  25. package/dist/adapter/ember/adapter/endpoints.d.ts.map +1 -1
  26. package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
  27. package/dist/adapter/ember/adapter/tokensManager.d.ts.map +1 -1
  28. package/dist/adapter/ember/ezsp/ezsp.d.ts.map +1 -1
  29. package/dist/adapter/ember/utils/initters.d.ts.map +1 -1
  30. package/dist/adapter/events.d.ts.map +1 -1
  31. package/dist/adapter/ezsp/adapter/backup.d.ts.map +1 -1
  32. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
  33. package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
  34. package/dist/adapter/ezsp/driver/index.d.ts.map +1 -1
  35. package/dist/adapter/ezsp/driver/multicast.d.ts.map +1 -1
  36. package/dist/adapter/index.d.ts.map +1 -1
  37. package/dist/adapter/z-stack/adapter/endpoints.d.ts.map +1 -1
  38. package/dist/adapter/z-stack/adapter/manager.d.ts.map +1 -1
  39. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
  40. package/dist/adapter/z-stack/models/startup-options.d.ts.map +1 -1
  41. package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -0
  42. package/dist/adapter/zboss/driver.d.ts.map +1 -0
  43. package/dist/adapter/zboss/frame.d.ts.map +1 -0
  44. package/dist/adapter/zboss/frame.js +200 -0
  45. package/dist/adapter/zboss/frame.js.map +1 -0
  46. package/dist/adapter/zboss/uart.d.ts.map +1 -0
  47. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
  48. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
  49. package/dist/adapter/zigate/driver/buffaloZiGate.js +70 -62
  50. package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
  51. package/dist/adapter/zigate/driver/ziGateObject.d.ts.map +1 -1
  52. package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
  53. package/dist/adapter/zoh/adapter/zohAdapter.d.ts.map +1 -0
  54. package/dist/controller/controller.d.ts.map +1 -1
  55. package/dist/controller/controller.js +524 -350
  56. package/dist/controller/controller.js.map +1 -1
  57. package/dist/controller/database.d.ts.map +1 -1
  58. package/dist/controller/events.d.ts.map +1 -1
  59. package/dist/controller/events.js +0 -110
  60. package/dist/controller/events.js.map +1 -1
  61. package/dist/controller/greenPower.d.ts.map +1 -1
  62. package/dist/controller/greenPower.js +330 -121
  63. package/dist/controller/greenPower.js.map +1 -1
  64. package/dist/controller/helpers/index.d.ts.map +1 -1
  65. package/dist/controller/helpers/ota.d.ts.map +1 -0
  66. package/dist/controller/helpers/ota.js +467 -0
  67. package/dist/controller/helpers/ota.js.map +1 -0
  68. package/dist/controller/helpers/request.d.ts.map +1 -1
  69. package/dist/controller/helpers/requestQueue.d.ts.map +1 -1
  70. package/dist/controller/helpers/zclFrameConverter.d.ts.map +1 -1
  71. package/dist/controller/helpers/zclFrameConverter.js +36 -22
  72. package/dist/controller/helpers/zclFrameConverter.js.map +1 -1
  73. package/dist/controller/index.d.ts.map +1 -1
  74. package/dist/controller/model/device.d.ts.map +1 -1
  75. package/dist/controller/model/device.js +1052 -402
  76. package/dist/controller/model/device.js.map +1 -1
  77. package/dist/controller/model/endpoint.d.ts.map +1 -1
  78. package/dist/controller/model/endpoint.js +447 -292
  79. package/dist/controller/model/endpoint.js.map +1 -1
  80. package/dist/controller/model/entity.d.ts.map +1 -1
  81. package/dist/controller/model/group.d.ts.map +1 -1
  82. package/dist/controller/model/group.js +202 -85
  83. package/dist/controller/model/group.js.map +1 -1
  84. package/dist/controller/model/index.d.ts.map +1 -1
  85. package/dist/controller/model/zigbeeEntity.d.ts.map +1 -0
  86. package/dist/controller/touchlink.d.ts.map +1 -1
  87. package/dist/controller/tstype.d.ts.map +1 -1
  88. package/dist/controller/tstype.js +0 -6
  89. package/dist/controller/tstype.js.map +1 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/utils/timeService.d.ts.map +1 -0
  92. package/dist/utils/timeService.js +127 -0
  93. package/dist/utils/timeService.js.map +1 -0
  94. package/dist/zspec/zcl/buffaloZcl.d.ts.map +1 -1
  95. package/dist/zspec/zcl/buffaloZcl.js +327 -287
  96. package/dist/zspec/zcl/buffaloZcl.js.map +1 -1
  97. package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
  98. package/dist/zspec/zcl/definition/cluster.js +6050 -4043
  99. package/dist/zspec/zcl/definition/cluster.js.map +1 -1
  100. package/dist/zspec/zcl/definition/clusters-types.d.ts +8135 -0
  101. package/dist/zspec/zcl/definition/clusters-types.d.ts.map +1 -0
  102. package/dist/zspec/zcl/definition/clusters-types.js +3 -0
  103. package/dist/zspec/zcl/definition/clusters-types.js.map +1 -0
  104. package/dist/zspec/zcl/definition/foundation.d.ts.map +1 -1
  105. package/dist/zspec/zcl/definition/foundation.js +170 -99
  106. package/dist/zspec/zcl/definition/foundation.js.map +1 -1
  107. package/dist/zspec/zcl/definition/tstype.d.ts +190 -31
  108. package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
  109. package/dist/zspec/zcl/definition/tstype.js +0 -1
  110. package/dist/zspec/zcl/definition/tstype.js.map +1 -1
  111. package/dist/zspec/zcl/index.d.ts.map +1 -1
  112. package/dist/zspec/zcl/index.js +23 -13
  113. package/dist/zspec/zcl/index.js.map +1 -1
  114. package/dist/zspec/zcl/utils.d.ts.map +1 -1
  115. package/dist/zspec/zcl/utils.js +288 -103
  116. package/dist/zspec/zcl/utils.js.map +1 -1
  117. package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
  118. package/dist/zspec/zcl/zclFrame.js +121 -97
  119. package/dist/zspec/zcl/zclFrame.js.map +1 -1
  120. package/dist/zspec/zcl/zclHeader.d.ts.map +1 -1
  121. package/dist/zspec/zcl/zclHeader.js +13 -13
  122. package/dist/zspec/zcl/zclHeader.js.map +1 -1
  123. package/examples/join-and-log.js +18 -18
  124. package/package.json +23 -3
  125. package/release-please-config.json +8 -8
  126. package/scripts/check-clusters-changes.ts +328 -0
  127. package/scripts/clusters-changes.log +584 -0
  128. package/scripts/clusters-typegen.ts +608 -0
  129. package/scripts/utils.ts +88 -0
  130. package/scripts/zap-update-clusters-report.json +303 -0
  131. package/scripts/zap-update-clusters.ts +1520 -0
  132. package/scripts/zap-update-types.ts +707 -0
  133. package/scripts/zap-xml-clusters-overrides-data.ts +52 -0
  134. package/scripts/zap-xml-clusters-overrides.ts +400 -0
  135. package/scripts/zap-xml-types.ts +146 -0
  136. package/src/adapter/adapter.ts +210 -0
  137. package/src/adapter/adapterDiscovery.ts +736 -0
  138. package/src/adapter/const.ts +12 -0
  139. package/src/adapter/deconz/adapter/deconzAdapter.ts +888 -0
  140. package/src/adapter/deconz/driver/constants.ts +246 -0
  141. package/src/adapter/deconz/driver/driver.ts +1528 -0
  142. package/src/adapter/deconz/driver/frame.ts +11 -0
  143. package/src/adapter/deconz/driver/frameParser.ts +766 -0
  144. package/src/adapter/deconz/driver/parser.ts +45 -0
  145. package/src/adapter/deconz/driver/writer.ts +22 -0
  146. package/src/adapter/deconz/types.d.ts +13 -0
  147. package/src/adapter/ember/adapter/emberAdapter.ts +2262 -0
  148. package/src/adapter/ember/adapter/endpoints.ts +86 -0
  149. package/src/adapter/ember/adapter/oneWaitress.ts +324 -0
  150. package/src/adapter/ember/adapter/tokensManager.ts +780 -0
  151. package/src/adapter/ember/consts.ts +178 -0
  152. package/src/adapter/ember/enums.ts +1746 -0
  153. package/src/adapter/ember/ezsp/buffalo.ts +1392 -0
  154. package/src/adapter/ember/ezsp/consts.ts +148 -0
  155. package/src/adapter/ember/ezsp/enums.ts +1114 -0
  156. package/src/adapter/ember/ezsp/ezsp.ts +9073 -0
  157. package/src/adapter/ember/ezspError.ts +10 -0
  158. package/src/adapter/ember/types.ts +866 -0
  159. package/src/adapter/ember/uart/ash.ts +1933 -0
  160. package/src/adapter/ember/uart/consts.ts +109 -0
  161. package/src/adapter/ember/uart/enums.ts +192 -0
  162. package/src/adapter/ember/uart/parser.ts +42 -0
  163. package/src/adapter/ember/uart/queues.ts +247 -0
  164. package/src/adapter/ember/uart/writer.ts +50 -0
  165. package/src/adapter/ember/utils/initters.ts +58 -0
  166. package/src/adapter/ember/utils/math.ts +71 -0
  167. package/src/adapter/events.ts +21 -0
  168. package/src/adapter/ezsp/adapter/backup.ts +100 -0
  169. package/src/adapter/ezsp/adapter/ezspAdapter.ts +632 -0
  170. package/src/adapter/ezsp/driver/commands.ts +2497 -0
  171. package/src/adapter/ezsp/driver/consts.ts +11 -0
  172. package/src/adapter/ezsp/driver/driver.ts +1002 -0
  173. package/src/adapter/ezsp/driver/ezsp.ts +802 -0
  174. package/src/adapter/ezsp/driver/frame.ts +101 -0
  175. package/src/adapter/ezsp/driver/index.ts +4 -0
  176. package/src/adapter/ezsp/driver/multicast.ts +78 -0
  177. package/src/adapter/ezsp/driver/parser.ts +81 -0
  178. package/src/adapter/ezsp/driver/types/basic.ts +201 -0
  179. package/src/adapter/ezsp/driver/types/index.ts +239 -0
  180. package/src/adapter/ezsp/driver/types/named.ts +2330 -0
  181. package/src/adapter/ezsp/driver/types/struct.ts +844 -0
  182. package/src/adapter/ezsp/driver/uart.ts +460 -0
  183. package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +44 -0
  184. package/src/adapter/ezsp/driver/utils/index.ts +32 -0
  185. package/src/adapter/ezsp/driver/writer.ts +64 -0
  186. package/src/adapter/index.ts +3 -0
  187. package/src/adapter/serialPort.ts +58 -0
  188. package/src/adapter/tstype.ts +57 -0
  189. package/src/adapter/utils.ts +41 -0
  190. package/src/adapter/z-stack/adapter/adapter-backup.ts +509 -0
  191. package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +457 -0
  192. package/src/adapter/z-stack/adapter/endpoints.ts +60 -0
  193. package/src/adapter/z-stack/adapter/manager.ts +543 -0
  194. package/src/adapter/z-stack/adapter/tstype.ts +6 -0
  195. package/src/adapter/z-stack/adapter/zStackAdapter.ts +1350 -0
  196. package/src/adapter/z-stack/constants/af.ts +27 -0
  197. package/src/adapter/z-stack/constants/common.ts +285 -0
  198. package/src/adapter/z-stack/constants/dbg.ts +23 -0
  199. package/src/adapter/z-stack/constants/index.ts +11 -0
  200. package/src/adapter/z-stack/constants/mac.ts +128 -0
  201. package/src/adapter/z-stack/constants/sapi.ts +25 -0
  202. package/src/adapter/z-stack/constants/sys.ts +72 -0
  203. package/src/adapter/z-stack/constants/util.ts +82 -0
  204. package/src/adapter/z-stack/constants/utils.ts +14 -0
  205. package/src/adapter/z-stack/constants/zdo.ts +103 -0
  206. package/src/adapter/z-stack/models/startup-options.ts +13 -0
  207. package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +44 -0
  208. package/src/adapter/z-stack/structs/entries/address-manager-table.ts +19 -0
  209. package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +12 -0
  210. package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +21 -0
  211. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +19 -0
  212. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +21 -0
  213. package/src/adapter/z-stack/structs/entries/channel-list.ts +8 -0
  214. package/src/adapter/z-stack/structs/entries/has-configured.ts +16 -0
  215. package/src/adapter/z-stack/structs/entries/index.ts +16 -0
  216. package/src/adapter/z-stack/structs/entries/nib.ts +66 -0
  217. package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +15 -0
  218. package/src/adapter/z-stack/structs/entries/nwk-key.ts +13 -0
  219. package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +8 -0
  220. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +20 -0
  221. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +19 -0
  222. package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +33 -0
  223. package/src/adapter/z-stack/structs/entries/security-manager-table.ts +22 -0
  224. package/src/adapter/z-stack/structs/index.ts +4 -0
  225. package/src/adapter/z-stack/structs/serializable-memory-object.ts +14 -0
  226. package/src/adapter/z-stack/structs/struct.ts +367 -0
  227. package/src/adapter/z-stack/structs/table.ts +198 -0
  228. package/src/adapter/z-stack/unpi/constants.ts +33 -0
  229. package/src/adapter/z-stack/unpi/frame.ts +62 -0
  230. package/src/adapter/z-stack/unpi/index.ts +4 -0
  231. package/src/adapter/z-stack/unpi/parser.ts +67 -0
  232. package/src/adapter/z-stack/unpi/writer.ts +37 -0
  233. package/src/adapter/z-stack/utils/channel-list.ts +40 -0
  234. package/src/adapter/z-stack/utils/index.ts +2 -0
  235. package/src/adapter/z-stack/utils/network-options.ts +26 -0
  236. package/src/adapter/z-stack/znp/buffaloZnp.ts +175 -0
  237. package/src/adapter/z-stack/znp/definition.ts +2713 -0
  238. package/src/adapter/z-stack/znp/index.ts +2 -0
  239. package/src/adapter/z-stack/znp/parameterType.ts +22 -0
  240. package/src/adapter/z-stack/znp/tstype.ts +44 -0
  241. package/src/adapter/z-stack/znp/utils.ts +10 -0
  242. package/src/adapter/z-stack/znp/znp.ts +345 -0
  243. package/src/adapter/z-stack/znp/zpiObject.ts +148 -0
  244. package/src/adapter/zboss/adapter/zbossAdapter.ts +535 -0
  245. package/src/adapter/zboss/commands.ts +1184 -0
  246. package/src/adapter/zboss/consts.ts +9 -0
  247. package/src/adapter/zboss/driver.ts +422 -0
  248. package/src/adapter/zboss/enums.ts +360 -0
  249. package/src/adapter/zboss/frame.ts +227 -0
  250. package/src/adapter/zboss/reader.ts +65 -0
  251. package/src/adapter/zboss/types.ts +0 -0
  252. package/src/adapter/zboss/uart.ts +428 -0
  253. package/src/adapter/zboss/utils.ts +58 -0
  254. package/src/adapter/zboss/writer.ts +49 -0
  255. package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +25 -0
  256. package/src/adapter/zigate/adapter/zigateAdapter.ts +633 -0
  257. package/src/adapter/zigate/driver/LICENSE +17 -0
  258. package/src/adapter/zigate/driver/buffaloZiGate.ts +210 -0
  259. package/src/adapter/zigate/driver/commandType.ts +418 -0
  260. package/src/adapter/zigate/driver/constants.ts +150 -0
  261. package/src/adapter/zigate/driver/frame.ts +197 -0
  262. package/src/adapter/zigate/driver/messageType.ts +287 -0
  263. package/src/adapter/zigate/driver/parameterType.ts +32 -0
  264. package/src/adapter/zigate/driver/ziGateObject.ts +146 -0
  265. package/src/adapter/zigate/driver/zigate.ts +422 -0
  266. package/src/adapter/zoh/adapter/utils.ts +27 -0
  267. package/src/adapter/zoh/adapter/zohAdapter.ts +931 -0
  268. package/src/buffalo/buffalo.ts +336 -0
  269. package/src/buffalo/index.ts +1 -0
  270. package/src/controller/controller.ts +1159 -0
  271. package/src/controller/database.ts +148 -0
  272. package/src/controller/events.ts +52 -0
  273. package/src/controller/greenPower.ts +613 -0
  274. package/src/controller/helpers/index.ts +1 -0
  275. package/src/controller/helpers/installCodes.ts +107 -0
  276. package/src/controller/helpers/ota.ts +578 -0
  277. package/src/controller/helpers/request.ts +96 -0
  278. package/src/controller/helpers/requestQueue.ts +126 -0
  279. package/src/controller/helpers/zclFrameConverter.ts +64 -0
  280. package/src/controller/helpers/zclTransactionSequenceNumber.ts +15 -0
  281. package/src/controller/index.ts +6 -0
  282. package/src/controller/model/device.ts +1791 -0
  283. package/src/controller/model/endpoint.ts +1235 -0
  284. package/src/controller/model/entity.ts +43 -0
  285. package/src/controller/model/group.ts +446 -0
  286. package/src/controller/model/index.ts +5 -0
  287. package/src/controller/model/konnextConfig.ts +6 -0
  288. package/src/controller/model/zigbeeEntity.ts +30 -0
  289. package/src/controller/touchlink.ts +195 -0
  290. package/src/controller/tstype.ts +374 -0
  291. package/src/index.ts +14 -0
  292. package/src/models/backup-storage-legacy.ts +48 -0
  293. package/src/models/backup-storage-unified.ts +47 -0
  294. package/src/models/backup.ts +37 -0
  295. package/src/models/index.ts +5 -0
  296. package/src/models/network-options.ts +11 -0
  297. package/src/utils/aes.ts +218 -0
  298. package/src/utils/async-mutex.ts +31 -0
  299. package/src/utils/backup.ts +152 -0
  300. package/src/utils/index.ts +5 -0
  301. package/src/utils/logger.ts +20 -0
  302. package/src/utils/patchBigIntSerialization.ts +8 -0
  303. package/src/utils/queue.ts +79 -0
  304. package/src/utils/timeService.ts +139 -0
  305. package/src/utils/utils.ts +19 -0
  306. package/src/utils/wait.ts +5 -0
  307. package/src/utils/waitress.ts +96 -0
  308. package/src/zspec/consts.ts +89 -0
  309. package/src/zspec/enums.ts +22 -0
  310. package/src/zspec/index.ts +3 -0
  311. package/src/zspec/tstypes.ts +18 -0
  312. package/src/zspec/utils.ts +247 -0
  313. package/src/zspec/zcl/buffaloZcl.ts +1073 -0
  314. package/src/zspec/zcl/definition/cluster.ts +7554 -0
  315. package/src/zspec/zcl/definition/clusters-types.ts +8228 -0
  316. package/src/zspec/zcl/definition/consts.ts +24 -0
  317. package/src/zspec/zcl/definition/datatypes.ts +2454 -0
  318. package/src/zspec/zcl/definition/enums.ts +224 -0
  319. package/src/zspec/zcl/definition/foundation.ts +342 -0
  320. package/src/zspec/zcl/definition/manufacturerCode.ts +730 -0
  321. package/src/zspec/zcl/definition/status.ts +69 -0
  322. package/src/zspec/zcl/definition/tstype.ts +432 -0
  323. package/src/zspec/zcl/index.ts +11 -0
  324. package/src/zspec/zcl/utils.ts +504 -0
  325. package/src/zspec/zcl/zclFrame.ts +383 -0
  326. package/src/zspec/zcl/zclHeader.ts +102 -0
  327. package/src/zspec/zcl/zclStatusError.ts +10 -0
  328. package/src/zspec/zdo/buffaloZdo.ts +2336 -0
  329. package/src/zspec/zdo/definition/clusters.ts +722 -0
  330. package/src/zspec/zdo/definition/consts.ts +16 -0
  331. package/src/zspec/zdo/definition/enums.ts +99 -0
  332. package/src/zspec/zdo/definition/status.ts +105 -0
  333. package/src/zspec/zdo/definition/tstypes.ts +1062 -0
  334. package/src/zspec/zdo/index.ts +7 -0
  335. package/src/zspec/zdo/utils.ts +76 -0
  336. package/src/zspec/zdo/zdoStatusError.ts +10 -0
  337. package/test/adapter/adapter.test.ts +1276 -0
  338. package/test/adapter/ember/ash.test.ts +337 -0
  339. package/test/adapter/ember/consts.ts +131 -0
  340. package/test/adapter/ember/emberAdapter.test.ts +3447 -0
  341. package/test/adapter/ember/ezsp.test.ts +389 -0
  342. package/test/adapter/ember/ezspBuffalo.test.ts +93 -0
  343. package/test/adapter/ember/ezspError.test.ts +12 -0
  344. package/test/adapter/ember/math.test.ts +190 -0
  345. package/test/adapter/ezsp/frame.test.ts +30 -0
  346. package/test/adapter/ezsp/uart.test.ts +181 -0
  347. package/test/adapter/z-stack/adapter.test.ts +4260 -0
  348. package/test/adapter/z-stack/constants.test.ts +33 -0
  349. package/test/adapter/z-stack/structs.test.ts +115 -0
  350. package/test/adapter/z-stack/unpi.test.ts +213 -0
  351. package/test/adapter/z-stack/znp.test.ts +1288 -0
  352. package/test/adapter/zboss/fixZdoResponse.test.ts +179 -0
  353. package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +81 -0
  354. package/test/adapter/zigate/zdo.test.ts +187 -0
  355. package/test/adapter/zoh/utils.test.ts +36 -0
  356. package/test/adapter/zoh/zohAdapter.test.ts +1451 -0
  357. package/test/benchOptions.ts +14 -0
  358. package/test/buffalo.test.ts +431 -0
  359. package/test/controller.bench.ts +215 -0
  360. package/test/controller.test.ts +10038 -0
  361. package/test/data/integrity-code-1166-012B-24031511-upgradeMe-RB 249 T.zigbee +0 -0
  362. package/test/data/manuf-tags-tradfri-cv-cct-unified_release_prod_v587757105_33e34452-9267-4665-bc5a-844c8f61f063.ota +0 -0
  363. package/test/data/padded-tretakt_smart_plug_soc-0x1100-2.4.25-prod.ota.ota.signed +0 -0
  364. package/test/data/telink-aes-A60_RGBW_T-0x00B6-0x03483712-MF_DIS.OTA +0 -0
  365. package/test/data/zbminir2_v1.0.8.ota +0 -0
  366. package/test/device-ota.test.ts +3332 -0
  367. package/test/greenpower.test.ts +1409 -0
  368. package/test/mockAdapters.ts +95 -0
  369. package/test/mockDevices.ts +623 -0
  370. package/test/requests.bench.ts +321 -0
  371. package/test/testUtils.ts +20 -0
  372. package/test/timeService.test.ts +214 -0
  373. package/test/tsconfig.json +9 -0
  374. package/test/utils/math.ts +19 -0
  375. package/test/utils.test.ts +352 -0
  376. package/test/vitest.config.mts +28 -0
  377. package/test/vitest.ts +9 -0
  378. package/test/zcl.test.ts +2887 -0
  379. package/test/zspec/utils.test.ts +68 -0
  380. package/test/zspec/zcl/buffalo.test.ts +1316 -0
  381. package/test/zspec/zcl/frame.test.ts +1056 -0
  382. package/test/zspec/zcl/utils.test.ts +650 -0
  383. package/test/zspec/zdo/buffalo.test.ts +1850 -0
  384. package/test/zspec/zdo/utils.test.ts +241 -0
  385. package/tsconfig.json +8 -10
  386. package/.babelrc.js +0 -6
  387. package/.eslintignore +0 -3
  388. package/dist/adapter/adapter.d.ts +0 -64
  389. package/dist/adapter/adapter.js +0 -157
  390. package/dist/adapter/adapter.js.map +0 -1
  391. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +0 -71
  392. package/dist/adapter/deconz/adapter/deconzAdapter.js +0 -1072
  393. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +0 -1
  394. package/dist/adapter/deconz/adapter/index.d.ts +0 -3
  395. package/dist/adapter/deconz/adapter/index.d.ts.map +0 -1
  396. package/dist/adapter/deconz/adapter/index.js +0 -11
  397. package/dist/adapter/deconz/adapter/index.js.map +0 -1
  398. package/dist/adapter/deconz/driver/constants.d.ts +0 -105
  399. package/dist/adapter/deconz/driver/constants.d.ts.map +0 -1
  400. package/dist/adapter/deconz/driver/constants.js +0 -56
  401. package/dist/adapter/deconz/driver/constants.js.map +0 -1
  402. package/dist/adapter/deconz/driver/driver.d.ts +0 -82
  403. package/dist/adapter/deconz/driver/driver.d.ts.map +0 -1
  404. package/dist/adapter/deconz/driver/driver.js +0 -751
  405. package/dist/adapter/deconz/driver/driver.js.map +0 -1
  406. package/dist/adapter/deconz/driver/frame.d.ts +0 -7
  407. package/dist/adapter/deconz/driver/frame.d.ts.map +0 -1
  408. package/dist/adapter/deconz/driver/frame.js +0 -14
  409. package/dist/adapter/deconz/driver/frame.js.map +0 -1
  410. package/dist/adapter/deconz/driver/frameParser.d.ts +0 -3
  411. package/dist/adapter/deconz/driver/frameParser.d.ts.map +0 -1
  412. package/dist/adapter/deconz/driver/frameParser.js +0 -444
  413. package/dist/adapter/deconz/driver/frameParser.js.map +0 -1
  414. package/dist/adapter/deconz/driver/parser.d.ts +0 -13
  415. package/dist/adapter/deconz/driver/parser.d.ts.map +0 -1
  416. package/dist/adapter/deconz/driver/parser.js +0 -64
  417. package/dist/adapter/deconz/driver/parser.js.map +0 -1
  418. package/dist/adapter/deconz/driver/writer.d.ts +0 -9
  419. package/dist/adapter/deconz/driver/writer.d.ts.map +0 -1
  420. package/dist/adapter/deconz/driver/writer.js +0 -45
  421. package/dist/adapter/deconz/driver/writer.js.map +0 -1
  422. package/dist/adapter/ember/adapter/emberAdapter.d.ts +0 -806
  423. package/dist/adapter/ember/adapter/emberAdapter.js +0 -2942
  424. package/dist/adapter/ember/adapter/emberAdapter.js.map +0 -1
  425. package/dist/adapter/ember/adapter/endpoints.d.ts +0 -27
  426. package/dist/adapter/ember/adapter/endpoints.js +0 -68
  427. package/dist/adapter/ember/adapter/endpoints.js.map +0 -1
  428. package/dist/adapter/ember/adapter/index.d.ts +0 -3
  429. package/dist/adapter/ember/adapter/index.d.ts.map +0 -1
  430. package/dist/adapter/ember/adapter/index.js +0 -6
  431. package/dist/adapter/ember/adapter/index.js.map +0 -1
  432. package/dist/adapter/ember/adapter/oneWaitress.d.ts +0 -108
  433. package/dist/adapter/ember/adapter/oneWaitress.js +0 -241
  434. package/dist/adapter/ember/adapter/oneWaitress.js.map +0 -1
  435. package/dist/adapter/ember/adapter/requestQueue.d.ts +0 -57
  436. package/dist/adapter/ember/adapter/requestQueue.d.ts.map +0 -1
  437. package/dist/adapter/ember/adapter/requestQueue.js +0 -139
  438. package/dist/adapter/ember/adapter/requestQueue.js.map +0 -1
  439. package/dist/adapter/ember/adapter/tokensManager.d.ts +0 -69
  440. package/dist/adapter/ember/adapter/tokensManager.js +0 -688
  441. package/dist/adapter/ember/adapter/tokensManager.js.map +0 -1
  442. package/dist/adapter/ember/consts.d.ts +0 -191
  443. package/dist/adapter/ember/consts.d.ts.map +0 -1
  444. package/dist/adapter/ember/consts.js +0 -246
  445. package/dist/adapter/ember/consts.js.map +0 -1
  446. package/dist/adapter/ember/enums.d.ts +0 -2172
  447. package/dist/adapter/ember/enums.d.ts.map +0 -1
  448. package/dist/adapter/ember/enums.js +0 -2375
  449. package/dist/adapter/ember/enums.js.map +0 -1
  450. package/dist/adapter/ember/ezsp/buffalo.d.ts +0 -156
  451. package/dist/adapter/ember/ezsp/buffalo.d.ts.map +0 -1
  452. package/dist/adapter/ember/ezsp/buffalo.js +0 -1033
  453. package/dist/adapter/ember/ezsp/buffalo.js.map +0 -1
  454. package/dist/adapter/ember/ezsp/consts.d.ts +0 -116
  455. package/dist/adapter/ember/ezsp/consts.d.ts.map +0 -1
  456. package/dist/adapter/ember/ezsp/consts.js +0 -128
  457. package/dist/adapter/ember/ezsp/consts.js.map +0 -1
  458. package/dist/adapter/ember/ezsp/enums.d.ts +0 -879
  459. package/dist/adapter/ember/ezsp/enums.d.ts.map +0 -1
  460. package/dist/adapter/ember/ezsp/enums.js +0 -948
  461. package/dist/adapter/ember/ezsp/enums.js.map +0 -1
  462. package/dist/adapter/ember/ezsp/ezsp.d.ts +0 -2662
  463. package/dist/adapter/ember/ezsp/ezsp.js +0 -6454
  464. package/dist/adapter/ember/ezsp/ezsp.js.map +0 -1
  465. package/dist/adapter/ember/types.d.ts +0 -733
  466. package/dist/adapter/ember/types.d.ts.map +0 -1
  467. package/dist/adapter/ember/types.js +0 -3
  468. package/dist/adapter/ember/types.js.map +0 -1
  469. package/dist/adapter/ember/uart/ash.d.ts +0 -464
  470. package/dist/adapter/ember/uart/ash.d.ts.map +0 -1
  471. package/dist/adapter/ember/uart/ash.js +0 -1633
  472. package/dist/adapter/ember/uart/ash.js.map +0 -1
  473. package/dist/adapter/ember/uart/consts.d.ts +0 -91
  474. package/dist/adapter/ember/uart/consts.d.ts.map +0 -1
  475. package/dist/adapter/ember/uart/consts.js +0 -100
  476. package/dist/adapter/ember/uart/consts.js.map +0 -1
  477. package/dist/adapter/ember/uart/enums.d.ts +0 -191
  478. package/dist/adapter/ember/uart/enums.d.ts.map +0 -1
  479. package/dist/adapter/ember/uart/enums.js +0 -197
  480. package/dist/adapter/ember/uart/enums.js.map +0 -1
  481. package/dist/adapter/ember/uart/parser.d.ts +0 -10
  482. package/dist/adapter/ember/uart/parser.d.ts.map +0 -1
  483. package/dist/adapter/ember/uart/parser.js +0 -37
  484. package/dist/adapter/ember/uart/parser.js.map +0 -1
  485. package/dist/adapter/ember/uart/queues.d.ts +0 -85
  486. package/dist/adapter/ember/uart/queues.d.ts.map +0 -1
  487. package/dist/adapter/ember/uart/queues.js +0 -214
  488. package/dist/adapter/ember/uart/queues.js.map +0 -1
  489. package/dist/adapter/ember/uart/writer.d.ts +0 -15
  490. package/dist/adapter/ember/uart/writer.d.ts.map +0 -1
  491. package/dist/adapter/ember/uart/writer.js +0 -46
  492. package/dist/adapter/ember/uart/writer.js.map +0 -1
  493. package/dist/adapter/ember/utils/initters.d.ts +0 -20
  494. package/dist/adapter/ember/utils/initters.js +0 -58
  495. package/dist/adapter/ember/utils/initters.js.map +0 -1
  496. package/dist/adapter/ember/utils/math.d.ts +0 -51
  497. package/dist/adapter/ember/utils/math.d.ts.map +0 -1
  498. package/dist/adapter/ember/utils/math.js +0 -102
  499. package/dist/adapter/ember/utils/math.js.map +0 -1
  500. package/dist/adapter/ember/zdo.d.ts +0 -925
  501. package/dist/adapter/ember/zdo.d.ts.map +0 -1
  502. package/dist/adapter/ember/zdo.js +0 -723
  503. package/dist/adapter/ember/zdo.js.map +0 -1
  504. package/dist/adapter/events.d.ts +0 -42
  505. package/dist/adapter/events.js +0 -13
  506. package/dist/adapter/events.js.map +0 -1
  507. package/dist/adapter/ezsp/adapter/backup.d.ts +0 -13
  508. package/dist/adapter/ezsp/adapter/backup.js +0 -101
  509. package/dist/adapter/ezsp/adapter/backup.js.map +0 -1
  510. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +0 -65
  511. package/dist/adapter/ezsp/adapter/ezspAdapter.js +0 -634
  512. package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +0 -1
  513. package/dist/adapter/ezsp/adapter/index.d.ts +0 -3
  514. package/dist/adapter/ezsp/adapter/index.d.ts.map +0 -1
  515. package/dist/adapter/ezsp/adapter/index.js +0 -11
  516. package/dist/adapter/ezsp/adapter/index.js.map +0 -1
  517. package/dist/adapter/ezsp/driver/commands.d.ts +0 -37
  518. package/dist/adapter/ezsp/driver/commands.d.ts.map +0 -1
  519. package/dist/adapter/ezsp/driver/commands.js +0 -2387
  520. package/dist/adapter/ezsp/driver/commands.js.map +0 -1
  521. package/dist/adapter/ezsp/driver/consts.d.ts +0 -11
  522. package/dist/adapter/ezsp/driver/consts.d.ts.map +0 -1
  523. package/dist/adapter/ezsp/driver/consts.js +0 -14
  524. package/dist/adapter/ezsp/driver/consts.js.map +0 -1
  525. package/dist/adapter/ezsp/driver/driver.d.ts +0 -109
  526. package/dist/adapter/ezsp/driver/driver.js +0 -796
  527. package/dist/adapter/ezsp/driver/driver.js.map +0 -1
  528. package/dist/adapter/ezsp/driver/ezsp.d.ts +0 -106
  529. package/dist/adapter/ezsp/driver/ezsp.d.ts.map +0 -1
  530. package/dist/adapter/ezsp/driver/ezsp.js +0 -664
  531. package/dist/adapter/ezsp/driver/ezsp.js.map +0 -1
  532. package/dist/adapter/ezsp/driver/frame.d.ts +0 -40
  533. package/dist/adapter/ezsp/driver/frame.d.ts.map +0 -1
  534. package/dist/adapter/ezsp/driver/frame.js +0 -101
  535. package/dist/adapter/ezsp/driver/frame.js.map +0 -1
  536. package/dist/adapter/ezsp/driver/index.d.ts +0 -4
  537. package/dist/adapter/ezsp/driver/index.js +0 -9
  538. package/dist/adapter/ezsp/driver/index.js.map +0 -1
  539. package/dist/adapter/ezsp/driver/multicast.d.ts +0 -13
  540. package/dist/adapter/ezsp/driver/multicast.js +0 -74
  541. package/dist/adapter/ezsp/driver/multicast.js.map +0 -1
  542. package/dist/adapter/ezsp/driver/parser.d.ts +0 -12
  543. package/dist/adapter/ezsp/driver/parser.d.ts.map +0 -1
  544. package/dist/adapter/ezsp/driver/parser.js +0 -105
  545. package/dist/adapter/ezsp/driver/parser.js.map +0 -1
  546. package/dist/adapter/ezsp/driver/types/basic.d.ts +0 -63
  547. package/dist/adapter/ezsp/driver/types/basic.d.ts.map +0 -1
  548. package/dist/adapter/ezsp/driver/types/basic.js +0 -209
  549. package/dist/adapter/ezsp/driver/types/basic.js.map +0 -1
  550. package/dist/adapter/ezsp/driver/types/index.d.ts +0 -10
  551. package/dist/adapter/ezsp/driver/types/index.d.ts.map +0 -1
  552. package/dist/adapter/ezsp/driver/types/index.js +0 -139
  553. package/dist/adapter/ezsp/driver/types/index.js.map +0 -1
  554. package/dist/adapter/ezsp/driver/types/named.d.ts +0 -1288
  555. package/dist/adapter/ezsp/driver/types/named.d.ts.map +0 -1
  556. package/dist/adapter/ezsp/driver/types/named.js +0 -2330
  557. package/dist/adapter/ezsp/driver/types/named.js.map +0 -1
  558. package/dist/adapter/ezsp/driver/types/struct.d.ts +0 -271
  559. package/dist/adapter/ezsp/driver/types/struct.d.ts.map +0 -1
  560. package/dist/adapter/ezsp/driver/types/struct.js +0 -804
  561. package/dist/adapter/ezsp/driver/types/struct.js.map +0 -1
  562. package/dist/adapter/ezsp/driver/uart.d.ts +0 -49
  563. package/dist/adapter/ezsp/driver/uart.d.ts.map +0 -1
  564. package/dist/adapter/ezsp/driver/uart.js +0 -383
  565. package/dist/adapter/ezsp/driver/uart.js.map +0 -1
  566. package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts +0 -3
  567. package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts.map +0 -1
  568. package/dist/adapter/ezsp/driver/utils/crc16ccitt.js +0 -56
  569. package/dist/adapter/ezsp/driver/utils/crc16ccitt.js.map +0 -1
  570. package/dist/adapter/ezsp/driver/utils/index.d.ts +0 -20
  571. package/dist/adapter/ezsp/driver/utils/index.d.ts.map +0 -1
  572. package/dist/adapter/ezsp/driver/utils/index.js +0 -73
  573. package/dist/adapter/ezsp/driver/utils/index.js.map +0 -1
  574. package/dist/adapter/ezsp/driver/writer.d.ts +0 -14
  575. package/dist/adapter/ezsp/driver/writer.d.ts.map +0 -1
  576. package/dist/adapter/ezsp/driver/writer.js +0 -83
  577. package/dist/adapter/ezsp/driver/writer.js.map +0 -1
  578. package/dist/adapter/index.d.ts +0 -5
  579. package/dist/adapter/index.js +0 -36
  580. package/dist/adapter/index.js.map +0 -1
  581. package/dist/adapter/serialPort.d.ts +0 -14
  582. package/dist/adapter/serialPort.d.ts.map +0 -1
  583. package/dist/adapter/serialPort.js +0 -47
  584. package/dist/adapter/serialPort.js.map +0 -1
  585. package/dist/adapter/serialPortUtils.d.ts +0 -13
  586. package/dist/adapter/serialPortUtils.d.ts.map +0 -1
  587. package/dist/adapter/serialPortUtils.js +0 -19
  588. package/dist/adapter/serialPortUtils.js.map +0 -1
  589. package/dist/adapter/socketPortUtils.d.ts +0 -11
  590. package/dist/adapter/socketPortUtils.d.ts.map +0 -1
  591. package/dist/adapter/socketPortUtils.js +0 -17
  592. package/dist/adapter/socketPortUtils.js.map +0 -1
  593. package/dist/adapter/tstype.d.ts +0 -86
  594. package/dist/adapter/tstype.d.ts.map +0 -1
  595. package/dist/adapter/tstype.js +0 -3
  596. package/dist/adapter/tstype.js.map +0 -1
  597. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts +0 -62
  598. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts.map +0 -1
  599. package/dist/adapter/z-stack/adapter/adapter-backup.js +0 -459
  600. package/dist/adapter/z-stack/adapter/adapter-backup.js.map +0 -1
  601. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts +0 -151
  602. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts.map +0 -1
  603. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +0 -259
  604. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +0 -1
  605. package/dist/adapter/z-stack/adapter/endpoints.d.ts +0 -12
  606. package/dist/adapter/z-stack/adapter/endpoints.js +0 -74
  607. package/dist/adapter/z-stack/adapter/endpoints.js.map +0 -1
  608. package/dist/adapter/z-stack/adapter/index.d.ts +0 -3
  609. package/dist/adapter/z-stack/adapter/index.d.ts.map +0 -1
  610. package/dist/adapter/z-stack/adapter/index.js +0 -9
  611. package/dist/adapter/z-stack/adapter/index.js.map +0 -1
  612. package/dist/adapter/z-stack/adapter/manager.d.ts +0 -84
  613. package/dist/adapter/z-stack/adapter/manager.js +0 -474
  614. package/dist/adapter/z-stack/adapter/manager.js.map +0 -1
  615. package/dist/adapter/z-stack/adapter/tstype.d.ts +0 -7
  616. package/dist/adapter/z-stack/adapter/tstype.d.ts.map +0 -1
  617. package/dist/adapter/z-stack/adapter/tstype.js +0 -10
  618. package/dist/adapter/z-stack/adapter/tstype.js.map +0 -1
  619. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +0 -86
  620. package/dist/adapter/z-stack/adapter/zStackAdapter.js +0 -912
  621. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +0 -1
  622. package/dist/adapter/z-stack/constants/af.d.ts +0 -24
  623. package/dist/adapter/z-stack/constants/af.d.ts.map +0 -1
  624. package/dist/adapter/z-stack/constants/af.js +0 -28
  625. package/dist/adapter/z-stack/constants/af.js.map +0 -1
  626. package/dist/adapter/z-stack/constants/common.d.ts +0 -279
  627. package/dist/adapter/z-stack/constants/common.d.ts.map +0 -1
  628. package/dist/adapter/z-stack/constants/common.js +0 -293
  629. package/dist/adapter/z-stack/constants/common.js.map +0 -1
  630. package/dist/adapter/z-stack/constants/dbg.d.ts +0 -23
  631. package/dist/adapter/z-stack/constants/dbg.d.ts.map +0 -1
  632. package/dist/adapter/z-stack/constants/dbg.js +0 -25
  633. package/dist/adapter/z-stack/constants/dbg.js.map +0 -1
  634. package/dist/adapter/z-stack/constants/index.d.ts +0 -11
  635. package/dist/adapter/z-stack/constants/index.d.ts.map +0 -1
  636. package/dist/adapter/z-stack/constants/index.js +0 -48
  637. package/dist/adapter/z-stack/constants/index.js.map +0 -1
  638. package/dist/adapter/z-stack/constants/mac.d.ts +0 -128
  639. package/dist/adapter/z-stack/constants/mac.d.ts.map +0 -1
  640. package/dist/adapter/z-stack/constants/mac.js +0 -130
  641. package/dist/adapter/z-stack/constants/mac.js.map +0 -1
  642. package/dist/adapter/z-stack/constants/sapi.d.ts +0 -25
  643. package/dist/adapter/z-stack/constants/sapi.d.ts.map +0 -1
  644. package/dist/adapter/z-stack/constants/sapi.js +0 -27
  645. package/dist/adapter/z-stack/constants/sapi.js.map +0 -1
  646. package/dist/adapter/z-stack/constants/sys.d.ts +0 -72
  647. package/dist/adapter/z-stack/constants/sys.d.ts.map +0 -1
  648. package/dist/adapter/z-stack/constants/sys.js +0 -74
  649. package/dist/adapter/z-stack/constants/sys.js.map +0 -1
  650. package/dist/adapter/z-stack/constants/util.d.ts +0 -82
  651. package/dist/adapter/z-stack/constants/util.d.ts.map +0 -1
  652. package/dist/adapter/z-stack/constants/util.js +0 -84
  653. package/dist/adapter/z-stack/constants/util.js.map +0 -1
  654. package/dist/adapter/z-stack/constants/utils.d.ts +0 -5
  655. package/dist/adapter/z-stack/constants/utils.d.ts.map +0 -1
  656. package/dist/adapter/z-stack/constants/utils.js +0 -15
  657. package/dist/adapter/z-stack/constants/utils.js.map +0 -1
  658. package/dist/adapter/z-stack/constants/zdo.d.ts +0 -103
  659. package/dist/adapter/z-stack/constants/zdo.d.ts.map +0 -1
  660. package/dist/adapter/z-stack/constants/zdo.js +0 -105
  661. package/dist/adapter/z-stack/constants/zdo.js.map +0 -1
  662. package/dist/adapter/z-stack/models/index.d.ts +0 -2
  663. package/dist/adapter/z-stack/models/index.d.ts.map +0 -1
  664. package/dist/adapter/z-stack/models/index.js +0 -18
  665. package/dist/adapter/z-stack/models/index.js.map +0 -1
  666. package/dist/adapter/z-stack/models/startup-options.d.ts +0 -13
  667. package/dist/adapter/z-stack/models/startup-options.js +0 -3
  668. package/dist/adapter/z-stack/models/startup-options.js.map +0 -1
  669. package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts +0 -24
  670. package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts.map +0 -1
  671. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js +0 -46
  672. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js.map +0 -1
  673. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts +0 -11
  674. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts.map +0 -1
  675. package/dist/adapter/z-stack/structs/entries/address-manager-table.js +0 -23
  676. package/dist/adapter/z-stack/structs/entries/address-manager-table.js.map +0 -1
  677. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts +0 -11
  678. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts.map +0 -1
  679. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js +0 -22
  680. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js.map +0 -1
  681. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts +0 -11
  682. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts.map +0 -1
  683. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js +0 -24
  684. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js.map +0 -1
  685. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts +0 -11
  686. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts.map +0 -1
  687. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js +0 -25
  688. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js.map +0 -1
  689. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts +0 -11
  690. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts.map +0 -1
  691. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js +0 -24
  692. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js.map +0 -1
  693. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts +0 -9
  694. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts.map +0 -1
  695. package/dist/adapter/z-stack/structs/entries/channel-list.js +0 -16
  696. package/dist/adapter/z-stack/structs/entries/channel-list.js.map +0 -1
  697. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts +0 -9
  698. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts.map +0 -1
  699. package/dist/adapter/z-stack/structs/entries/has-configured.js +0 -17
  700. package/dist/adapter/z-stack/structs/entries/has-configured.js.map +0 -1
  701. package/dist/adapter/z-stack/structs/entries/index.d.ts +0 -17
  702. package/dist/adapter/z-stack/structs/entries/index.d.ts.map +0 -1
  703. package/dist/adapter/z-stack/structs/entries/index.js +0 -33
  704. package/dist/adapter/z-stack/structs/entries/index.js.map +0 -1
  705. package/dist/adapter/z-stack/structs/entries/nib.d.ts +0 -11
  706. package/dist/adapter/z-stack/structs/entries/nib.d.ts.map +0 -1
  707. package/dist/adapter/z-stack/structs/entries/nib.js +0 -69
  708. package/dist/adapter/z-stack/structs/entries/nib.js.map +0 -1
  709. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts +0 -11
  710. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts.map +0 -1
  711. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js +0 -19
  712. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js.map +0 -1
  713. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts +0 -9
  714. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts.map +0 -1
  715. package/dist/adapter/z-stack/structs/entries/nwk-key.js +0 -16
  716. package/dist/adapter/z-stack/structs/entries/nwk-key.js.map +0 -1
  717. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts +0 -9
  718. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts.map +0 -1
  719. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js +0 -16
  720. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js.map +0 -1
  721. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts +0 -14
  722. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts.map +0 -1
  723. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js +0 -24
  724. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js.map +0 -1
  725. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts +0 -11
  726. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts.map +0 -1
  727. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js +0 -23
  728. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js.map +0 -1
  729. package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts +0 -21
  730. package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts.map +0 -1
  731. package/dist/adapter/z-stack/structs/entries/security-manager-entry.js +0 -37
  732. package/dist/adapter/z-stack/structs/entries/security-manager-entry.js.map +0 -1
  733. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts +0 -11
  734. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts.map +0 -1
  735. package/dist/adapter/z-stack/structs/entries/security-manager-table.js +0 -25
  736. package/dist/adapter/z-stack/structs/entries/security-manager-table.js.map +0 -1
  737. package/dist/adapter/z-stack/structs/index.d.ts +0 -5
  738. package/dist/adapter/z-stack/structs/index.d.ts.map +0 -1
  739. package/dist/adapter/z-stack/structs/index.js +0 -21
  740. package/dist/adapter/z-stack/structs/index.js.map +0 -1
  741. package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts +0 -14
  742. package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts.map +0 -1
  743. package/dist/adapter/z-stack/structs/serializable-memory-object.js +0 -3
  744. package/dist/adapter/z-stack/structs/serializable-memory-object.js.map +0 -1
  745. package/dist/adapter/z-stack/structs/struct.d.ts +0 -100
  746. package/dist/adapter/z-stack/structs/struct.d.ts.map +0 -1
  747. package/dist/adapter/z-stack/structs/struct.js +0 -297
  748. package/dist/adapter/z-stack/structs/struct.js.map +0 -1
  749. package/dist/adapter/z-stack/structs/table.d.ts +0 -95
  750. package/dist/adapter/z-stack/structs/table.d.ts.map +0 -1
  751. package/dist/adapter/z-stack/structs/table.js +0 -164
  752. package/dist/adapter/z-stack/structs/table.js.map +0 -1
  753. package/dist/adapter/z-stack/unpi/constants.d.ts +0 -29
  754. package/dist/adapter/z-stack/unpi/constants.d.ts.map +0 -1
  755. package/dist/adapter/z-stack/unpi/constants.js +0 -40
  756. package/dist/adapter/z-stack/unpi/constants.js.map +0 -1
  757. package/dist/adapter/z-stack/unpi/frame.d.ts +0 -17
  758. package/dist/adapter/z-stack/unpi/frame.d.ts.map +0 -1
  759. package/dist/adapter/z-stack/unpi/frame.js +0 -55
  760. package/dist/adapter/z-stack/unpi/frame.js.map +0 -1
  761. package/dist/adapter/z-stack/unpi/index.d.ts +0 -6
  762. package/dist/adapter/z-stack/unpi/index.d.ts.map +0 -1
  763. package/dist/adapter/z-stack/unpi/index.js +0 -38
  764. package/dist/adapter/z-stack/unpi/index.js.map +0 -1
  765. package/dist/adapter/z-stack/unpi/parser.d.ts +0 -13
  766. package/dist/adapter/z-stack/unpi/parser.d.ts.map +0 -1
  767. package/dist/adapter/z-stack/unpi/parser.js +0 -86
  768. package/dist/adapter/z-stack/unpi/parser.js.map +0 -1
  769. package/dist/adapter/z-stack/unpi/writer.d.ts +0 -12
  770. package/dist/adapter/z-stack/unpi/writer.d.ts.map +0 -1
  771. package/dist/adapter/z-stack/unpi/writer.js +0 -55
  772. package/dist/adapter/z-stack/unpi/writer.js.map +0 -1
  773. package/dist/adapter/z-stack/utils/channel-list.d.ts +0 -21
  774. package/dist/adapter/z-stack/utils/channel-list.d.ts.map +0 -1
  775. package/dist/adapter/z-stack/utils/channel-list.js +0 -41
  776. package/dist/adapter/z-stack/utils/channel-list.js.map +0 -1
  777. package/dist/adapter/z-stack/utils/index.d.ts +0 -3
  778. package/dist/adapter/z-stack/utils/index.d.ts.map +0 -1
  779. package/dist/adapter/z-stack/utils/index.js +0 -19
  780. package/dist/adapter/z-stack/utils/index.js.map +0 -1
  781. package/dist/adapter/z-stack/utils/network-options.d.ts +0 -9
  782. package/dist/adapter/z-stack/utils/network-options.d.ts.map +0 -1
  783. package/dist/adapter/z-stack/utils/network-options.js +0 -23
  784. package/dist/adapter/z-stack/utils/network-options.js.map +0 -1
  785. package/dist/adapter/z-stack/znp/buffaloZnp.d.ts +0 -14
  786. package/dist/adapter/z-stack/znp/buffaloZnp.d.ts.map +0 -1
  787. package/dist/adapter/z-stack/znp/buffaloZnp.js +0 -243
  788. package/dist/adapter/z-stack/znp/buffaloZnp.js.map +0 -1
  789. package/dist/adapter/z-stack/znp/definition.d.ts +0 -6
  790. package/dist/adapter/z-stack/znp/definition.d.ts.map +0 -1
  791. package/dist/adapter/z-stack/znp/definition.js +0 -3052
  792. package/dist/adapter/z-stack/znp/definition.js.map +0 -1
  793. package/dist/adapter/z-stack/znp/index.d.ts +0 -4
  794. package/dist/adapter/z-stack/znp/index.d.ts.map +0 -1
  795. package/dist/adapter/z-stack/znp/index.js +0 -11
  796. package/dist/adapter/z-stack/znp/index.js.map +0 -1
  797. package/dist/adapter/z-stack/znp/parameterType.d.ts +0 -23
  798. package/dist/adapter/z-stack/znp/parameterType.d.ts.map +0 -1
  799. package/dist/adapter/z-stack/znp/parameterType.js +0 -26
  800. package/dist/adapter/z-stack/znp/parameterType.js.map +0 -1
  801. package/dist/adapter/z-stack/znp/tstype.d.ts +0 -23
  802. package/dist/adapter/z-stack/znp/tstype.d.ts.map +0 -1
  803. package/dist/adapter/z-stack/znp/tstype.js +0 -3
  804. package/dist/adapter/z-stack/znp/tstype.js.map +0 -1
  805. package/dist/adapter/z-stack/znp/znp.d.ts +0 -47
  806. package/dist/adapter/z-stack/znp/znp.d.ts.map +0 -1
  807. package/dist/adapter/z-stack/znp/znp.js +0 -322
  808. package/dist/adapter/z-stack/znp/znp.js.map +0 -1
  809. package/dist/adapter/z-stack/znp/zpiObject.d.ts +0 -20
  810. package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +0 -1
  811. package/dist/adapter/z-stack/znp/zpiObject.js +0 -103
  812. package/dist/adapter/z-stack/znp/zpiObject.js.map +0 -1
  813. package/dist/adapter/zigate/adapter/index.d.ts +0 -3
  814. package/dist/adapter/zigate/adapter/index.d.ts.map +0 -1
  815. package/dist/adapter/zigate/adapter/index.js +0 -11
  816. package/dist/adapter/zigate/adapter/index.js.map +0 -1
  817. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +0 -72
  818. package/dist/adapter/zigate/adapter/zigateAdapter.js +0 -681
  819. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +0 -1
  820. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts +0 -18
  821. package/dist/adapter/zigate/driver/commandType.d.ts +0 -43
  822. package/dist/adapter/zigate/driver/commandType.d.ts.map +0 -1
  823. package/dist/adapter/zigate/driver/commandType.js +0 -390
  824. package/dist/adapter/zigate/driver/commandType.js.map +0 -1
  825. package/dist/adapter/zigate/driver/constants.d.ts +0 -277
  826. package/dist/adapter/zigate/driver/constants.d.ts.map +0 -1
  827. package/dist/adapter/zigate/driver/constants.js +0 -372
  828. package/dist/adapter/zigate/driver/constants.js.map +0 -1
  829. package/dist/adapter/zigate/driver/frame.d.ts +0 -27
  830. package/dist/adapter/zigate/driver/frame.d.ts.map +0 -1
  831. package/dist/adapter/zigate/driver/frame.js +0 -173
  832. package/dist/adapter/zigate/driver/frame.js.map +0 -1
  833. package/dist/adapter/zigate/driver/messageType.d.ts +0 -13
  834. package/dist/adapter/zigate/driver/messageType.d.ts.map +0 -1
  835. package/dist/adapter/zigate/driver/messageType.js +0 -284
  836. package/dist/adapter/zigate/driver/messageType.js.map +0 -1
  837. package/dist/adapter/zigate/driver/parameterType.d.ts +0 -28
  838. package/dist/adapter/zigate/driver/parameterType.d.ts.map +0 -1
  839. package/dist/adapter/zigate/driver/parameterType.js +0 -33
  840. package/dist/adapter/zigate/driver/parameterType.js.map +0 -1
  841. package/dist/adapter/zigate/driver/ziGateObject.d.ts +0 -24
  842. package/dist/adapter/zigate/driver/ziGateObject.js +0 -111
  843. package/dist/adapter/zigate/driver/ziGateObject.js.map +0 -1
  844. package/dist/adapter/zigate/driver/zigate.d.ts +0 -50
  845. package/dist/adapter/zigate/driver/zigate.js +0 -289
  846. package/dist/adapter/zigate/driver/zigate.js.map +0 -1
  847. package/dist/buffalo/buffalo.d.ts +0 -55
  848. package/dist/buffalo/buffalo.d.ts.map +0 -1
  849. package/dist/buffalo/buffalo.js +0 -230
  850. package/dist/buffalo/buffalo.js.map +0 -1
  851. package/dist/buffalo/index.d.ts +0 -3
  852. package/dist/buffalo/index.d.ts.map +0 -1
  853. package/dist/buffalo/index.js +0 -9
  854. package/dist/buffalo/index.js.map +0 -1
  855. package/dist/controller/controller.d.ts +0 -119
  856. package/dist/controller/database.d.ts +0 -20
  857. package/dist/controller/database.js +0 -94
  858. package/dist/controller/database.js.map +0 -1
  859. package/dist/controller/events.d.ts +0 -59
  860. package/dist/controller/greenPower.d.ts +0 -14
  861. package/dist/controller/helpers/index.d.ts +0 -3
  862. package/dist/controller/helpers/index.js +0 -29
  863. package/dist/controller/helpers/index.js.map +0 -1
  864. package/dist/controller/helpers/request.d.ts +0 -22
  865. package/dist/controller/helpers/request.js +0 -78
  866. package/dist/controller/helpers/request.js.map +0 -1
  867. package/dist/controller/helpers/requestQueue.d.ts +0 -13
  868. package/dist/controller/helpers/requestQueue.js +0 -106
  869. package/dist/controller/helpers/requestQueue.js.map +0 -1
  870. package/dist/controller/helpers/zclFrameConverter.d.ts +0 -9
  871. package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts +0 -6
  872. package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts.map +0 -1
  873. package/dist/controller/helpers/zclTransactionSequenceNumber.js +0 -14
  874. package/dist/controller/helpers/zclTransactionSequenceNumber.js.map +0 -1
  875. package/dist/controller/index.d.ts +0 -6
  876. package/dist/controller/index.js +0 -9
  877. package/dist/controller/index.js.map +0 -1
  878. package/dist/controller/model/device.d.ts +0 -140
  879. package/dist/controller/model/endpoint.d.ts +0 -134
  880. package/dist/controller/model/entity.d.ts +0 -15
  881. package/dist/controller/model/entity.js +0 -27
  882. package/dist/controller/model/entity.js.map +0 -1
  883. package/dist/controller/model/group.d.ts +0 -39
  884. package/dist/controller/model/index.d.ts +0 -6
  885. package/dist/controller/model/index.js +0 -15
  886. package/dist/controller/model/index.js.map +0 -1
  887. package/dist/controller/model/konnextConfig.d.ts +0 -7
  888. package/dist/controller/model/konnextConfig.d.ts.map +0 -1
  889. package/dist/controller/model/konnextConfig.js +0 -3
  890. package/dist/controller/model/konnextConfig.js.map +0 -1
  891. package/dist/controller/touchlink.d.ts +0 -20
  892. package/dist/controller/touchlink.js +0 -157
  893. package/dist/controller/touchlink.js.map +0 -1
  894. package/dist/controller/tstype.d.ts +0 -21
  895. package/dist/index.d.ts +0 -6
  896. package/dist/index.js +0 -37
  897. package/dist/index.js.map +0 -1
  898. package/dist/models/backup-storage-legacy.d.ts +0 -27
  899. package/dist/models/backup-storage-legacy.d.ts.map +0 -1
  900. package/dist/models/backup-storage-legacy.js +0 -3
  901. package/dist/models/backup-storage-legacy.js.map +0 -1
  902. package/dist/models/backup-storage-unified.d.ts +0 -50
  903. package/dist/models/backup-storage-unified.d.ts.map +0 -1
  904. package/dist/models/backup-storage-unified.js +0 -3
  905. package/dist/models/backup-storage-unified.js.map +0 -1
  906. package/dist/models/backup.d.ts +0 -38
  907. package/dist/models/backup.d.ts.map +0 -1
  908. package/dist/models/backup.js +0 -3
  909. package/dist/models/backup.js.map +0 -1
  910. package/dist/models/index.d.ts +0 -5
  911. package/dist/models/index.d.ts.map +0 -1
  912. package/dist/models/index.js +0 -21
  913. package/dist/models/index.js.map +0 -1
  914. package/dist/models/network-options.d.ts +0 -13
  915. package/dist/models/network-options.d.ts.map +0 -1
  916. package/dist/models/network-options.js +0 -3
  917. package/dist/models/network-options.js.map +0 -1
  918. package/dist/utils/aes.d.ts +0 -40
  919. package/dist/utils/aes.d.ts.map +0 -1
  920. package/dist/utils/aes.js +0 -198
  921. package/dist/utils/aes.js.map +0 -1
  922. package/dist/utils/assertString.d.ts +0 -3
  923. package/dist/utils/assertString.d.ts.map +0 -1
  924. package/dist/utils/assertString.js +0 -9
  925. package/dist/utils/assertString.js.map +0 -1
  926. package/dist/utils/backup.d.ts +0 -21
  927. package/dist/utils/backup.d.ts.map +0 -1
  928. package/dist/utils/backup.js +0 -190
  929. package/dist/utils/backup.js.map +0 -1
  930. package/dist/utils/equalsPartial.d.ts +0 -3
  931. package/dist/utils/equalsPartial.d.ts.map +0 -1
  932. package/dist/utils/equalsPartial.js +0 -12
  933. package/dist/utils/equalsPartial.js.map +0 -1
  934. package/dist/utils/index.d.ts +0 -10
  935. package/dist/utils/index.d.ts.map +0 -1
  936. package/dist/utils/index.js +0 -46
  937. package/dist/utils/index.js.map +0 -1
  938. package/dist/utils/isNumberArray.d.ts +0 -3
  939. package/dist/utils/isNumberArray.d.ts.map +0 -1
  940. package/dist/utils/isNumberArray.js +0 -7
  941. package/dist/utils/isNumberArray.js.map +0 -1
  942. package/dist/utils/logger.d.ts +0 -9
  943. package/dist/utils/logger.d.ts.map +0 -1
  944. package/dist/utils/logger.js +0 -14
  945. package/dist/utils/logger.js.map +0 -1
  946. package/dist/utils/queue.d.ts +0 -12
  947. package/dist/utils/queue.d.ts.map +0 -1
  948. package/dist/utils/queue.js +0 -62
  949. package/dist/utils/queue.js.map +0 -1
  950. package/dist/utils/realpathSync.d.ts +0 -3
  951. package/dist/utils/realpathSync.d.ts.map +0 -1
  952. package/dist/utils/realpathSync.js +0 -13
  953. package/dist/utils/realpathSync.js.map +0 -1
  954. package/dist/utils/wait.d.ts +0 -3
  955. package/dist/utils/wait.d.ts.map +0 -1
  956. package/dist/utils/wait.js +0 -9
  957. package/dist/utils/wait.js.map +0 -1
  958. package/dist/utils/waitress.d.ts +0 -22
  959. package/dist/utils/waitress.d.ts.map +0 -1
  960. package/dist/utils/waitress.js +0 -69
  961. package/dist/utils/waitress.js.map +0 -1
  962. package/dist/zspec/consts.d.ts +0 -60
  963. package/dist/zspec/consts.d.ts.map +0 -1
  964. package/dist/zspec/consts.js +0 -64
  965. package/dist/zspec/consts.js.map +0 -1
  966. package/dist/zspec/enums.d.ts +0 -19
  967. package/dist/zspec/enums.d.ts.map +0 -1
  968. package/dist/zspec/enums.js +0 -28
  969. package/dist/zspec/enums.js.map +0 -1
  970. package/dist/zspec/index.d.ts +0 -4
  971. package/dist/zspec/index.d.ts.map +0 -1
  972. package/dist/zspec/index.js +0 -43
  973. package/dist/zspec/index.js.map +0 -1
  974. package/dist/zspec/tstypes.d.ts +0 -19
  975. package/dist/zspec/tstypes.d.ts.map +0 -1
  976. package/dist/zspec/tstypes.js +0 -3
  977. package/dist/zspec/tstypes.js.map +0 -1
  978. package/dist/zspec/utils.d.ts +0 -14
  979. package/dist/zspec/utils.d.ts.map +0 -1
  980. package/dist/zspec/utils.js +0 -29
  981. package/dist/zspec/utils.js.map +0 -1
  982. package/dist/zspec/zcl/buffaloZcl.d.ts +0 -55
  983. package/dist/zspec/zcl/definition/cluster.d.ts +0 -3
  984. package/dist/zspec/zcl/definition/consts.d.ts +0 -9
  985. package/dist/zspec/zcl/definition/consts.d.ts.map +0 -1
  986. package/dist/zspec/zcl/definition/consts.js +0 -27
  987. package/dist/zspec/zcl/definition/consts.js.map +0 -1
  988. package/dist/zspec/zcl/definition/enums.d.ts +0 -177
  989. package/dist/zspec/zcl/definition/enums.d.ts.map +0 -1
  990. package/dist/zspec/zcl/definition/enums.js +0 -187
  991. package/dist/zspec/zcl/definition/enums.js.map +0 -1
  992. package/dist/zspec/zcl/definition/foundation.d.ts +0 -11
  993. package/dist/zspec/zcl/definition/manufacturerCode.d.ts +0 -727
  994. package/dist/zspec/zcl/definition/manufacturerCode.d.ts.map +0 -1
  995. package/dist/zspec/zcl/definition/manufacturerCode.js +0 -733
  996. package/dist/zspec/zcl/definition/manufacturerCode.js.map +0 -1
  997. package/dist/zspec/zcl/definition/status.d.ts +0 -69
  998. package/dist/zspec/zcl/definition/status.d.ts.map +0 -1
  999. package/dist/zspec/zcl/definition/status.js +0 -74
  1000. package/dist/zspec/zcl/definition/status.js.map +0 -1
  1001. package/dist/zspec/zcl/index.d.ts +0 -11
  1002. package/dist/zspec/zcl/utils.d.ts +0 -7
  1003. package/dist/zspec/zcl/zclFrame.d.ts +0 -36
  1004. package/dist/zspec/zcl/zclHeader.d.ts +0 -17
  1005. package/dist/zspec/zcl/zclStatusError.d.ts +0 -6
  1006. package/dist/zspec/zcl/zclStatusError.d.ts.map +0 -1
  1007. package/dist/zspec/zcl/zclStatusError.js +0 -13
  1008. package/dist/zspec/zcl/zclStatusError.js.map +0 -1
  1009. package/dist/zspec/zdo/buffaloZdo.d.ts +0 -438
  1010. package/dist/zspec/zdo/buffaloZdo.d.ts.map +0 -1
  1011. package/dist/zspec/zdo/buffaloZdo.js +0 -1892
  1012. package/dist/zspec/zdo/buffaloZdo.js.map +0 -1
  1013. package/dist/zspec/zdo/definition/clusters.d.ts +0 -624
  1014. package/dist/zspec/zdo/definition/clusters.d.ts.map +0 -1
  1015. package/dist/zspec/zdo/definition/clusters.js +0 -687
  1016. package/dist/zspec/zdo/definition/clusters.js.map +0 -1
  1017. package/dist/zspec/zdo/definition/consts.d.ts +0 -13
  1018. package/dist/zspec/zdo/definition/consts.d.ts.map +0 -1
  1019. package/dist/zspec/zdo/definition/consts.js +0 -16
  1020. package/dist/zspec/zdo/definition/consts.js.map +0 -1
  1021. package/dist/zspec/zdo/definition/enums.d.ts +0 -75
  1022. package/dist/zspec/zdo/definition/enums.d.ts.map +0 -1
  1023. package/dist/zspec/zdo/definition/enums.js +0 -97
  1024. package/dist/zspec/zdo/definition/enums.js.map +0 -1
  1025. package/dist/zspec/zdo/definition/status.d.ts +0 -99
  1026. package/dist/zspec/zdo/definition/status.d.ts.map +0 -1
  1027. package/dist/zspec/zdo/definition/status.js +0 -109
  1028. package/dist/zspec/zdo/definition/status.js.map +0 -1
  1029. package/dist/zspec/zdo/definition/tstypes.d.ts +0 -787
  1030. package/dist/zspec/zdo/definition/tstypes.d.ts.map +0 -1
  1031. package/dist/zspec/zdo/definition/tstypes.js +0 -3
  1032. package/dist/zspec/zdo/definition/tstypes.js.map +0 -1
  1033. package/dist/zspec/zdo/index.d.ts +0 -7
  1034. package/dist/zspec/zdo/index.d.ts.map +0 -1
  1035. package/dist/zspec/zdo/index.js +0 -39
  1036. package/dist/zspec/zdo/index.js.map +0 -1
  1037. package/dist/zspec/zdo/utils.d.ts +0 -25
  1038. package/dist/zspec/zdo/utils.d.ts.map +0 -1
  1039. package/dist/zspec/zdo/utils.js +0 -75
  1040. package/dist/zspec/zdo/utils.js.map +0 -1
  1041. package/dist/zspec/zdo/zdoStatusError.d.ts +0 -6
  1042. package/dist/zspec/zdo/zdoStatusError.d.ts.map +0 -1
  1043. package/dist/zspec/zdo/zdoStatusError.js +0 -13
  1044. package/dist/zspec/zdo/zdoStatusError.js.map +0 -1
  1045. package/typedoc-tsconfig.json +0 -44
@@ -0,0 +1,4260 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import equals from "fast-deep-equal/es6";
4
+ import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
5
+ import type {ZclPayload} from "../../../src/adapter/events";
6
+ import {ZnpVersion} from "../../../src/adapter/z-stack/adapter/tstype";
7
+ import {ZStackAdapter} from "../../../src/adapter/z-stack/adapter/zStackAdapter";
8
+ import * as Constants from "../../../src/adapter/z-stack/constants";
9
+ import {AddressMode, DevStates, NvItemsIds, NvSystemIds, type ZnpCommandStatus} from "../../../src/adapter/z-stack/constants/common";
10
+ import * as Structs from "../../../src/adapter/z-stack/structs";
11
+ import {Subsystem, Type} from "../../../src/adapter/z-stack/unpi/constants";
12
+ import {Znp, type ZpiObject} from "../../../src/adapter/z-stack/znp";
13
+ import Definition from "../../../src/adapter/z-stack/znp/definition";
14
+ import type {ZpiObjectPayload} from "../../../src/adapter/z-stack/znp/tstype";
15
+ import type {UnifiedBackupStorage} from "../../../src/models";
16
+ import {setLogger} from "../../../src/utils/logger";
17
+ import * as ZSpec from "../../../src/zspec";
18
+ import {BroadcastAddress} from "../../../src/zspec/enums";
19
+ import * as Zcl from "../../../src/zspec/zcl";
20
+ import * as Zdo from "../../../src/zspec/zdo";
21
+ import type {
22
+ ActiveEndpointsResponse,
23
+ EndDeviceAnnounce,
24
+ LQITableResponse,
25
+ NetworkAddressResponse,
26
+ NodeDescriptorResponse,
27
+ RoutingTableResponse,
28
+ SimpleDescriptorResponse,
29
+ } from "../../../src/zspec/zdo/definition/tstypes";
30
+
31
+ const DUMMY_NODE_DESC_RSP_CAPABILITIES = {
32
+ allocateAddress: 0,
33
+ alternatePANCoordinator: 0,
34
+ deviceType: 2,
35
+ powerSource: 0,
36
+ reserved1: 0,
37
+ reserved2: 0,
38
+ rxOnWhenIdle: 0,
39
+ securityCapability: 0,
40
+ };
41
+
42
+ const STR_500_BYTES =
43
+ "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 " +
44
+ "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 " +
45
+ "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 " +
46
+ "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 " +
47
+ "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ";
48
+
49
+ const mockLogger = {
50
+ debug: vi.fn(),
51
+ info: vi.fn(),
52
+ warning: vi.fn(),
53
+ error: vi.fn(),
54
+ };
55
+ const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
56
+ const mockSetTimeout = () => {
57
+ return vi.spyOn(globalThis, "setTimeout").mockImplementation(
58
+ // @ts-expect-error mock
59
+ (cb) => cb(),
60
+ );
61
+ };
62
+
63
+ vi.mock("../../../src/utils/wait", () => ({
64
+ wait: vi.fn(() => {
65
+ return new Promise<void>((resolve) => resolve());
66
+ }),
67
+ }));
68
+
69
+ const waitForResult = (payloadOrPromise: Promise<unknown> | ZpiObjectPayload, id?: number) => {
70
+ id = id || 1;
71
+ if (payloadOrPromise instanceof Promise) {
72
+ return {
73
+ start: () => {
74
+ return {promise: payloadOrPromise, ID: id};
75
+ },
76
+ ID: id,
77
+ };
78
+ }
79
+
80
+ return {
81
+ start: () => {
82
+ return {promise: new Promise((r) => r(payloadOrPromise)), ID: id};
83
+ },
84
+ ID: id,
85
+ };
86
+ };
87
+
88
+ const networkOptions = {
89
+ panID: 123,
90
+ extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
91
+ channelList: [21],
92
+ networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
93
+ networkKeyDistribute: false,
94
+ };
95
+
96
+ const networkOptionsDefaultExtendedPanId = {
97
+ panID: 123,
98
+ extendedPanID: [0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd],
99
+ channelList: [21],
100
+ networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
101
+ networkKeyDistribute: false,
102
+ };
103
+
104
+ const networkOptionsMismatched = {
105
+ panID: 124,
106
+ extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
107
+ channelList: [21],
108
+ networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
109
+ networkKeyDistribute: false,
110
+ };
111
+
112
+ const networkOptionsInvalidPanId = {
113
+ panID: 65535,
114
+ extendedPanID: [0x00, 0x12, 0x4b, 0x00, 0x09, 0xd6, 0x9f, 0x77],
115
+ channelList: [21],
116
+ networkKey: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
117
+ networkKeyDistribute: false,
118
+ };
119
+
120
+ const serialPortOptions = {
121
+ baudRate: 800,
122
+ rtscts: false,
123
+ path: "dummy",
124
+ };
125
+
126
+ const backupMatchingConfig = {
127
+ metadata: {
128
+ format: "zigpy/open-coordinator-backup",
129
+ version: 1,
130
+ source: "zigbee-herdsman@0.13.65",
131
+ internal: {
132
+ date: "2021-03-03T19:15:40.524Z",
133
+ znpVersion: 2,
134
+ },
135
+ },
136
+ stack_specific: {
137
+ zstack: {
138
+ tclk_seed: "928a2c479e72a9a53e3b5133fc55021f",
139
+ },
140
+ },
141
+ coordinator_ieee: "00124b0009d80ba7",
142
+ pan_id: "007b",
143
+ extended_pan_id: "00124b0009d69f77",
144
+ nwk_update_id: 0,
145
+ security_level: 5,
146
+ channel: 21,
147
+ channel_mask: [21],
148
+ network_key: {
149
+ key: "01030507090b0d0f00020406080a0c0d",
150
+ sequence_number: 0,
151
+ frame_counter: 16754,
152
+ },
153
+ devices: [
154
+ {
155
+ nwk_address: "ddf6",
156
+ ieee_address: "00124b002226ef87",
157
+ },
158
+ {
159
+ nwk_address: "c2dc",
160
+ ieee_address: "04cf8cdf3c79455f",
161
+ link_key: {
162
+ key: "0e768569dd935d8e7302e74e7629f13f",
163
+ rx_counter: 0,
164
+ tx_counter: 275,
165
+ },
166
+ },
167
+ {
168
+ nwk_address: "740a",
169
+ ieee_address: "680ae2fffeae5647",
170
+ link_key: {
171
+ key: "7c079d02aae015facd7ae9608d4baf56",
172
+ rx_counter: 0,
173
+ tx_counter: 275,
174
+ },
175
+ },
176
+ {
177
+ nwk_address: "19fa",
178
+ ieee_address: "00158d00024fa79b",
179
+ link_key: {
180
+ key: "cea550908aa1529ee90eea3c3bdc26fc",
181
+ rx_counter: 0,
182
+ tx_counter: 44,
183
+ },
184
+ },
185
+ {
186
+ nwk_address: "6182",
187
+ ieee_address: "00158d00024f4518",
188
+ link_key: {
189
+ key: "267e1e31fcd8171f8acf63459effbca5",
190
+ rx_counter: 0,
191
+ tx_counter: 44,
192
+ },
193
+ },
194
+ {
195
+ nwk_address: "4285",
196
+ ieee_address: "00158d00024f810d",
197
+ is_child: false,
198
+ link_key: {
199
+ key: "55ba1e31fcd8171f9f0b63459effbca5",
200
+ rx_counter: 0,
201
+ tx_counter: 44,
202
+ },
203
+ },
204
+ {
205
+ // "nwk_address": "4286", commented because `nwk_address` is optional in the backup
206
+ ieee_address: "00158d00024f810e",
207
+ is_child: true,
208
+ link_key: {
209
+ key: "55ba1e31fcd8171fee0b63459effeea5",
210
+ rx_counter: 24,
211
+ tx_counter: 91,
212
+ },
213
+ },
214
+ ],
215
+ };
216
+
217
+ const backupMatchingConfig12 = {
218
+ metadata: {
219
+ format: "zigpy/open-coordinator-backup",
220
+ version: 1,
221
+ source: "zigbee-herdsman@0.13.65",
222
+ internal: {
223
+ date: "2021-03-03T19:15:40.524Z",
224
+ znpVersion: 0,
225
+ },
226
+ },
227
+ stack_specific: {
228
+ zstack: {},
229
+ },
230
+ coordinator_ieee: "00124b0009d80ba7",
231
+ pan_id: "007b",
232
+ extended_pan_id: "00124b0009d69f77",
233
+ nwk_update_id: 0,
234
+ security_level: 5,
235
+ channel: 21,
236
+ channel_mask: [21],
237
+ network_key: {
238
+ key: "01030507090b0d0f00020406080a0c0d",
239
+ sequence_number: 0,
240
+ frame_counter: 0,
241
+ },
242
+ devices: [
243
+ {
244
+ nwk_address: "ddf6",
245
+ ieee_address: "00124b002226ef87",
246
+ },
247
+ ],
248
+ };
249
+
250
+ const backupNotMatchingConfig = {
251
+ metadata: {
252
+ format: "zigpy/open-coordinator-backup",
253
+ version: 1,
254
+ source: "zigbee-herdsman@0.13.65",
255
+ internal: {
256
+ date: "2021-03-03T19:15:40.524Z",
257
+ znpVersion: 2,
258
+ },
259
+ },
260
+ stack_specific: {
261
+ zstack: {
262
+ tclk_seed: "928a2c479e72a9a53e3b5133fc55021f",
263
+ },
264
+ },
265
+ coordinator_ieee: "00124b0009d80ba7",
266
+ pan_id: "007c",
267
+ extended_pan_id: "00124b0009d69f77",
268
+ nwk_update_id: 0,
269
+ security_level: 5,
270
+ channel: 21,
271
+ channel_mask: [21],
272
+ network_key: {
273
+ key: "01030507090b0d0f00020406080a0c0d",
274
+ sequence_number: 0,
275
+ frame_counter: 16754,
276
+ },
277
+ devices: [
278
+ {
279
+ nwk_address: "ddf6",
280
+ ieee_address: "00124b002226ef87",
281
+ },
282
+ {
283
+ nwk_address: "c2dc",
284
+ ieee_address: "04cf8cdf3c79455f",
285
+ link_key: {
286
+ key: "0e768569dd935d8e7302e74e7629f13f",
287
+ rx_counter: 0,
288
+ tx_counter: 275,
289
+ },
290
+ },
291
+ {
292
+ nwk_address: "740a",
293
+ ieee_address: "680ae2fffeae5647",
294
+ link_key: {
295
+ key: "7c079d02aae015facd7ae9608d4baf56",
296
+ rx_counter: 0,
297
+ tx_counter: 275,
298
+ },
299
+ },
300
+ {
301
+ nwk_address: "19fa",
302
+ ieee_address: "00158d00024fa79b",
303
+ link_key: {
304
+ key: "cea550908aa1529ee90eea3c3bdc26fc",
305
+ rx_counter: 0,
306
+ tx_counter: 44,
307
+ },
308
+ },
309
+ {
310
+ nwk_address: "6182",
311
+ ieee_address: "00158d00024f4518",
312
+ link_key: {
313
+ key: "267e1e31fcd8171f8acf63459effbca5",
314
+ rx_counter: 0,
315
+ tx_counter: 44,
316
+ },
317
+ },
318
+ {
319
+ nwk_address: "4285",
320
+ ieee_address: "00158d00024f810d",
321
+ link_key: {
322
+ key: "55ba1e31fcd8171f9f0b63459effbca5",
323
+ rx_counter: 0,
324
+ tx_counter: 44,
325
+ },
326
+ },
327
+ ],
328
+ };
329
+
330
+ const legacyBackup = {
331
+ adapterType: "zStack",
332
+ time: "Thu, 04 Mar 2021 10:55:12 GMT",
333
+ meta: {
334
+ product: 2,
335
+ },
336
+ data: {
337
+ ZCD_NV_EXTADDR: {
338
+ id: 1,
339
+ offset: 0,
340
+ osal: true,
341
+ product: -1,
342
+ value: [167, 11, 216, 9, 0, 75, 18, 0],
343
+ len: 8,
344
+ },
345
+ ZCD_NV_NIB: {
346
+ id: 33,
347
+ offset: 0,
348
+ osal: true,
349
+ product: -1,
350
+ value: [
351
+ 145, 5, 2, 16, 20, 16, 0, 20, 0, 0, 0, 1, 5, 1, 143, 7, 0, 2, 5, 30, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 8, 0, 0, 32, 0,
352
+ 15, 15, 4, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 119, 159, 214, 9, 0, 75, 18, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 3, 0, 1, 120, 10, 1, 0, 0, 146, 235, 0,
354
+ ],
355
+ len: 110,
356
+ },
357
+ ZCD_NV_PANID: {
358
+ id: 131,
359
+ offset: 0,
360
+ osal: true,
361
+ product: -1,
362
+ value: [123, 0],
363
+ len: 2,
364
+ },
365
+ ZCD_NV_EXTENDED_PAN_ID: {
366
+ id: 45,
367
+ offset: 0,
368
+ osal: true,
369
+ product: -1,
370
+ value: [221, 221, 221, 221, 221, 221, 221, 221],
371
+ len: 8,
372
+ },
373
+ ZCD_NV_NWK_ACTIVE_KEY_INFO: {
374
+ id: 58,
375
+ offset: 0,
376
+ osal: true,
377
+ product: -1,
378
+ value: [0, 1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
379
+ len: 17,
380
+ },
381
+ ZCD_NV_NWK_ALTERN_KEY_INFO: {
382
+ id: 59,
383
+ offset: 0,
384
+ osal: true,
385
+ product: -1,
386
+ value: [0, 1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
387
+ len: 17,
388
+ },
389
+ ZCD_NV_APS_USE_EXT_PANID: {
390
+ id: 71,
391
+ offset: 0,
392
+ osal: true,
393
+ product: -1,
394
+ value: [0, 0, 0, 0, 0, 0, 0, 0],
395
+ len: 8,
396
+ },
397
+ ZCD_NV_PRECFGKEY: {
398
+ id: 98,
399
+ offset: 0,
400
+ osal: true,
401
+ product: -1,
402
+ value: [1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13],
403
+ len: 16,
404
+ },
405
+ ZCD_NV_PRECFGKEY_ENABLE: {
406
+ id: 99,
407
+ offset: 0,
408
+ osal: true,
409
+ product: -1,
410
+ value: [0],
411
+ len: 1,
412
+ },
413
+ ZCD_NV_CHANLIST: {
414
+ id: 132,
415
+ offset: 0,
416
+ osal: true,
417
+ product: -1,
418
+ value: [0, 20, 0, 0],
419
+ len: 4,
420
+ },
421
+ ZCD_NV_LEGACY_TCLK_TABLE_START: {
422
+ id: 273,
423
+ product: 2,
424
+ offset: 0,
425
+ osal: true,
426
+ value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0],
427
+ len: 19,
428
+ },
429
+ ZCD_NV_LEGACY_NWK_SEC_MATERIAL_TABLE_START: {
430
+ id: 117,
431
+ product: 2,
432
+ offset: 0,
433
+ osal: true,
434
+ value: [83, 144, 14, 0, 134, 114, 56, 25, 0, 75, 18, 0],
435
+ len: 12,
436
+ },
437
+ },
438
+ };
439
+
440
+ class ZnpRequestMockBuilder {
441
+ // biome-ignore lint/suspicious/noExplicitAny: API
442
+ public responders: {subsystem: Subsystem; command: string; exec: (payload: any, handler?: ZnpRequestMockBuilder) => any}[] = [];
443
+ public nvItems: {id: NvItemsIds; value?: Buffer}[] = [];
444
+ public nvExtendedItems: {sysId: NvSystemIds; id: NvItemsIds; subId: number; value?: Buffer}[] = [];
445
+
446
+ constructor() {
447
+ const handleOsalNvRead = (payload, handler) => {
448
+ if (payload.offset !== undefined && payload.offset !== 0) {
449
+ throw new Error("osalNvLength offset not supported");
450
+ }
451
+ const item = handler.nvItems.find((e) => e.id === payload.id);
452
+ return {payload: {status: item?.value ? 0 : 1, value: item?.value ? item.value : undefined}};
453
+ };
454
+ this.handle(Subsystem.SYS, "osalNvRead", handleOsalNvRead);
455
+ this.handle(Subsystem.SYS, "osalNvReadExt", handleOsalNvRead);
456
+
457
+ const handleOsalNvWrite = (payload, handler) => {
458
+ if (payload.offset !== undefined && payload.offset !== 0) {
459
+ throw new Error("osalNvLength offset not supported");
460
+ }
461
+ const item = handler.nvItems.find((e) => e.id === payload.id);
462
+ if (item) {
463
+ item.value = payload.value;
464
+ return {payload: {status: 0}};
465
+ }
466
+
467
+ return {payload: {status: 1}};
468
+ };
469
+ this.handle(Subsystem.SYS, "osalNvWrite", handleOsalNvWrite);
470
+ this.handle(Subsystem.SYS, "osalNvWriteExt", handleOsalNvWrite);
471
+
472
+ this.handle(Subsystem.SYS, "osalNvItemInit", (payload, handler) => {
473
+ let item = handler.nvItems.find((e) => e.id === payload.id);
474
+ if (item) {
475
+ if (item.value && item.value.length !== payload.len) {
476
+ return {payload: {status: 0x0a}};
477
+ }
478
+ return {payload: {status: 0x00}};
479
+ }
480
+
481
+ item = {
482
+ id: payload.id,
483
+ value: payload.initvalue || null,
484
+ };
485
+ handler.nvItems.push(item);
486
+ return {payload: {status: 0x09}};
487
+ });
488
+ this.handle(Subsystem.SYS, "osalNvLength", (payload, handler) => {
489
+ if (payload.offset !== undefined && payload.offset !== 0) {
490
+ throw new Error("osalNvLength offset not supported");
491
+ }
492
+ const item = handler.nvItems.find((e) => e.id === payload.id);
493
+ return {payload: {length: item?.value ? item.value.length : 0}};
494
+ });
495
+ this.handle(Subsystem.SYS, "osalNvDelete", (payload, handler) => {
496
+ const item = handler.nvItems.find((e) => e.id === payload.id);
497
+ if (item) {
498
+ if (item.value && item.value.length !== payload.len) {
499
+ return {payload: {status: 0x0a}};
500
+ }
501
+ const itemIndex = handler.nvItems.indexOf(item);
502
+ handler.nvItems.splice(itemIndex, 1);
503
+ return {payload: {status: 0x00}};
504
+ }
505
+
506
+ return {payload: {status: 0x09}};
507
+ });
508
+
509
+ this.handle(Subsystem.SYS, "nvRead", (payload, handler: ZnpRequestMockBuilder) => {
510
+ if (payload.offset !== undefined && payload.offset !== 0) {
511
+ throw new Error("nvRead offset not supported");
512
+ }
513
+ const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
514
+ return {
515
+ payload: {
516
+ status: item?.value ? 0 : 1,
517
+ value: item?.value ? item.value : undefined,
518
+ len: item?.value?.length || undefined,
519
+ },
520
+ };
521
+ });
522
+
523
+ this.handle(Subsystem.SYS, "nvWrite", (payload, handler: ZnpRequestMockBuilder) => {
524
+ if (payload.offset !== undefined && payload.offset !== 0) {
525
+ throw new Error("nwWrite offset not supported");
526
+ }
527
+ const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
528
+ if (item) {
529
+ item.value = payload.value;
530
+ return {payload: {status: 0}};
531
+ }
532
+
533
+ return {payload: {status: 1}};
534
+ });
535
+
536
+ this.handle(Subsystem.SYS, "nvCreate", (payload, handler: ZnpRequestMockBuilder) => {
537
+ let item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
538
+ if (item) {
539
+ if (item.value && item.value.length !== payload.len) {
540
+ return {payload: {status: 0x0a}};
541
+ }
542
+ return {payload: {status: 0x00}};
543
+ }
544
+
545
+ item = {
546
+ sysId: payload.sysid,
547
+ id: payload.itemid,
548
+ subId: payload.subid,
549
+ value: null,
550
+ };
551
+ handler.nvExtendedItems.push(item);
552
+ return {payload: {status: 0x09}};
553
+ });
554
+ this.handle(Subsystem.SYS, "nvLength", (payload, handler) => {
555
+ if (payload.offset !== undefined && payload.offset !== 0) {
556
+ throw new Error("nvLength offset not supported");
557
+ }
558
+ const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
559
+ return {payload: {len: item?.value ? item.value.length : 0}};
560
+ });
561
+ this.handle(Subsystem.SYS, "nvDelete", (payload, handler) => {
562
+ const item = handler.nvExtendedItems.find((e) => e.sysId === payload.sysid && e.id === payload.itemid && e.subId === payload.subid);
563
+ if (item) {
564
+ if (item.value && item.value.length !== payload.len) {
565
+ return {payload: {status: 0x0a}};
566
+ }
567
+ const itemIndex = handler.nvItems.indexOf(item);
568
+ handler.nvItems.splice(itemIndex, 1);
569
+ return {payload: {status: 0x00}};
570
+ }
571
+
572
+ return {payload: {status: 0x09}};
573
+ });
574
+ }
575
+
576
+ // biome-ignore lint/suspicious/noExplicitAny: API
577
+ public handle(subsystem: Subsystem, command: string, exec?: (payload: any, handler?: ZnpRequestMockBuilder) => any) {
578
+ const index = this.responders.findIndex((r) => r.subsystem === subsystem && r.command === command);
579
+ if (index > -1) {
580
+ this.responders.splice(index, 1);
581
+ }
582
+ this.responders.push({subsystem, command, exec: exec || (() => ({}))});
583
+ return this;
584
+ }
585
+
586
+ public nv(id: NvItemsIds, value?: Buffer) {
587
+ const index = this.nvItems.findIndex((e) => e.id === id);
588
+ if (index > -1) {
589
+ this.nvItems.splice(index, 1);
590
+ }
591
+ if (value) {
592
+ this.nvItems.push({id, value: value || null});
593
+ }
594
+ return this;
595
+ }
596
+
597
+ public nvExtended(sysId: NvSystemIds, id: NvItemsIds, subId: number, value?: Buffer) {
598
+ const index = this.nvExtendedItems.findIndex((e) => e.sysId === sysId && e.id === id && e.subId === subId);
599
+ if (index > -1) {
600
+ this.nvExtendedItems.splice(index, 1);
601
+ }
602
+ if (value) {
603
+ this.nvExtendedItems.push({sysId, id, subId, value: value || null});
604
+ }
605
+ return this;
606
+ }
607
+
608
+ // biome-ignore lint/suspicious/noExplicitAny: API
609
+ public execute(message: {subsystem: Subsystem; command: string; payload: any}) {
610
+ const responder = this.responders.find((r) => r.subsystem === message.subsystem && r.command === message.command);
611
+ if (!responder) {
612
+ const msg = `Not implemented - ${Subsystem[message.subsystem]} - ${message.command} - ${JSON.stringify(message.payload)}`;
613
+ console.log(msg);
614
+ throw new Error(msg);
615
+ }
616
+ const response = responder.exec(message.payload, this);
617
+ return response;
618
+ }
619
+
620
+ public clone(): ZnpRequestMockBuilder {
621
+ const newBuilder = new ZnpRequestMockBuilder();
622
+ newBuilder.responders = this.responders.map((responder) => ({...responder}));
623
+ newBuilder.nvItems = this.nvItems.map((item) => ({...item, value: Buffer.from(item.value)}));
624
+ newBuilder.nvExtendedItems = this.nvExtendedItems.map((item) => ({...item, value: Buffer.from(item.value)}));
625
+ return newBuilder;
626
+ }
627
+ }
628
+
629
+ const baseZnpRequestMock = new ZnpRequestMockBuilder()
630
+ .handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack30x, revision: 20201026}} : undefined))
631
+ .handle(Subsystem.SYS, "ping", () => ({}))
632
+ .handle(Subsystem.SYS, "resetReq", () => ({}))
633
+ .handle(Subsystem.SYS, "getExtAddr", () => ({payload: {extaddress: "0x00124b0009d69f77"}}))
634
+ .handle(Subsystem.SYS, "stackTune", () => ({}))
635
+ .handle(Subsystem.ZDO, "extFindGroup", () => ({payload: {status: 0}}))
636
+ .handle(Subsystem.ZDO, "extAddGroup", () => ({payload: {status: 0}}))
637
+ .handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: 0x00, ieeeaddr: "0x00124b0009d80ba7"}}))
638
+ .handle(Subsystem.ZDO, "activeEpReq", () => ({}))
639
+ .handle(Subsystem.ZDO, "simpleDescReq", () => ({}))
640
+ .handle(Subsystem.ZDO, "mgmtPermitJoinReq", () => ({}))
641
+ .handle(Subsystem.ZDO, "nodeDescReq", () => ({}))
642
+ .handle(Subsystem.ZDO, "bindReq", () => ({}))
643
+ .handle(Subsystem.ZDO, "unbindReq", () => ({}))
644
+ .handle(Subsystem.ZDO, "mgmtLeaveReq", () => ({}))
645
+ .handle(Subsystem.ZDO, "mgmtLqiReq", () => ({}))
646
+ .handle(Subsystem.ZDO, "mgmtRtgReq", () => ({}))
647
+ .handle(Subsystem.ZDO, "mgmtNwkUpdateReq", () => ({}))
648
+ .handle(Subsystem.AF, "interPanCtl", () => ({}))
649
+ .handle(Subsystem.ZDO, "extRouteDisc", () => ({}))
650
+ .handle(Subsystem.ZDO, "nwkAddrReq", () => ({}))
651
+ .handle(Subsystem.UTIL, "assocRemove", () => ({payload: {}}))
652
+ .handle(Subsystem.UTIL, "assocGetWithAddress", () => ({payload: {noderelation: assocGetWithAddressNodeRelation}}))
653
+ .handle(Subsystem.UTIL, "assocAdd", () => ({payload: {}}))
654
+ .handle(Subsystem.UTIL, "ledControl", () => ({}))
655
+ .handle(Subsystem.APP_CNF, "bdbAddInstallCode", () => ({}))
656
+ .handle(Subsystem.AF, "register", () => ({}))
657
+ .handle(Subsystem.AF, "dataRequest", () => {
658
+ if (dataRequestCode !== 0) {
659
+ throw new Error(`Data request failed with code '${dataRequestCode}'`);
660
+ }
661
+ return {};
662
+ })
663
+ .handle(Subsystem.AF, "dataRequestExt", () => {
664
+ if (dataRequestExtCode !== 0) {
665
+ throw new Error(`Data request failed with code '${dataRequestExtCode}'`);
666
+ }
667
+ return {};
668
+ })
669
+ .handle(Subsystem.SYS, "resetReq", () => ({}))
670
+ .handle(Subsystem.APP_CNF, "bdbSetChannel", () => ({}))
671
+ .handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
672
+ const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
673
+ if (nibIndex > -1) {
674
+ handler.nvItems.splice(nibIndex, 1);
675
+ }
676
+ handler.nvItems.push({
677
+ id: NvItemsIds.NIB,
678
+ value: Buffer.from(
679
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
680
+ "hex",
681
+ ),
682
+ });
683
+ return {};
684
+ })
685
+ .handle(Subsystem.ZDO, "extNwkInfo", (_, handler) => {
686
+ const nib = Structs.nib(handler.nvItems.find((item) => item.id === NvItemsIds.NIB).value);
687
+ return {payload: {panid: nib.nwkPanId, extendedpanid: `0x${nib.extendedPANID.toString("hex")}`, channel: nib.nwkLogicalChannel}};
688
+ })
689
+ .handle(Subsystem.ZDO, "startupFromApp", () => ({}))
690
+ .nv(NvItemsIds.CHANLIST, Buffer.from([0, 8, 0, 0]))
691
+ .nv(NvItemsIds.PRECFGKEY, Buffer.alloc(16, 0))
692
+ .nv(NvItemsIds.PRECFGKEYS_ENABLE, Buffer.from([0]))
693
+ .nv(NvItemsIds.NWKKEY, Buffer.alloc(24, 0))
694
+ .nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("000000000000000000000000000000000000", "hex"))
695
+ .nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("000000000000000000000000000000000000", "hex"))
696
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
697
+ .nv(
698
+ NvItemsIds.NIB,
699
+ Buffer.from(
700
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000000bcd0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
701
+ "hex",
702
+ ),
703
+ );
704
+
705
+ let mockHugePayloadTimestamp: number | undefined;
706
+ let mockHugePayloadIndex = 0;
707
+ let mockHugePayload: Buffer = Buffer.alloc(0);
708
+ let mockHugePayloadError = 0;
709
+
710
+ /**
711
+ * @param mockError 0: none
712
+ * 1: dataRetrieve error return
713
+ * 2: dataRetrieve wrong data size return
714
+ */
715
+ const mockIncomingMsgExtSetHugeData = (timestamp: number, data: Buffer, mockError = 0) => {
716
+ mockHugePayloadTimestamp = timestamp;
717
+ mockHugePayload = data;
718
+ mockHugePayloadIndex = 0;
719
+ mockHugePayloadError = mockError;
720
+ };
721
+
722
+ const incomingMsgExtHugeDataReqMock = baseZnpRequestMock.clone().handle(Subsystem.AF, "dataRetrieve", (payload) => {
723
+ if (payload.timestamp !== mockHugePayloadTimestamp) {
724
+ throw new Error("Payload timestamp doesnt match mock data timestamp. Did you call mockIncomingMsgExtSetHugeData?");
725
+ }
726
+ if (payload.length > mockHugePayload.length - mockHugePayloadIndex) {
727
+ // Unclear if ZNP returns error or just returns fewer bytes
728
+ // in this case, but handler should request the correct amount.
729
+ throw new Error("Requested data chunk exceeds available bytes");
730
+ }
731
+ const chunk = {
732
+ payload: {
733
+ status: mockHugePayloadError === 1 ? 0x01 : 0x00,
734
+ length: mockHugePayloadError === 2 ? payload.length + 1 : payload.length,
735
+ data: mockHugePayload.subarray(mockHugePayloadIndex, mockHugePayloadIndex + payload.length),
736
+ },
737
+ };
738
+ if (payload.length === 0) {
739
+ // dataRetrieve with length 0 closes the ZNP buffer
740
+ mockHugePayloadTimestamp = 0;
741
+ mockHugePayloadIndex = 0;
742
+ } else {
743
+ mockHugePayloadIndex += payload.length;
744
+ }
745
+ return chunk;
746
+ });
747
+
748
+ const empty3UnalignedRequestMock = baseZnpRequestMock
749
+ .clone()
750
+ .handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
751
+ const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
752
+ if (nibIndex > -1) {
753
+ handler.nvItems.splice(nibIndex, 1);
754
+ }
755
+ handler.nvItems.push({
756
+ id: NvItemsIds.NIB,
757
+ value: Buffer.from(
758
+ "fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
759
+ "hex",
760
+ ),
761
+ });
762
+ return {};
763
+ })
764
+ .nv(NvItemsIds.NWKKEY, Buffer.alloc(21, 0))
765
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
766
+ .nv(
767
+ NvItemsIds.NIB,
768
+ Buffer.from(
769
+ "fb050279147900640000000105018f0700020d1e00001500000000000000000000ffff08000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
770
+ "hex",
771
+ ),
772
+ )
773
+ .nv(
774
+ NvItemsIds.ADDRMGR,
775
+ Buffer.from(
776
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
777
+ "hex",
778
+ ),
779
+ )
780
+ .nv(
781
+ NvItemsIds.APS_LINK_KEY_TABLE,
782
+ Buffer.from(
783
+ "0000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000feff000000",
784
+ "hex",
785
+ ),
786
+ );
787
+ for (let i = 0; i < 4; i++) {
788
+ empty3UnalignedRequestMock.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
789
+ }
790
+ for (let i = 0; i < 16; i++) {
791
+ empty3UnalignedRequestMock.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, Buffer.from("00000000000000000000000000000000000000", "hex"));
792
+ }
793
+ for (let i = 0; i < 16; i++) {
794
+ empty3UnalignedRequestMock.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
795
+ }
796
+
797
+ const empty3AlignedRequestMock = baseZnpRequestMock
798
+ .clone()
799
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
800
+ .nv(
801
+ NvItemsIds.NIB,
802
+ Buffer.from(
803
+ "fb050279147900640000000105018f000700020d1e000000150000000000000000000000ffff0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
804
+ "hex",
805
+ ),
806
+ )
807
+ .nv(
808
+ NvItemsIds.ADDRMGR,
809
+ Buffer.from(
810
+ "00ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff00000000000000000000",
811
+ "hex",
812
+ ),
813
+ )
814
+ .nv(
815
+ NvItemsIds.APS_LINK_KEY_TABLE,
816
+ Buffer.from(
817
+ "0000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000",
818
+ "hex",
819
+ ),
820
+ );
821
+ for (let i = 0; i < 4; i++) {
822
+ empty3AlignedRequestMock.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
823
+ }
824
+ for (let i = 0; i < 16; i++) {
825
+ empty3AlignedRequestMock.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, Buffer.from("0000000000000000000000000000000000000000", "hex"));
826
+ }
827
+ for (let i = 0; i < 16; i++) {
828
+ empty3AlignedRequestMock.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
829
+ }
830
+
831
+ const commissioned3AlignedRequestMock = empty3AlignedRequestMock
832
+ .clone()
833
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x55]))
834
+ .nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
835
+ .nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
836
+ .nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
837
+ .nv(
838
+ NvItemsIds.NIB,
839
+ Buffer.from(
840
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
841
+ "hex",
842
+ ),
843
+ )
844
+ .nv(
845
+ NvItemsIds.ADDRMGR,
846
+ Buffer.from(
847
+ "01ff4f3a080000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000ff00000000000000000000",
848
+ "hex",
849
+ ),
850
+ );
851
+
852
+ const commissioned3AlignedConfigMistmachRequestMock = commissioned3AlignedRequestMock
853
+ .clone()
854
+ .nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
855
+ .nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
856
+ .nv(
857
+ NvItemsIds.NIB,
858
+ Buffer.from(
859
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000007e000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
860
+ "hex",
861
+ ),
862
+ );
863
+
864
+ const empty3x0AlignedRequestMock = baseZnpRequestMock
865
+ .clone()
866
+ .handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack3x0, revision: 20210430}} : undefined))
867
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x00]))
868
+ .nv(
869
+ NvItemsIds.NIB,
870
+ Buffer.from(
871
+ "fb050279147900640000000105018f000700020d1e000000150000000000000000000000ffff0800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
872
+ "hex",
873
+ ),
874
+ )
875
+ .nv(
876
+ NvItemsIds.APS_LINK_KEY_TABLE,
877
+ Buffer.from(
878
+ "0000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000feff00000000",
879
+ "hex",
880
+ ),
881
+ );
882
+ for (let i = 0; i < 16; i++) {
883
+ empty3x0AlignedRequestMock.nvExtended(NvSystemIds.ZSTACK, NvItemsIds.ZCD_NV_EX_ADDRMGR, i, Buffer.from("00ff00000000000000000000", "hex"));
884
+ }
885
+ for (let i = 0; i < 4; i++) {
886
+ empty3x0AlignedRequestMock.nvExtended(
887
+ NvSystemIds.ZSTACK,
888
+ NvItemsIds.EX_NWK_SEC_MATERIAL_TABLE,
889
+ i,
890
+ Buffer.from("000000000000000000000000", "hex"),
891
+ );
892
+ }
893
+ for (let i = 0; i < 16; i++) {
894
+ empty3x0AlignedRequestMock.nvExtended(
895
+ NvSystemIds.ZSTACK,
896
+ NvItemsIds.EX_TCLK_TABLE,
897
+ i,
898
+ Buffer.from("0000000000000000000000000000000000000000", "hex"),
899
+ );
900
+ }
901
+ for (let i = 0; i < 16; i++) {
902
+ empty3x0AlignedRequestMock.nvExtended(
903
+ NvSystemIds.ZSTACK,
904
+ NvItemsIds.ZCD_NV_EX_APS_KEY_DATA_TABLE,
905
+ i,
906
+ Buffer.from("000000000000000000000000000000000000000000000000", "hex"),
907
+ );
908
+ }
909
+
910
+ const commissioned3x0AlignedRequestMock = empty3x0AlignedRequestMock
911
+ .clone()
912
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x55]))
913
+ .nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
914
+ .nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
915
+ .nv(NvItemsIds.NWK_ALTERN_KEY_INFO, Buffer.from("0001030507090b0d0f00020406080a0c0d00", "hex"))
916
+ .nv(
917
+ NvItemsIds.NIB,
918
+ Buffer.from(
919
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000007b000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
920
+ "hex",
921
+ ),
922
+ )
923
+ .nvExtended(NvSystemIds.ZSTACK, NvItemsIds.ZCD_NV_EX_ADDRMGR, 0, Buffer.from("01ff4f3a0800000000000000", "hex"));
924
+
925
+ const empty12UnalignedRequestMock = baseZnpRequestMock
926
+ .clone()
927
+ .handle(Subsystem.SYS, "version", (payload) => (equals(payload, {}) ? {payload: {product: ZnpVersion.ZStack12}} : undefined))
928
+ .handle(Subsystem.SAPI, "readConfiguration", (payload, handler) => {
929
+ if (payload.configid !== NvItemsIds.PRECFGKEY) {
930
+ throw new Error("Only pre-configured key should be read/written using SAPI layer");
931
+ }
932
+ const item = handler.nvItems.find((item) => item.id === payload.configid);
933
+ if (item) {
934
+ return {payload: {status: 0, configid: item.id, len: item.value?.length || 0, value: item.value}};
935
+ }
936
+ return {payload: {status: 1}};
937
+ })
938
+ .handle(Subsystem.SAPI, "writeConfiguration", (payload, handler) => {
939
+ if (payload.configid !== NvItemsIds.PRECFGKEY) {
940
+ throw new Error("Only pre-configured key should be read/written using SAPI layer");
941
+ }
942
+ const item = handler.nvItems.find((item) => item.id === payload.configid);
943
+ if (item) {
944
+ item.value = payload.value;
945
+ } else {
946
+ handler.nvItems.push({id: payload.configid, value: payload.value});
947
+ }
948
+ handler.nv(
949
+ NvItemsIds.NIB,
950
+ Buffer.from(
951
+ "fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
952
+ "hex",
953
+ ),
954
+ );
955
+ return {payload: {status: 0}};
956
+ })
957
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1, Buffer.from([0x00]));
958
+
959
+ const commissioned12UnalignedRequestMock = empty12UnalignedRequestMock
960
+ .clone()
961
+ .nv(NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1, Buffer.from([0x55]))
962
+ .nv(NvItemsIds.PRECFGKEY, Buffer.from("01030507090b0d0f00020406080a0c0d", "hex"))
963
+ .nv(
964
+ NvItemsIds.NIB,
965
+ Buffer.from(
966
+ "fb050279147900640000000105018f0700020d1e000015000000000000000000007b0008000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a010000060200",
967
+ "hex",
968
+ ),
969
+ );
970
+
971
+ const commissioned12UnalignedMismatchRequestMock = commissioned12UnalignedRequestMock
972
+ .clone()
973
+ .nv(NvItemsIds.PRECFGKEY, Buffer.from("aabb0507090b0d0f00020406080a0c0d", "hex"));
974
+
975
+ const mockZnpRequest = vi
976
+ .fn()
977
+ .mockReturnValue(new Promise((resolve) => resolve({payload: {}})))
978
+ .mockImplementation(
979
+ // biome-ignore lint/suspicious/noExplicitAny: API
980
+ (subsystem: Subsystem, command: string, payload: any, _expectedStatus: ZnpCommandStatus) =>
981
+ new Promise((resolve) => resolve(baseZnpRequestMock.execute({subsystem, command, payload}))),
982
+ );
983
+ const mockZnpRequestZdo = vi.fn();
984
+ const mockZnpWaitFor = vi.fn();
985
+ const mockZnpOpen = vi.fn();
986
+ const mockZnpClose = vi.fn();
987
+ const mockQueueExecute = vi.fn().mockImplementation(async (func) => await func());
988
+ const mocks = [mockZnpOpen, mockZnpRequest, mockZnpClose];
989
+
990
+ const mockZnpRequestWith = (builder: ZnpRequestMockBuilder) => {
991
+ builder = builder.clone();
992
+ mockZnpRequest.mockImplementation(
993
+ // biome-ignore lint/suspicious/noExplicitAny: API
994
+ (subsystem: Subsystem, command: string, payload: any, _expectedStatus: ZnpCommandStatus) =>
995
+ new Promise((resolve) => resolve(builder.execute({subsystem, command, payload}))),
996
+ );
997
+ };
998
+
999
+ const mockZnpWaitForDefault = () => {
1000
+ mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
1001
+ const missing = () => {
1002
+ const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
1003
+ console.log(msg);
1004
+ throw new Error(msg);
1005
+ };
1006
+
1007
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
1008
+ return waitForResult(
1009
+ mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
1010
+ Zdo.Status.SUCCESS,
1011
+ {
1012
+ nwkAddress: 0,
1013
+ endpointList: [],
1014
+ },
1015
+ ]),
1016
+ );
1017
+ }
1018
+
1019
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtPermitJoinRsp") {
1020
+ return waitForResult(mockZdoZpiObject("mgmtPermitJoinRsp", target, [Zdo.Status.SUCCESS, undefined]));
1021
+ }
1022
+
1023
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
1024
+ return waitForResult({payload: {state: 9}});
1025
+ }
1026
+
1027
+ missing();
1028
+ });
1029
+ };
1030
+
1031
+ const mockZnpWaitForStateChangeIndTimeout = () => {
1032
+ mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
1033
+ const missing = () => {
1034
+ const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
1035
+ console.log(msg);
1036
+ throw new Error(msg);
1037
+ };
1038
+
1039
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
1040
+ return waitForResult(
1041
+ mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
1042
+ Zdo.Status.SUCCESS,
1043
+ {
1044
+ nwkAddress: 0,
1045
+ endpointList: [],
1046
+ },
1047
+ ]),
1048
+ );
1049
+ }
1050
+
1051
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
1052
+ return;
1053
+ }
1054
+
1055
+ missing();
1056
+ });
1057
+ };
1058
+
1059
+ let bindStatusResponse = 0;
1060
+
1061
+ const mockZdoZpiObject = <T>(commandName: string, srcaddr: number | undefined, payload: [Zdo.Status, T | undefined]): ZpiObject => {
1062
+ const subsystem = Subsystem.ZDO;
1063
+ const command = Definition[subsystem].find((c) => c.name === commandName)!;
1064
+ return {
1065
+ type: Type.AREQ,
1066
+ subsystem,
1067
+ command,
1068
+ payload: {srcaddr, zdo: payload},
1069
+ };
1070
+ };
1071
+
1072
+ const mockZpiObject = (type: Type, subsystem: Subsystem, commandName: string, payload: {[s: string]: unknown}) => {
1073
+ const command = Definition[subsystem].find((c) => c.name === commandName);
1074
+ return {type, subsystem, payload, command};
1075
+ };
1076
+
1077
+ const basicMocks = () => {
1078
+ mockZnpRequestWith(commissioned3x0AlignedRequestMock);
1079
+ mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
1080
+ const missing = () => {
1081
+ const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
1082
+ console.log(msg);
1083
+ throw new Error(msg);
1084
+ };
1085
+
1086
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
1087
+ return waitForResult(
1088
+ mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
1089
+ Zdo.Status.SUCCESS,
1090
+ {
1091
+ nwkAddress: 0,
1092
+ endpointList: [1, 2, 3, 4, 5, 6, 8, 10, 11, 110, 12, 13, 47, 242],
1093
+ },
1094
+ ]),
1095
+ );
1096
+ }
1097
+
1098
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
1099
+ return waitForResult({payload: {}});
1100
+ }
1101
+
1102
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtPermitJoinRsp") {
1103
+ return waitForResult(mockZdoZpiObject("mgmtPermitJoinRsp", target, [Zdo.Status.SUCCESS, undefined]));
1104
+ }
1105
+
1106
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "simpleDescRsp") {
1107
+ let responsePayload: SimpleDescriptorResponse;
1108
+ if (simpleDescriptorEndpoint === 1) {
1109
+ responsePayload = {
1110
+ length: 1, // bogus
1111
+ endpoint: 1,
1112
+ profileId: 123,
1113
+ deviceId: 5,
1114
+ inClusterList: [1],
1115
+ outClusterList: [2],
1116
+ nwkAddress: target,
1117
+ deviceVersion: 0,
1118
+ };
1119
+ } else if (simpleDescriptorEndpoint === 99) {
1120
+ responsePayload = {
1121
+ length: 1, // bogus
1122
+ endpoint: 99,
1123
+ profileId: 123,
1124
+ deviceId: 5,
1125
+ inClusterList: [1],
1126
+ outClusterList: [2],
1127
+ nwkAddress: target,
1128
+ deviceVersion: 0,
1129
+ };
1130
+ } else {
1131
+ responsePayload = {
1132
+ length: 1, // bogus
1133
+ endpoint: simpleDescriptorEndpoint,
1134
+ profileId: 124,
1135
+ deviceId: 7,
1136
+ inClusterList: [8],
1137
+ outClusterList: [9],
1138
+ nwkAddress: target,
1139
+ deviceVersion: 0,
1140
+ };
1141
+ }
1142
+
1143
+ return waitForResult(mockZdoZpiObject<SimpleDescriptorResponse>("simpleDescRsp", target, [Zdo.Status.SUCCESS, responsePayload]));
1144
+ }
1145
+
1146
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nodeDescRsp") {
1147
+ if (nodeDescRspErrorOnce) {
1148
+ nodeDescRspErrorOnce = false;
1149
+ return {
1150
+ start: () => {
1151
+ return {
1152
+ promise: new Promise((_resolve, reject) => {
1153
+ reject("timeout after xx");
1154
+ }),
1155
+ };
1156
+ },
1157
+ ID: 89,
1158
+ };
1159
+ }
1160
+
1161
+ return waitForResult(
1162
+ mockZdoZpiObject<NodeDescriptorResponse>("nodeDescRsp", target, [
1163
+ Zdo.Status.SUCCESS,
1164
+ {
1165
+ manufacturerCode: target * 2,
1166
+ apsFlags: 0,
1167
+ capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES,
1168
+ deprecated1: 0,
1169
+ fragmentationSupported: true,
1170
+ frequencyBand: 0,
1171
+ logicalType: target - 1,
1172
+ maxBufSize: 0,
1173
+ maxIncTxSize: 0,
1174
+ maxOutTxSize: 0,
1175
+ nwkAddress: target,
1176
+ serverMask: {
1177
+ backupTrustCenter: 0,
1178
+ deprecated1: 0,
1179
+ deprecated2: 0,
1180
+ deprecated3: 0,
1181
+ deprecated4: 0,
1182
+ networkManager: 0,
1183
+ primaryTrustCenter: 0,
1184
+ reserved1: 0,
1185
+ reserved2: 0,
1186
+ stackComplianceRevision: 0,
1187
+ },
1188
+ tlvs: [],
1189
+ },
1190
+ ]),
1191
+ );
1192
+ }
1193
+
1194
+ if (type === Type.AREQ && subsystem === Subsystem.AF && command === "dataConfirm") {
1195
+ const status = dataConfirmCode;
1196
+ if (dataConfirmCodeReset) {
1197
+ dataConfirmCode = 0;
1198
+ }
1199
+
1200
+ if (status === 9999) {
1201
+ return {
1202
+ start: () => {
1203
+ return {
1204
+ promise: new Promise((_resolve, reject) => {
1205
+ reject("timeout after xx");
1206
+ }),
1207
+ };
1208
+ },
1209
+ ID: 99,
1210
+ };
1211
+ }
1212
+
1213
+ return waitForResult({payload: {status}}, 99);
1214
+ }
1215
+
1216
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLqiRsp" && target === 203) {
1217
+ const defaults = {deviceType: 0, extendedPanId: [0], permitJoining: 0, reserved1: 0, reserved2: 0, rxOnWhenIdle: 0};
1218
+
1219
+ if (lastStartIndex === 0) {
1220
+ lastStartIndex += 2;
1221
+ return waitForResult(
1222
+ mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
1223
+ Zdo.Status.SUCCESS,
1224
+ {
1225
+ neighborTableEntries: 5,
1226
+ startIndex: 0,
1227
+ entryList: [
1228
+ {lqi: 10, nwkAddress: 2, eui64: "0x3", relationship: 3, depth: 1, ...defaults},
1229
+ {lqi: 15, nwkAddress: 3, eui64: "0x4", relationship: 2, depth: 5, ...defaults},
1230
+ ],
1231
+ },
1232
+ ]),
1233
+ );
1234
+ }
1235
+
1236
+ if (lastStartIndex === 2) {
1237
+ lastStartIndex += 2;
1238
+ return waitForResult(
1239
+ mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
1240
+ Zdo.Status.SUCCESS,
1241
+ {
1242
+ neighborTableEntries: 5,
1243
+ startIndex: 0,
1244
+ entryList: [
1245
+ {lqi: 10, nwkAddress: 5, eui64: "0x6", relationship: 3, depth: 1, ...defaults},
1246
+ {lqi: 15, nwkAddress: 7, eui64: "0x8", relationship: 2, depth: 5, ...defaults},
1247
+ ],
1248
+ },
1249
+ ]),
1250
+ );
1251
+ }
1252
+
1253
+ if (lastStartIndex === 4) {
1254
+ return waitForResult(
1255
+ mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [
1256
+ Zdo.Status.SUCCESS,
1257
+ {
1258
+ neighborTableEntries: 5,
1259
+ startIndex: 0,
1260
+ entryList: [{lqi: 10, nwkAddress: 9, eui64: "0x10", relationship: 3, depth: 1, ...defaults}],
1261
+ },
1262
+ ]),
1263
+ );
1264
+ }
1265
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLqiRsp" && target === 204) {
1266
+ return waitForResult(mockZdoZpiObject<LQITableResponse>("mgmtLqiRsp", target, [Zdo.Status.NOT_AUTHORIZED, undefined]));
1267
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtRtgRsp" && target === 205) {
1268
+ const defaultEntryList = {
1269
+ manyToOne: 0,
1270
+ memoryConstrained: 0,
1271
+ reserved1: 0,
1272
+ routeRecordRequired: 0,
1273
+ status: Zdo.RoutingTableStatus[0] as keyof typeof Zdo.RoutingTableStatus,
1274
+ };
1275
+ if (lastStartIndex === 0) {
1276
+ lastStartIndex += 2;
1277
+ return waitForResult(
1278
+ mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
1279
+ Zdo.Status.SUCCESS,
1280
+ {
1281
+ startIndex: 0,
1282
+ routingTableEntries: 5,
1283
+ entryList: [
1284
+ {destinationAddress: 10, nextHopAddress: 3, ...defaultEntryList},
1285
+ {destinationAddress: 11, nextHopAddress: 3, ...defaultEntryList},
1286
+ ],
1287
+ },
1288
+ ]),
1289
+ );
1290
+ }
1291
+
1292
+ if (lastStartIndex === 2) {
1293
+ lastStartIndex += 2;
1294
+ return waitForResult(
1295
+ mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
1296
+ Zdo.Status.SUCCESS,
1297
+ {
1298
+ startIndex: 0,
1299
+ routingTableEntries: 5,
1300
+ entryList: [
1301
+ {destinationAddress: 12, nextHopAddress: 3, ...defaultEntryList},
1302
+ {destinationAddress: 13, nextHopAddress: 3, ...defaultEntryList},
1303
+ ],
1304
+ },
1305
+ ]),
1306
+ );
1307
+ }
1308
+
1309
+ if (lastStartIndex === 4) {
1310
+ return waitForResult(
1311
+ mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [
1312
+ Zdo.Status.SUCCESS,
1313
+ {
1314
+ startIndex: 0,
1315
+ routingTableEntries: 5,
1316
+ entryList: [{destinationAddress: 14, nextHopAddress: 3, ...defaultEntryList}],
1317
+ },
1318
+ ]),
1319
+ );
1320
+ }
1321
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtRtgRsp" && target === 206) {
1322
+ return waitForResult(mockZdoZpiObject<RoutingTableResponse>("mgmtRtgRsp", target, [Zdo.Status.INSUFFICIENT_SPACE, undefined]));
1323
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "bindRsp" && target === 301) {
1324
+ return waitForResult(mockZdoZpiObject("bindRsp", target, [bindStatusResponse, undefined]));
1325
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "unbindRsp" && target === 301) {
1326
+ return waitForResult(mockZdoZpiObject("unbindRsp", target, [bindStatusResponse, undefined]));
1327
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "mgmtLeaveRsp" && target === 401) {
1328
+ return waitForResult(mockZdoZpiObject("mgmtLeaveRsp", target, [Zdo.Status.SUCCESS, undefined]));
1329
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nwkAddrRsp" && target === "0x03") {
1330
+ return waitForResult(
1331
+ mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", target, [
1332
+ Zdo.Status.SUCCESS,
1333
+ {
1334
+ nwkAddress: 3,
1335
+ eui64: "0x03",
1336
+ assocDevList: [],
1337
+ startIndex: 0,
1338
+ },
1339
+ ]),
1340
+ );
1341
+ } else if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "nwkAddrRsp" && target === "0x02") {
1342
+ return waitForResult(
1343
+ mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", target, [
1344
+ Zdo.Status.SUCCESS,
1345
+ {
1346
+ nwkAddress: 2,
1347
+ eui64: "0x02",
1348
+ assocDevList: [],
1349
+ startIndex: 0,
1350
+ },
1351
+ ]),
1352
+ );
1353
+ } else {
1354
+ missing();
1355
+ }
1356
+ });
1357
+ };
1358
+
1359
+ const touchlinkScanRequest = Zcl.Frame.create(
1360
+ Zcl.FrameType.SPECIFIC,
1361
+ Zcl.Direction.CLIENT_TO_SERVER,
1362
+ false,
1363
+ undefined,
1364
+ 12,
1365
+ "scanRequest",
1366
+ Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
1367
+ {transactionID: 1, zigbeeInformation: 4, touchlinkInformation: 18},
1368
+ {},
1369
+ );
1370
+
1371
+ const touchlinkScanResponse = Zcl.Frame.create(
1372
+ Zcl.FrameType.SPECIFIC,
1373
+ Zcl.Direction.SERVER_TO_CLIENT,
1374
+ false,
1375
+ undefined,
1376
+ 12,
1377
+ "scanResponse",
1378
+ Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
1379
+ {
1380
+ transactionID: 1,
1381
+ rssiCorrection: 10,
1382
+ zigbeeInformation: 5,
1383
+ touchlinkInformation: 6,
1384
+ keyBitmask: 12,
1385
+ responseID: 11,
1386
+ extendedPanID: "0x0017210104d9cd33",
1387
+ networkUpdateID: 1,
1388
+ logicalChannel: 12,
1389
+ panID: 13,
1390
+ networkAddress: 5,
1391
+ numberOfSubDevices: 10,
1392
+ totalGroupIdentifiers: 5,
1393
+ },
1394
+ {},
1395
+ );
1396
+
1397
+ const touchlinkIdentifyRequest = Zcl.Frame.create(
1398
+ Zcl.FrameType.SPECIFIC,
1399
+ Zcl.Direction.CLIENT_TO_SERVER,
1400
+ false,
1401
+ undefined,
1402
+ 12,
1403
+ "identifyRequest",
1404
+ Zcl.Utils.getCluster("touchlink", undefined, {}).ID,
1405
+ {transactionID: 1, duration: 65535},
1406
+ {},
1407
+ );
1408
+
1409
+ const getRandomArbitrary = (min, max) => {
1410
+ return Math.random() * (max - min) + min;
1411
+ };
1412
+
1413
+ const getTempFile = () => {
1414
+ const tempPath = path.resolve("temp");
1415
+ if (!fs.existsSync(tempPath)) {
1416
+ fs.mkdirSync(tempPath);
1417
+ }
1418
+ return path.join(tempPath, `temp_${getRandomArbitrary(1, 99999999)}`);
1419
+ };
1420
+
1421
+ let znpReceived;
1422
+ let znpClose;
1423
+ let dataConfirmCode = 0;
1424
+ let dataConfirmCodeReset = false;
1425
+ let nodeDescRspErrorOnce = false;
1426
+ let dataRequestCode = 0;
1427
+ let dataRequestExtCode = 0;
1428
+ let lastStartIndex = 0;
1429
+ let simpleDescriptorEndpoint = 0;
1430
+ let assocGetWithAddressNodeRelation;
1431
+
1432
+ vi.mock("../../../src/adapter/z-stack/znp/znp", () => ({
1433
+ Znp: vi.fn(() => ({
1434
+ on: (event, handler) => {
1435
+ if (event === "received") {
1436
+ znpReceived = handler;
1437
+ } else if (event === "close") {
1438
+ znpClose = handler;
1439
+ }
1440
+ },
1441
+ open: mockZnpOpen,
1442
+ request: mockZnpRequest,
1443
+ requestZdo: mockZnpRequestZdo,
1444
+ requestWithReply: mockZnpRequest,
1445
+ waitFor: mockZnpWaitFor,
1446
+ close: mockZnpClose,
1447
+ })),
1448
+ }));
1449
+
1450
+ vi.mock("../../../src/utils/queue", () => ({
1451
+ Queue: vi.fn(() => ({
1452
+ execute: mockQueueExecute,
1453
+ count: () => 1,
1454
+ })),
1455
+ }));
1456
+
1457
+ const mocksClear = [mockLogger.debug, mockLogger.info, mockLogger.warning, mockLogger.error];
1458
+
1459
+ describe("zstack-adapter", () => {
1460
+ let adapter: ZStackAdapter;
1461
+
1462
+ beforeAll(() => {
1463
+ setLogger(mockLogger);
1464
+ });
1465
+
1466
+ afterAll(() => {
1467
+ vi.useRealTimers();
1468
+ });
1469
+
1470
+ beforeEach(() => {
1471
+ vi.useRealTimers();
1472
+ vi.useFakeTimers();
1473
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
1474
+ mockZnpWaitForDefault();
1475
+ for (const m of mocks) m.mockRestore();
1476
+ for (const m of mocksClear) m.mockClear();
1477
+ mockQueueExecute.mockClear();
1478
+ mockZnpWaitFor.mockClear();
1479
+ dataConfirmCode = 0;
1480
+ dataRequestCode = 0;
1481
+ dataRequestExtCode = 0;
1482
+ bindStatusResponse = 0;
1483
+ assocGetWithAddressNodeRelation = 1;
1484
+ networkOptions.networkKeyDistribute = false;
1485
+ dataConfirmCodeReset = false;
1486
+ nodeDescRspErrorOnce = false;
1487
+ lastStartIndex = 0;
1488
+ simpleDescriptorEndpoint = 0;
1489
+ });
1490
+
1491
+ it("should commission network with 3.0.x adapter", async () => {
1492
+ mockZnpRequestWith(empty3AlignedRequestMock);
1493
+ const result = await adapter.start();
1494
+ expect(result).toBe("reset");
1495
+ });
1496
+
1497
+ it("should commission network with 3.0.x adapter - auto concurrency", async () => {
1498
+ mockZnpRequestWith(empty3AlignedRequestMock);
1499
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {});
1500
+ const result = await adapter.start();
1501
+ expect(result).toBe("reset");
1502
+ });
1503
+
1504
+ it("should commission network with 3.x.0 adapter - auto concurrency", async () => {
1505
+ mockZnpRequestWith(empty3x0AlignedRequestMock);
1506
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {});
1507
+ const result = await adapter.start();
1508
+ expect(result).toBe("reset");
1509
+ });
1510
+
1511
+ it("should commission network with 3.0.x adapter - unaligned 8-bit", async () => {
1512
+ mockZnpRequestWith(empty3UnalignedRequestMock);
1513
+ const result = await adapter.start();
1514
+ expect(result).toBe("reset");
1515
+ });
1516
+
1517
+ it("should commission network with 3.0.x adapter - default extended pan id", async () => {
1518
+ mockZnpRequestWith(empty3AlignedRequestMock);
1519
+ adapter = new ZStackAdapter(networkOptionsDefaultExtendedPanId, serialPortOptions, "backup.json", {concurrent: 3});
1520
+ const result = await adapter.start();
1521
+ expect(result).toBe("reset");
1522
+ });
1523
+
1524
+ it("should commission with 3.0.x adapter - empty, mismatched config/backup", async () => {
1525
+ const backupFile = getTempFile();
1526
+ fs.writeFileSync(backupFile, JSON.stringify(backupNotMatchingConfig), "utf8");
1527
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1528
+ mockZnpRequestWith(empty3AlignedRequestMock);
1529
+ const result = await adapter.start();
1530
+ expect(result).toBe("reset");
1531
+ });
1532
+
1533
+ it("should commission with 3.0.x adapter - commissioned, mismatched adapter-config-backup", async () => {
1534
+ const backupFile = getTempFile();
1535
+ fs.writeFileSync(backupFile, JSON.stringify(backupNotMatchingConfig), "utf8");
1536
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1537
+ mockZnpRequestWith(commissioned3AlignedConfigMistmachRequestMock);
1538
+ const result = await adapter.start();
1539
+ expect(result).toBe("reset");
1540
+ });
1541
+
1542
+ it("should fail to commission network with 3.0.x adapter with invalid pan id 65535", async () => {
1543
+ mockZnpRequestWith(empty3AlignedRequestMock);
1544
+ adapter = new ZStackAdapter(networkOptionsInvalidPanId, serialPortOptions, "backup.json", {concurrent: 3});
1545
+ await expect(adapter.start()).rejects.toThrowError("network commissioning failed - cannot use pan id 65535");
1546
+ });
1547
+
1548
+ it("should fail to commission network with 3.0.x adapter when bdb commissioning times out", async () => {
1549
+ mockZnpWaitForStateChangeIndTimeout();
1550
+ mockZnpRequestWith(empty3AlignedRequestMock);
1551
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
1552
+ await expect(adapter.start()).rejects.toThrowError(
1553
+ "network commissioning timed out - most likely network with the same panId or extendedPanId already exists nearby",
1554
+ );
1555
+ });
1556
+
1557
+ it("should fail to commission network with 3.0.x adapter when nib fails to settle", async () => {
1558
+ mockZnpRequestWith(empty3AlignedRequestMock.clone().handle(Subsystem.APP_CNF, "bdbStartCommissioning", () => ({})));
1559
+ vi.setConfig({testTimeout: 35000});
1560
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
1561
+ const promise = adapter.start();
1562
+ await expect(promise).rejects.toThrowError("network commissioning failed - timed out waiting for nib to settle");
1563
+ });
1564
+
1565
+ it("should fail to commission network with 3.0.x adapter when nib reports different pan id", async () => {
1566
+ mockZnpRequestWith(
1567
+ empty3AlignedRequestMock.clone().handle(Subsystem.APP_CNF, "bdbStartCommissioning", (_, handler) => {
1568
+ const nibIndex = handler.nvItems.findIndex((e) => e.id === NvItemsIds.NIB);
1569
+ if (nibIndex > -1) {
1570
+ handler.nvItems.splice(nibIndex, 1);
1571
+ }
1572
+ handler.nvItems.push({
1573
+ id: NvItemsIds.NIB,
1574
+ value: Buffer.from(
1575
+ "fb050279147900640000000105018f000700020d1e0000001500000000000000000000007c000800000020000f0f0400010000000100000000779fd609004b1200010000000000000000000000000000000000000000000000000000000000000000000000003c0c0001780a0100000006020000",
1576
+ "hex",
1577
+ ),
1578
+ });
1579
+ return {};
1580
+ }),
1581
+ );
1582
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3});
1583
+ const promise = adapter.start();
1584
+ await expect(promise).rejects.toThrowError("network commissioning failed - panId collision detected (expected=123, actual=124)");
1585
+ });
1586
+
1587
+ it("should start network with 3.0.x adapter", async () => {
1588
+ mockZnpRequestWith(commissioned3AlignedRequestMock);
1589
+ const result = await adapter.start();
1590
+ expect(result).toBe("resumed");
1591
+ });
1592
+
1593
+ it("should restore unified backup with 3.0.x adapter and create backup - empty", async () => {
1594
+ const backupFile = getTempFile();
1595
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1596
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1597
+ mockZnpRequestWith(empty3AlignedRequestMock);
1598
+ const result = await adapter.start();
1599
+ expect(result).toBe("restored");
1600
+
1601
+ await adapter.backup([]);
1602
+ });
1603
+
1604
+ it("should restore unified backup with 3.0.x adapter and create backup - no tclk seed", async () => {
1605
+ const backupFile = getTempFile();
1606
+ const backup = JSON.parse(JSON.stringify(backupMatchingConfig));
1607
+ delete backup.stack_specific.zstack;
1608
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1609
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1610
+ mockZnpRequestWith(empty3AlignedRequestMock);
1611
+ const result = await adapter.start();
1612
+ expect(result).toBe("restored");
1613
+
1614
+ await adapter.backup([]);
1615
+ });
1616
+
1617
+ it("should restore unified backup with 3.x.0 adapter and create backup - empty", async () => {
1618
+ const backupFile = getTempFile();
1619
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1620
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1621
+ mockZnpRequestWith(empty3x0AlignedRequestMock);
1622
+ const result = await adapter.start();
1623
+ expect(result).toBe("restored");
1624
+
1625
+ await adapter.backup([]);
1626
+ });
1627
+
1628
+ it("should (recommission) restore unified backup with 1.2 adapter and create backup - empty", async () => {
1629
+ const backupFile = getTempFile();
1630
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig12), "utf8");
1631
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 1});
1632
+ mockZnpRequestWith(empty12UnalignedRequestMock);
1633
+ const result = await adapter.start();
1634
+ expect(result).toBe("restored");
1635
+
1636
+ const backup = await adapter.backup([]);
1637
+ expect(backup.networkKeyInfo.frameCounter).toBe(0);
1638
+ });
1639
+
1640
+ it("should create backup with 3.0.x adapter - default security material table entry", async () => {
1641
+ const builder = commissioned3AlignedRequestMock.clone();
1642
+ mockZnpRequestWith(builder);
1643
+ const result = await adapter.start();
1644
+ expect(result).toBe("resumed");
1645
+ for (let i = 0; i < 4; i++) {
1646
+ builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
1647
+ }
1648
+
1649
+ const secMaterialTableEntry = Structs.nwkSecMaterialDescriptorEntry();
1650
+ secMaterialTableEntry.extendedPanID = Buffer.alloc(8, 0xff);
1651
+ secMaterialTableEntry.FrameCounter = 2800;
1652
+ builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + 0, secMaterialTableEntry.serialize("aligned"));
1653
+ mockZnpRequestWith(builder);
1654
+
1655
+ const backup = await adapter.backup([]);
1656
+ expect(backup.networkKeyInfo.frameCounter).toBe(2800);
1657
+ });
1658
+
1659
+ it("should create backup with 3.0.x adapter - emnpty security material table", async () => {
1660
+ const builder = commissioned3AlignedRequestMock.clone();
1661
+ mockZnpRequestWith(builder);
1662
+ const result = await adapter.start();
1663
+ expect(result).toBe("resumed");
1664
+ for (let i = 0; i < 4; i++) {
1665
+ builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
1666
+ }
1667
+ mockZnpRequestWith(builder);
1668
+
1669
+ const backup = await adapter.backup([]);
1670
+ expect(backup.networkKeyInfo.frameCounter).toBe(1250);
1671
+ });
1672
+
1673
+ it("should create backup with 3.0.x adapter - security material table with generic record", async () => {
1674
+ const builder = commissioned3AlignedRequestMock.clone();
1675
+ mockZnpRequestWith(builder);
1676
+ const result = await adapter.start();
1677
+ expect(result).toBe("resumed");
1678
+ for (let i = 0; i < 4; i++) {
1679
+ builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + i, Buffer.from("000000000000000000000000", "hex"));
1680
+ }
1681
+ const genericEntry = Structs.nwkSecMaterialDescriptorEntry();
1682
+ genericEntry.extendedPanID = Buffer.from("ffffffffffffffff", "hex");
1683
+ genericEntry.FrameCounter = 8737;
1684
+ builder.nv(NvItemsIds.LEGACY_NWK_SEC_MATERIAL_TABLE_START + 3, genericEntry.serialize("aligned"));
1685
+ mockZnpRequestWith(builder);
1686
+
1687
+ const backup = await adapter.backup([]);
1688
+ expect(backup.networkKeyInfo.frameCounter).toBe(8737);
1689
+ });
1690
+
1691
+ it("should create backup with 1.2 adapter", async () => {
1692
+ mockZnpRequestWith(commissioned12UnalignedRequestMock);
1693
+ const result = await adapter.start();
1694
+ expect(result).toBe("resumed");
1695
+
1696
+ const backup = await adapter.backup([]);
1697
+ expect(backup.networkKeyInfo.frameCounter).toBe(0);
1698
+ });
1699
+
1700
+ it("should keep missing devices in backup", async () => {
1701
+ const backupFile = getTempFile();
1702
+ const backupWithMissingDevice = JSON.parse(JSON.stringify(backupMatchingConfig));
1703
+ backupWithMissingDevice.devices.push({
1704
+ nwk_address: "20fa",
1705
+ ieee_address: "00128d11124fa80b",
1706
+ link_key: {
1707
+ key: "bff550908aa1529ee90eea3c3bdc26fc",
1708
+ rx_counter: 0,
1709
+ tx_counter: 2,
1710
+ },
1711
+ });
1712
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1713
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1714
+ mockZnpRequestWith(empty3AlignedRequestMock);
1715
+ await adapter.start();
1716
+ fs.writeFileSync(backupFile, JSON.stringify(backupWithMissingDevice), "utf8");
1717
+ const devicesInDatabase = backupWithMissingDevice.devices.map((d) => ZSpec.Utils.eui64BEBufferToHex(d.ieee_address));
1718
+ const backup = await adapter.backup(devicesInDatabase);
1719
+ const missingDevice = backup.devices.find((d) => d.ieeeAddress.toString("hex") === "00128d11124fa80b");
1720
+ expect(missingDevice).not.toBeNull();
1721
+ expect(backupWithMissingDevice.devices.length).toBe(backup.devices.length);
1722
+ expect(missingDevice?.linkKey?.key.toString("hex")).toBe("bff550908aa1529ee90eea3c3bdc26fc");
1723
+ });
1724
+
1725
+ it("should fail when backup file is corrupted - Coordinator backup is corrupted", async () => {
1726
+ const backupFile = getTempFile();
1727
+ fs.writeFileSync(backupFile, "{", "utf8");
1728
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1729
+ mockZnpRequestWith(empty3AlignedRequestMock);
1730
+ await expect(adapter.start()).rejects.toThrowError("Coordinator backup is corrupted");
1731
+ });
1732
+
1733
+ it("should fail to restore unified backup with 3.0.x adapter - invalid open coordinator backup version", async () => {
1734
+ const backupFile = getTempFile();
1735
+ let backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1736
+ backupData = {
1737
+ ...backupData,
1738
+ metadata: {
1739
+ ...backupData.metadata,
1740
+ // biome-ignore lint/suspicious/noExplicitAny: mock
1741
+ version: 99 as any,
1742
+ },
1743
+ };
1744
+
1745
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1746
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1747
+ mockZnpRequestWith(empty3AlignedRequestMock);
1748
+ await expect(adapter.start()).rejects.toThrowError("Unsupported open coordinator backup version (version=99)");
1749
+ });
1750
+
1751
+ it("should fail to restore (unified) backup with 3.0.x adapter - unsupported backup format", async () => {
1752
+ const backupFile = getTempFile();
1753
+ let backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1754
+ backupData = {
1755
+ ...backupData,
1756
+ metadata: {
1757
+ ...backupData.metadata,
1758
+ version: undefined,
1759
+ },
1760
+ };
1761
+
1762
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1763
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1764
+ mockZnpRequestWith(empty3AlignedRequestMock);
1765
+ await expect(adapter.start()).rejects.toThrowError("Unknown backup format");
1766
+ });
1767
+
1768
+ it("should fail to restore unified backup with 3.0.x adapter - insufficient tclk table size", async () => {
1769
+ const backupFile = getTempFile();
1770
+ const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1771
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1772
+
1773
+ const builder = empty3AlignedRequestMock.clone();
1774
+ for (let i = 0; i < 16; i++) {
1775
+ builder.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + i, null);
1776
+ }
1777
+ builder.nv(NvItemsIds.LEGACY_TCLK_TABLE_START + 0, Buffer.from("0000000000000000000000000000000000000000", "hex"));
1778
+ mockZnpRequestWith(builder);
1779
+
1780
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1781
+ await expect(adapter.start()).rejects.toThrowError("target adapter tclk table size insufficient (size=1)");
1782
+ });
1783
+
1784
+ it("should fail to restore unified backup with 3.0.x adapter - insufficient aps link key data table size", async () => {
1785
+ const backupFile = getTempFile();
1786
+ const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1787
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1788
+
1789
+ const builder = empty3AlignedRequestMock.clone();
1790
+ for (let i = 0; i < 16; i++) {
1791
+ builder.nv(NvItemsIds.APS_LINK_KEY_DATA_START + i, null);
1792
+ }
1793
+ builder.nv(NvItemsIds.APS_LINK_KEY_DATA_START + 0, Buffer.from("000000000000000000000000000000000000000000000000", "hex"));
1794
+ mockZnpRequestWith(builder);
1795
+
1796
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1797
+ await expect(adapter.start()).rejects.toThrowError("target adapter aps link key data table size insufficient (size=1)");
1798
+ });
1799
+
1800
+ it("should fail to restore unified backup with 3.0.x adapter - insufficient security manager table size", async () => {
1801
+ const backupFile = getTempFile();
1802
+ const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1803
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1804
+
1805
+ const builder = empty3AlignedRequestMock.clone();
1806
+ builder.nv(NvItemsIds.APS_LINK_KEY_TABLE, Buffer.from("0000feff00000000", "hex"));
1807
+ mockZnpRequestWith(builder);
1808
+
1809
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1810
+ await expect(adapter.start()).rejects.toThrowError("target adapter security manager table size insufficient (size=1)");
1811
+ });
1812
+
1813
+ it("should fail to restore unified backup with 1.2 adapter - backup from newer adapter", async () => {
1814
+ const backupFile = getTempFile();
1815
+ const backupData: UnifiedBackupStorage = JSON.parse(JSON.stringify(backupMatchingConfig));
1816
+ fs.writeFileSync(backupFile, JSON.stringify(backupData), "utf8");
1817
+
1818
+ mockZnpRequestWith(empty12UnalignedRequestMock);
1819
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1820
+ await expect(adapter.start()).rejects.toThrowError(
1821
+ "your backup is from newer platform version (Z-Stack 3.0.x+) and cannot be restored onto Z-Stack 1.2 adapter - please remove backup before proceeding",
1822
+ );
1823
+ });
1824
+
1825
+ it("should fail to create backup with 3.0.x adapter - unable to read ieee address", async () => {
1826
+ mockZnpRequestWith(commissioned3AlignedRequestMock.clone().handle(Subsystem.SYS, "getExtAddr", () => ({payload: {}})));
1827
+ const result = await adapter.start();
1828
+ expect(result).toBe("resumed");
1829
+ await expect(adapter.backup([])).rejects.toThrowError("Failed to read adapter IEEE address");
1830
+ });
1831
+
1832
+ it("should fail to create backup with 3.0.x adapter - adapter not commissioned - missing nib", async () => {
1833
+ const builder = empty3AlignedRequestMock.clone();
1834
+ mockZnpRequestWith(builder);
1835
+ const result = await adapter.start();
1836
+ expect(result).toBe("reset");
1837
+ builder.nv(NvItemsIds.NIB, null);
1838
+ mockZnpRequestWith(builder);
1839
+ await expect(adapter.backup([])).rejects.toThrowError("Cannot backup - adapter not commissioned");
1840
+ });
1841
+
1842
+ it("should fail to create backup with 3.0.x adapter - missing active key info", async () => {
1843
+ const builder = empty3AlignedRequestMock.clone();
1844
+ mockZnpRequestWith(builder);
1845
+ const result = await adapter.start();
1846
+ expect(result).toBe("reset");
1847
+ builder.nv(NvItemsIds.NWK_ACTIVE_KEY_INFO, null);
1848
+ mockZnpRequestWith(builder);
1849
+ await expect(adapter.backup([])).rejects.toThrowError("Cannot backup - missing active key info");
1850
+ });
1851
+
1852
+ it("should restore legacy backup with 3.0.x adapter - empty", async () => {
1853
+ const backupFile = getTempFile();
1854
+ fs.writeFileSync(backupFile, JSON.stringify(legacyBackup), "utf8");
1855
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1856
+ mockZnpRequestWith(empty3AlignedRequestMock);
1857
+ const result = await adapter.start();
1858
+ expect(result).toBe("restored");
1859
+ });
1860
+
1861
+ it("should fail to restore legacy backup with 3.0.x adapter - missing NIB", async () => {
1862
+ const backupFile = getTempFile();
1863
+ const backup = JSON.parse(JSON.stringify(legacyBackup));
1864
+ delete backup.data.ZCD_NV_NIB;
1865
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1866
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1867
+ mockZnpRequestWith(empty3AlignedRequestMock);
1868
+ await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing NIB");
1869
+ });
1870
+
1871
+ it("should fail to restore legacy backup with 3.0.x adapter - missing active key info", async () => {
1872
+ const backupFile = getTempFile();
1873
+ const backup = JSON.parse(JSON.stringify(legacyBackup));
1874
+ delete backup.data.ZCD_NV_NWK_ACTIVE_KEY_INFO;
1875
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1876
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1877
+ mockZnpRequestWith(empty3AlignedRequestMock);
1878
+ await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing active key info");
1879
+ });
1880
+
1881
+ it("should fail to restore legacy backup with 3.0.x adapter - missing pre-configured key enabled", async () => {
1882
+ const backupFile = getTempFile();
1883
+ const backup = JSON.parse(JSON.stringify(legacyBackup));
1884
+ delete backup.data.ZCD_NV_PRECFGKEY_ENABLE;
1885
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1886
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1887
+ mockZnpRequestWith(empty3AlignedRequestMock);
1888
+ await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing pre-configured key enable attribute");
1889
+ });
1890
+
1891
+ it("should fail to restore legacy backup with 3.0.x adapter - pre-configured key enabled", async () => {
1892
+ const backupFile = getTempFile();
1893
+ const backup = JSON.parse(JSON.stringify(legacyBackup));
1894
+ delete backup.data.ZCD_NV_EX_NWK_SEC_MATERIAL_TABLE;
1895
+ delete backup.data.ZCD_NV_LEGACY_NWK_SEC_MATERIAL_TABLE_START;
1896
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1897
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1898
+ mockZnpRequestWith(empty3AlignedRequestMock);
1899
+ await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing network security material table");
1900
+ });
1901
+
1902
+ it("should fail to restore legacy backup with 3.0.x adapter - missing adapter ieee address", async () => {
1903
+ const backupFile = getTempFile();
1904
+ const backup = JSON.parse(JSON.stringify(legacyBackup));
1905
+ delete backup.data.ZCD_NV_EXTADDR;
1906
+ fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8");
1907
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1908
+ mockZnpRequestWith(empty3AlignedRequestMock);
1909
+ await expect(adapter.start()).rejects.toThrow("Backup corrupted - missing adapter IEEE address NV entry");
1910
+ });
1911
+
1912
+ it("should fail to start with 3.0.x adapter - commissioned, config-adapter mismatch", async () => {
1913
+ const backupFile = getTempFile();
1914
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1915
+
1916
+ adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3});
1917
+ mockZnpRequestWith(commissioned3AlignedRequestMock);
1918
+ await expect(adapter.start()).rejects.toThrow("startup failed - configuration-adapter mismatch - see logs above for more information");
1919
+ expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!");
1920
+ expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123");
1921
+ expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77");
1922
+ expect(mockLogger.error.mock.calls[3][0]).toBe(
1923
+ "- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter:active=01030507090b0d0f00020406080a0c0d adapter:preconfigured=01030507090b0d0f00020406080a0c0d, adapter:alternate=01030507090b0d0f00020406080a0c0d",
1924
+ );
1925
+ expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21");
1926
+ expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues.");
1927
+ expect(mockLogger.error.mock.calls[6][0]).toMatch(
1928
+ `If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`,
1929
+ );
1930
+ expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!");
1931
+ });
1932
+
1933
+ it("should start with runInconsistent option with 3.0.x adapter - commissioned, config-adapter mismatch", async () => {
1934
+ const backupFile = getTempFile();
1935
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1936
+
1937
+ adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {
1938
+ concurrent: 3,
1939
+ forceStartWithInconsistentAdapterConfiguration: true,
1940
+ });
1941
+ mockZnpRequestWith(commissioned3AlignedRequestMock);
1942
+ const result = await adapter.start();
1943
+ expect(result).toBe("resumed");
1944
+ expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!");
1945
+ expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123");
1946
+ expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77");
1947
+ expect(mockLogger.error.mock.calls[3][0]).toBe(
1948
+ "- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter:active=01030507090b0d0f00020406080a0c0d adapter:preconfigured=01030507090b0d0f00020406080a0c0d, adapter:alternate=01030507090b0d0f00020406080a0c0d",
1949
+ );
1950
+ expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21");
1951
+ expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues.");
1952
+ expect(mockLogger.error.mock.calls[6][0]).toMatch(
1953
+ `If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`,
1954
+ );
1955
+ expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!");
1956
+ expect(mockLogger.error.mock.calls[8][0]).toBe(
1957
+ "Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible.",
1958
+ );
1959
+ });
1960
+
1961
+ it("should start with 3.0.x adapter - backward-compat - reversed extended pan id", async () => {
1962
+ const backupFile = getTempFile();
1963
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1964
+
1965
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1966
+ const nib = Structs.nib(Buffer.from(commissioned3AlignedRequestMock.nvItems.find((item) => item.id === NvItemsIds.NIB).value));
1967
+ nib.extendedPANID = nib.extendedPANID.reverse();
1968
+ mockZnpRequestWith(commissioned3AlignedRequestMock.clone().nv(NvItemsIds.NIB, nib.serialize()));
1969
+ const result = await adapter.start();
1970
+ expect(result).toBe("resumed");
1971
+ expect(mockLogger.warning.mock.calls[0][0]).toBe("Extended PAN ID is reversed (expected=00124b0009d69f77, actual=779fd609004b1200)");
1972
+ });
1973
+
1974
+ it("should restore unified backup with 3.0.x adapter - commissioned, mismatched adapter-config, matching config-backup", async () => {
1975
+ const backupFile = getTempFile();
1976
+ fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8");
1977
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3});
1978
+ mockZnpRequestWith(commissioned3AlignedConfigMistmachRequestMock);
1979
+ const result = await adapter.start();
1980
+ expect(result).toBe("restored");
1981
+ });
1982
+
1983
+ it("should start network with 3.0.x adapter - resume in coordinator mode", async () => {
1984
+ mockZnpRequestWith(
1985
+ commissioned3AlignedRequestMock.clone().handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: DevStates.ZB_COORD}})),
1986
+ );
1987
+ mockZnpWaitFor.mockImplementation((type, subsystem, command, target, transid, state, timeout) => {
1988
+ const missing = () => {
1989
+ const msg = `Not implemented - ${Type[type]} - ${Subsystem[subsystem]} - ${command} - ${target} - ${transid} - ${state} - ${timeout}`;
1990
+ console.log(msg);
1991
+ throw new Error(msg);
1992
+ };
1993
+
1994
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "activeEpRsp") {
1995
+ return waitForResult(
1996
+ mockZdoZpiObject<ActiveEndpointsResponse>("activeEpRsp", target, [
1997
+ Zdo.Status.SUCCESS,
1998
+ {
1999
+ nwkAddress: 0,
2000
+ endpointList: [1, 2, 3],
2001
+ },
2002
+ ]),
2003
+ );
2004
+ }
2005
+
2006
+ if (type === Type.AREQ && subsystem === Subsystem.ZDO && command === "stateChangeInd") {
2007
+ return waitForResult({payload: {state: 9}});
2008
+ }
2009
+
2010
+ missing();
2011
+ });
2012
+ const result = await adapter.start();
2013
+ expect(result).toBe("resumed");
2014
+ });
2015
+
2016
+ it("should start network with 3.0.x adapter - resume in coordinator mode, extGroupFind failed", async () => {
2017
+ mockZnpRequestWith(
2018
+ commissioned3AlignedRequestMock
2019
+ .clone()
2020
+ .handle(Subsystem.UTIL, "getDeviceInfo", () => ({payload: {devicestate: DevStates.ZB_COORD}}))
2021
+ .handle(Subsystem.ZDO, "extFindGroup", () => ({payload: {status: 1}})),
2022
+ );
2023
+ const result = await adapter.start();
2024
+ expect(result).toBe("resumed");
2025
+ });
2026
+
2027
+ it("should commission network with 1.2 adapter", async () => {
2028
+ mockZnpRequestWith(empty12UnalignedRequestMock);
2029
+ const result = await adapter.start();
2030
+ expect(result).toBe("restored");
2031
+ });
2032
+
2033
+ it("should commission network with 1.2 adapter - default extended pan id", async () => {
2034
+ mockZnpRequestWith(empty12UnalignedRequestMock);
2035
+ adapter = new ZStackAdapter(networkOptionsDefaultExtendedPanId, serialPortOptions, "backup.json", {concurrent: 3});
2036
+ const result = await adapter.start();
2037
+ expect(result).toBe("restored");
2038
+ });
2039
+
2040
+ it("should commission network with 1.2 adapter - old adapter without version reporting", async () => {
2041
+ mockZnpRequestWith(empty12UnalignedRequestMock.clone().handle(Subsystem.SYS, "version", () => undefined));
2042
+ const result = await adapter.start();
2043
+ expect(result).toBe("restored");
2044
+ });
2045
+
2046
+ it("should reset network with 1.2 adapter - config mismtach", async () => {
2047
+ mockZnpRequestWith(commissioned12UnalignedMismatchRequestMock);
2048
+ const result = await adapter.start();
2049
+ expect(result).toBe("reset");
2050
+ });
2051
+
2052
+ it("Add install code: Install Code + CRC", async () => {
2053
+ basicMocks();
2054
+ await adapter.start();
2055
+ await adapter.addInstallCode(
2056
+ "0x9035EAFFFE424783",
2057
+ Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31, 0xe8, 0x02]),
2058
+ false,
2059
+ );
2060
+ const payload = {
2061
+ installCodeFormat: 0x1,
2062
+ ieeeaddr: "0x9035EAFFFE424783",
2063
+ installCode: Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31, 0xe8, 0x02]),
2064
+ };
2065
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.APP_CNF, "bdbAddInstallCode", payload);
2066
+ });
2067
+
2068
+ it("Add install code: Key derived from Install Code", async () => {
2069
+ basicMocks();
2070
+ await adapter.start();
2071
+ await adapter.addInstallCode(
2072
+ "0x9035EAFFFE424783",
2073
+ Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31]),
2074
+ true,
2075
+ );
2076
+ const payload = {
2077
+ installCodeFormat: 0x2,
2078
+ ieeeaddr: "0x9035EAFFFE424783",
2079
+ installCode: Buffer.from([0xae, 0x3b, 0x28, 0x72, 0x81, 0xcf, 0x16, 0xf5, 0x50, 0x73, 0x3a, 0x0c, 0xec, 0x38, 0xaa, 0x31]),
2080
+ };
2081
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.APP_CNF, "bdbAddInstallCode", payload);
2082
+ });
2083
+
2084
+ it("LED behaviour: disable LED true, firmware not handling leds", async () => {
2085
+ basicMocks();
2086
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: true});
2087
+ await adapter.start();
2088
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
2089
+ mockZnpRequest.mockClear();
2090
+ mockQueueExecute.mockClear();
2091
+ await adapter.permitJoin(255, 0);
2092
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
2093
+ mockZnpRequest.mockClear();
2094
+ mockQueueExecute.mockClear();
2095
+ await adapter.permitJoin(0, 0);
2096
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
2097
+ });
2098
+
2099
+ it("LED behaviour: disable LED false, firmware not handling leds", async () => {
2100
+ basicMocks();
2101
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: false});
2102
+ await adapter.start();
2103
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
2104
+ mockZnpRequest.mockClear();
2105
+ mockQueueExecute.mockClear();
2106
+ await adapter.permitJoin(255, 0);
2107
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
2108
+ mockZnpRequest.mockClear();
2109
+ mockQueueExecute.mockClear();
2110
+ await adapter.permitJoin(0, 0);
2111
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
2112
+ });
2113
+
2114
+ it("LED behaviour: disable LED true, firmware handling leds", async () => {
2115
+ mockZnpRequestWith(
2116
+ baseZnpRequestMock.clone().handle(Subsystem.SYS, "version", (_payload) => {
2117
+ return {payload: {product: ZnpVersion.ZStack30x, revision: 20211030}};
2118
+ }),
2119
+ );
2120
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: true});
2121
+ await adapter.start();
2122
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 0xff, mode: 5}, undefined, 500);
2123
+ mockZnpRequest.mockClear();
2124
+ mockQueueExecute.mockClear();
2125
+ await adapter.permitJoin(255, 0);
2126
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
2127
+ mockZnpRequest.mockClear();
2128
+ mockQueueExecute.mockClear();
2129
+ await adapter.permitJoin(0, 0);
2130
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), undefined, 500);
2131
+ });
2132
+
2133
+ it("LED behaviour: disable LED false, firmware handling leds", async () => {
2134
+ mockZnpRequestWith(
2135
+ baseZnpRequestMock.clone().handle(Subsystem.SYS, "version", (_payload) => {
2136
+ return {payload: {product: ZnpVersion.ZStack30x, revision: 20211030}};
2137
+ }),
2138
+ );
2139
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {disableLED: false});
2140
+ await adapter.start();
2141
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
2142
+ mockZnpRequest.mockClear();
2143
+ mockQueueExecute.mockClear();
2144
+ await adapter.permitJoin(255, 0);
2145
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
2146
+ mockZnpRequest.mockClear();
2147
+ mockQueueExecute.mockClear();
2148
+ await adapter.permitJoin(0, 0);
2149
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", expect.any(Object), null, 500);
2150
+ });
2151
+
2152
+ /* Original Tests */
2153
+
2154
+ it("Call znp constructor", () => {
2155
+ expect(Znp).toHaveBeenCalledWith("dummy", 800, false);
2156
+ });
2157
+
2158
+ it("Close adapter", async () => {
2159
+ basicMocks();
2160
+ await adapter.start();
2161
+ await adapter.stop();
2162
+ expect(mockZnpClose).toHaveBeenCalledTimes(1);
2163
+ });
2164
+
2165
+ it("Get coordinator IEEE", async () => {
2166
+ basicMocks();
2167
+ await adapter.start();
2168
+ const ieee = await adapter.getCoordinatorIEEE();
2169
+ expect(ieee).toStrictEqual("0x00124b0009d80ba7");
2170
+ });
2171
+
2172
+ it("Permit join all", async () => {
2173
+ basicMocks();
2174
+ await adapter.start();
2175
+ mockZnpRequest.mockClear();
2176
+ mockZnpRequestZdo.mockClear();
2177
+ mockQueueExecute.mockClear();
2178
+ await adapter.permitJoin(100);
2179
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2180
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2181
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.PERMIT_JOINING_REQUEST, 100, 1, []);
2182
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2183
+ Zdo.ClusterId.PERMIT_JOINING_REQUEST,
2184
+ Buffer.from([
2185
+ AddressMode.ADDR_BROADCAST,
2186
+ ZSpec.BroadcastAddress.DEFAULT & 0xff,
2187
+ (ZSpec.BroadcastAddress.DEFAULT >> 8) & 0xff,
2188
+ ...zdoPayload,
2189
+ ]),
2190
+ undefined,
2191
+ // Subsystem.ZDO, 'mgmtPermitJoinReq', {
2192
+ // addrmode: 0x0f,
2193
+ // dstaddr: 0xfffc,
2194
+ // duration: 100,
2195
+ // tcsignificance: 0,
2196
+ // }
2197
+ );
2198
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
2199
+ });
2200
+
2201
+ it("Permit join specific networkAddress", async () => {
2202
+ basicMocks();
2203
+ await adapter.start();
2204
+ mockZnpRequest.mockClear();
2205
+ mockZnpRequestZdo.mockClear();
2206
+ mockQueueExecute.mockClear();
2207
+ await adapter.permitJoin(102, 42102);
2208
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2209
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2210
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.PERMIT_JOINING_REQUEST, 102, 1, []);
2211
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2212
+ Zdo.ClusterId.PERMIT_JOINING_REQUEST,
2213
+ Buffer.from([AddressMode.ADDR_16BIT, 42102 & 0xff, (42102 >> 8) & 0xff, ...zdoPayload]),
2214
+ expect.any(Number),
2215
+ // Subsystem.ZDO, 'mgmtPermitJoinReq', {
2216
+ // addrmode: 2,
2217
+ // dstaddr: 42102,
2218
+ // duration: 102,
2219
+ // tcsignificance: 0,
2220
+ // }
2221
+ );
2222
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 1}, undefined, 500);
2223
+ });
2224
+
2225
+ it("Get coordinator version", async () => {
2226
+ basicMocks();
2227
+ await adapter.start();
2228
+ mockZnpRequest.mockClear();
2229
+ mockQueueExecute.mockClear();
2230
+ expect(await adapter.getCoordinatorVersion()).toStrictEqual({type: "ZStack3x0", meta: {revision: 20210430, product: 1}});
2231
+ });
2232
+
2233
+ it("Soft reset", async () => {
2234
+ basicMocks();
2235
+ await adapter.start();
2236
+ mockZnpRequest.mockClear();
2237
+ mockQueueExecute.mockClear();
2238
+ await adapter.reset("soft");
2239
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2240
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "resetReq", {type: 1});
2241
+ });
2242
+
2243
+ it("Hard reset", async () => {
2244
+ basicMocks();
2245
+ await adapter.start();
2246
+ mockZnpRequest.mockClear();
2247
+ mockQueueExecute.mockClear();
2248
+ await adapter.reset("hard");
2249
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2250
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "resetReq", {type: 0});
2251
+ });
2252
+
2253
+ it("Start with transmit power set", async () => {
2254
+ basicMocks();
2255
+ adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {transmitPower: 2, disableLED: false});
2256
+ await adapter.start();
2257
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.SYS, "stackTune", {operation: 0, value: 2});
2258
+ });
2259
+
2260
+ it("Support LED should go to false when LED request fails", async () => {
2261
+ basicMocks();
2262
+ await adapter.start();
2263
+ mockZnpRequest.mockClear();
2264
+ mockQueueExecute.mockClear();
2265
+ mockZnpRequest.mockImplementation(
2266
+ (_, cmd) =>
2267
+ new Promise((resolve, reject) => {
2268
+ if (cmd === "ledControl") reject("FAILED");
2269
+ else resolve(undefined);
2270
+ }),
2271
+ );
2272
+ await adapter.permitJoin(0, 0);
2273
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
2274
+ mockZnpRequest.mockClear();
2275
+ mockQueueExecute.mockClear();
2276
+ await adapter.permitJoin(0, 0);
2277
+ expect(mockZnpRequest).not.toHaveBeenCalledWith(Subsystem.UTIL, "ledControl", {ledid: 3, mode: 0}, undefined, 500);
2278
+ });
2279
+
2280
+ it("Send zcl frame network address", async () => {
2281
+ basicMocks();
2282
+ await adapter.start();
2283
+
2284
+ mockZnpRequest.mockClear();
2285
+ mockQueueExecute.mockClear();
2286
+ const frame = Zcl.Frame.create(
2287
+ Zcl.FrameType.GLOBAL,
2288
+ Zcl.Direction.CLIENT_TO_SERVER,
2289
+ true,
2290
+ undefined,
2291
+ 100,
2292
+ "writeNoRsp",
2293
+ 0,
2294
+ [{attrId: 0, dataType: 0, attrData: null}],
2295
+ {},
2296
+ );
2297
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2298
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
2299
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2300
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2301
+ 4,
2302
+ "dataRequest",
2303
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2304
+ 99,
2305
+ );
2306
+ });
2307
+
2308
+ it("Send zcl frame network address retry on MAC channel access failure", async () => {
2309
+ basicMocks();
2310
+ dataConfirmCode = 225;
2311
+ dataConfirmCodeReset = true;
2312
+ await adapter.start();
2313
+ mockZnpRequest.mockClear();
2314
+ mockQueueExecute.mockClear();
2315
+ const frame = Zcl.Frame.create(
2316
+ Zcl.FrameType.GLOBAL,
2317
+ Zcl.Direction.CLIENT_TO_SERVER,
2318
+ true,
2319
+ undefined,
2320
+ 100,
2321
+ "writeNoRsp",
2322
+ 0,
2323
+ [{attrId: 0, dataType: 0, attrData: null}],
2324
+ {},
2325
+ );
2326
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2327
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
2328
+ expect(mockZnpRequest).toHaveBeenCalledTimes(2);
2329
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2330
+ 4,
2331
+ "dataRequest",
2332
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2333
+ 99,
2334
+ );
2335
+ });
2336
+
2337
+ it("Send zcl frame network address dataConfirm fails", async () => {
2338
+ basicMocks();
2339
+ await adapter.start();
2340
+ dataConfirmCode = 201;
2341
+ mockZnpRequest.mockClear();
2342
+ mockQueueExecute.mockClear();
2343
+ const frame = Zcl.Frame.create(
2344
+ Zcl.FrameType.GLOBAL,
2345
+ Zcl.Direction.CLIENT_TO_SERVER,
2346
+ true,
2347
+ undefined,
2348
+ 100,
2349
+ "writeNoRsp",
2350
+ 0,
2351
+ [{attrId: 0, dataType: 0, attrData: null}],
2352
+ {},
2353
+ );
2354
+ let error;
2355
+ try {
2356
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2357
+ } catch (e) {
2358
+ error = e;
2359
+ }
2360
+ expect(error.message).toStrictEqual("Data request failed with error: 'NWK_UNSUPPORTED_ATTRIBUTE' (0xc9)");
2361
+ });
2362
+
2363
+ it("Send zcl frame network address with default response", async () => {
2364
+ basicMocks();
2365
+ await adapter.start();
2366
+ const defaultReponse = Zcl.Frame.create(
2367
+ Zcl.FrameType.GLOBAL,
2368
+ Zcl.Direction.SERVER_TO_CLIENT,
2369
+ true,
2370
+ undefined,
2371
+ 100,
2372
+ "defaultRsp",
2373
+ 0,
2374
+ {cmdId: 0, status: 0},
2375
+ {},
2376
+ );
2377
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
2378
+ clusterid: 0,
2379
+ srcendpoint: 20,
2380
+ srcaddr: 2,
2381
+ linkquality: 101,
2382
+ groupid: 12,
2383
+ data: defaultReponse.toBuffer(),
2384
+ });
2385
+ mockZnpRequest.mockClear();
2386
+ mockQueueExecute.mockClear();
2387
+ const frame = Zcl.Frame.create(
2388
+ Zcl.FrameType.GLOBAL,
2389
+ Zcl.Direction.CLIENT_TO_SERVER,
2390
+ false,
2391
+ undefined,
2392
+ 100,
2393
+ "writeNoRsp",
2394
+ 0,
2395
+ [{attrId: 0, dataType: 0, attrData: null}],
2396
+ {},
2397
+ );
2398
+ const request = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2399
+ znpReceived(object);
2400
+ await request;
2401
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
2402
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2403
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2404
+ 4,
2405
+ "dataRequest",
2406
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2407
+ 99,
2408
+ );
2409
+ });
2410
+
2411
+ it("Send zcl frame network address fails because mac transaction expire, should retry", async () => {
2412
+ basicMocks();
2413
+ await adapter.start();
2414
+ dataConfirmCode = 240;
2415
+ mockZnpRequest.mockClear();
2416
+ mockZnpRequestZdo.mockClear();
2417
+ mockQueueExecute.mockClear();
2418
+ const frame = Zcl.Frame.create(
2419
+ Zcl.FrameType.GLOBAL,
2420
+ Zcl.Direction.CLIENT_TO_SERVER,
2421
+ true,
2422
+ undefined,
2423
+ 100,
2424
+ "writeNoRsp",
2425
+ 0,
2426
+ [{attrId: 0, dataType: 0, attrData: null}],
2427
+ {},
2428
+ );
2429
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2430
+ let error;
2431
+ try {
2432
+ await response;
2433
+ } catch (e) {
2434
+ error = e;
2435
+ }
2436
+
2437
+ expect(error.message).toStrictEqual("Data request failed with error: 'MAC_TRANSACTION_EXPIRED' (0xf0)");
2438
+ expect(mockZnpRequest).toHaveBeenCalledTimes(9);
2439
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2440
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2441
+ 1,
2442
+ 4,
2443
+ "dataRequest",
2444
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2445
+ 99,
2446
+ );
2447
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2448
+ 2,
2449
+ 4,
2450
+ "dataRequest",
2451
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
2452
+ 99,
2453
+ );
2454
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
2455
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 7, "assocRemove", {ieeeadr: "0x02"});
2456
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2457
+ 5,
2458
+ 4,
2459
+ "dataRequest",
2460
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
2461
+ 99,
2462
+ );
2463
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(6, 7, "assocAdd", {ieeeadr: "0x02", noderelation: 1, nwkaddr: 2});
2464
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(7, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
2465
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2466
+ 8,
2467
+ 4,
2468
+ "dataRequest",
2469
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
2470
+ 99,
2471
+ );
2472
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2473
+ Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
2474
+ Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
2475
+ expect.any(Number),
2476
+ //9, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
2477
+ );
2478
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2479
+ 9,
2480
+ 4,
2481
+ "dataRequest",
2482
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
2483
+ 99,
2484
+ );
2485
+ });
2486
+
2487
+ it("Send zcl frame network address fails because mac transaction expire when not being a parent, should retry", async () => {
2488
+ basicMocks();
2489
+ await adapter.start();
2490
+ dataConfirmCode = 240;
2491
+ assocGetWithAddressNodeRelation = 255;
2492
+ mockZnpRequest.mockClear();
2493
+ mockZnpRequestZdo.mockClear();
2494
+ mockQueueExecute.mockClear();
2495
+ const frame = Zcl.Frame.create(
2496
+ Zcl.FrameType.GLOBAL,
2497
+ Zcl.Direction.CLIENT_TO_SERVER,
2498
+ true,
2499
+ undefined,
2500
+ 100,
2501
+ "writeNoRsp",
2502
+ 0,
2503
+ [{attrId: 0, dataType: 0, attrData: null}],
2504
+ {},
2505
+ );
2506
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2507
+ let error;
2508
+ try {
2509
+ await response;
2510
+ } catch (e) {
2511
+ error = e;
2512
+ }
2513
+
2514
+ expect(error.message).toStrictEqual("Data request failed with error: 'MAC_TRANSACTION_EXPIRED' (0xf0)");
2515
+ expect(mockZnpRequest).toHaveBeenCalledTimes(7);
2516
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2517
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2518
+ 1,
2519
+ 4,
2520
+ "dataRequest",
2521
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2522
+ 99,
2523
+ );
2524
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2525
+ 2,
2526
+ 4,
2527
+ "dataRequest",
2528
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
2529
+ 99,
2530
+ );
2531
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
2532
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
2533
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2534
+ 5,
2535
+ 4,
2536
+ "dataRequest",
2537
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
2538
+ 99,
2539
+ );
2540
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2541
+ Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
2542
+ Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
2543
+ expect.any(Number),
2544
+ //6, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
2545
+ );
2546
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2547
+ 6,
2548
+ 4,
2549
+ "dataRequest",
2550
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
2551
+ 99,
2552
+ );
2553
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2554
+ 7,
2555
+ 4,
2556
+ "dataRequest",
2557
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
2558
+ 99,
2559
+ );
2560
+ });
2561
+
2562
+ it("Send zcl frame network address fails because mac no ack, should retry", async () => {
2563
+ basicMocks();
2564
+ await adapter.start();
2565
+ dataConfirmCode = 233;
2566
+ mockZnpRequest.mockClear();
2567
+ mockZnpRequestZdo.mockClear();
2568
+ mockQueueExecute.mockClear();
2569
+ const frame = Zcl.Frame.create(
2570
+ Zcl.FrameType.GLOBAL,
2571
+ Zcl.Direction.CLIENT_TO_SERVER,
2572
+ true,
2573
+ undefined,
2574
+ 100,
2575
+ "writeNoRsp",
2576
+ 0,
2577
+ [{attrId: 0, dataType: 0, attrData: null}],
2578
+ {},
2579
+ );
2580
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2581
+ let error;
2582
+ try {
2583
+ await response;
2584
+ } catch (e) {
2585
+ error = e;
2586
+ }
2587
+
2588
+ expect(error.message).toStrictEqual("Data request failed with error: 'MAC_NO_ACK' (0xe9)");
2589
+ expect(mockZnpRequest).toHaveBeenCalledTimes(6);
2590
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2591
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2592
+ 1,
2593
+ 4,
2594
+ "dataRequest",
2595
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2596
+ 99,
2597
+ );
2598
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2599
+ 2,
2600
+ 4,
2601
+ "dataRequest",
2602
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
2603
+ 99,
2604
+ );
2605
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
2606
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2607
+ 4,
2608
+ 4,
2609
+ "dataRequest",
2610
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
2611
+ 99,
2612
+ );
2613
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2614
+ Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
2615
+ Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x02", false, 0),
2616
+ expect.any(Number),
2617
+ //5, 5, 'nwkAddrReq', {ieeeaddr: '0x02', reqtype: 0, startindex: 0}
2618
+ );
2619
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2620
+ 5,
2621
+ 4,
2622
+ "dataRequest",
2623
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
2624
+ 99,
2625
+ );
2626
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2627
+ 6,
2628
+ 4,
2629
+ "dataRequest",
2630
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
2631
+ 99,
2632
+ );
2633
+ });
2634
+
2635
+ it("Send zcl frame network address fails because mac no ack with network address change, should retry", async () => {
2636
+ basicMocks();
2637
+ await adapter.start();
2638
+ dataConfirmCode = 233;
2639
+ mockZnpRequest.mockClear();
2640
+ mockZnpRequestZdo.mockClear();
2641
+ mockQueueExecute.mockClear();
2642
+ const frame = Zcl.Frame.create(
2643
+ Zcl.FrameType.GLOBAL,
2644
+ Zcl.Direction.CLIENT_TO_SERVER,
2645
+ true,
2646
+ undefined,
2647
+ 100,
2648
+ "writeNoRsp",
2649
+ 0,
2650
+ [{attrId: 0, dataType: 0, attrData: null}],
2651
+ {},
2652
+ );
2653
+ const response = adapter.sendZclFrameToEndpoint("0x03", 2, 20, frame, 10000, false, false);
2654
+ let error;
2655
+ try {
2656
+ await response;
2657
+ } catch (e) {
2658
+ error = e;
2659
+ }
2660
+
2661
+ expect(error.message).toStrictEqual("Data request failed with error: 'MAC_NO_ACK' (0xe9)");
2662
+ // expect(mockZnpRequest).toHaveBeenCalledTimes(7);
2663
+ // expect(mockZnpRequestZdo).toHaveBeenCalledTimes(1);
2664
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2665
+ 1,
2666
+ 4,
2667
+ "dataRequest",
2668
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2669
+ 99,
2670
+ );
2671
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2672
+ 2,
2673
+ 4,
2674
+ "dataRequest",
2675
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 2},
2676
+ 99,
2677
+ );
2678
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: 30});
2679
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2680
+ 4,
2681
+ 4,
2682
+ "dataRequest",
2683
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 3},
2684
+ 99,
2685
+ );
2686
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
2687
+ Zdo.ClusterId.NETWORK_ADDRESS_REQUEST,
2688
+ Zdo.Buffalo.buildRequest(false, Zdo.ClusterId.NETWORK_ADDRESS_REQUEST, "0x03", false, 0),
2689
+ expect.any(Number),
2690
+ //5, 5, 'nwkAddrReq', {ieeeaddr: '0x03', reqtype: 0, startindex: 0}
2691
+ );
2692
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(5, 5, "extRouteDisc", {dstAddr: 3, options: 0, radius: 30});
2693
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2694
+ 6,
2695
+ 4,
2696
+ "dataRequest",
2697
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 3, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 4},
2698
+ 99,
2699
+ );
2700
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2701
+ 7,
2702
+ 4,
2703
+ "dataRequest",
2704
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 3, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 5},
2705
+ 99,
2706
+ );
2707
+ });
2708
+
2709
+ it("Send zcl frame network address fails because mac no ack with network address change, without recovery", async () => {
2710
+ basicMocks();
2711
+ await adapter.start();
2712
+ dataConfirmCode = 233;
2713
+ mockZnpRequest.mockClear();
2714
+ mockQueueExecute.mockClear();
2715
+ const frame = Zcl.Frame.create(
2716
+ Zcl.FrameType.GLOBAL,
2717
+ Zcl.Direction.CLIENT_TO_SERVER,
2718
+ true,
2719
+ undefined,
2720
+ 100,
2721
+ "writeNoRsp",
2722
+ 0,
2723
+ [{attrId: 0, dataType: 0, attrData: null}],
2724
+ {},
2725
+ );
2726
+ const response = adapter.sendZclFrameToEndpoint("0x03", 2, 20, frame, 10000, false, true, undefined);
2727
+ let error;
2728
+ try {
2729
+ await response;
2730
+ } catch (e) {
2731
+ error = e;
2732
+ }
2733
+
2734
+ expect(error.message).toStrictEqual("Data request failed with error: 'MAC_NO_ACK' (0xe9)");
2735
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2736
+ });
2737
+
2738
+ it("Send zcl frame network address fails because requested profileId is not configured", async () => {
2739
+ basicMocks();
2740
+ await adapter.start();
2741
+
2742
+ mockZnpRequest.mockClear();
2743
+ mockQueueExecute.mockClear();
2744
+ const frame = Zcl.Frame.create(
2745
+ Zcl.FrameType.GLOBAL,
2746
+ Zcl.Direction.CLIENT_TO_SERVER,
2747
+ true,
2748
+ undefined,
2749
+ 100,
2750
+ "writeNoRsp",
2751
+ 0,
2752
+ [{attrId: 0, dataType: 0, attrData: null}],
2753
+ {},
2754
+ );
2755
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false, undefined, 9999);
2756
+ let error;
2757
+ try {
2758
+ await response;
2759
+ } catch (e) {
2760
+ error = e;
2761
+ }
2762
+
2763
+ expect(error.message).toStrictEqual("Profile ID 9999 is not supported by this adapter.");
2764
+ });
2765
+
2766
+ it("Source Endpoint is selected based on profileId", async () => {
2767
+ basicMocks();
2768
+ await adapter.start();
2769
+
2770
+ mockZnpRequest.mockClear();
2771
+ mockQueueExecute.mockClear();
2772
+ const frame = Zcl.Frame.create(
2773
+ Zcl.FrameType.GLOBAL,
2774
+ Zcl.Direction.CLIENT_TO_SERVER,
2775
+ true,
2776
+ undefined,
2777
+ 100,
2778
+ "writeNoRsp",
2779
+ 0,
2780
+ [{attrId: 0, dataType: 0, attrData: null}],
2781
+ {},
2782
+ );
2783
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false, undefined, 0x0109);
2784
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2785
+ 4,
2786
+ "dataRequest",
2787
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 6, transid: 1},
2788
+ 99,
2789
+ );
2790
+ });
2791
+
2792
+ it("Send zcl frame network address should retry on dataconfirm timeout", async () => {
2793
+ basicMocks();
2794
+ await adapter.start();
2795
+ dataConfirmCode = 9999;
2796
+ dataConfirmCodeReset = true;
2797
+ mockZnpRequest.mockClear();
2798
+ mockQueueExecute.mockClear();
2799
+ const frame = Zcl.Frame.create(
2800
+ Zcl.FrameType.GLOBAL,
2801
+ Zcl.Direction.CLIENT_TO_SERVER,
2802
+ true,
2803
+ undefined,
2804
+ 100,
2805
+ "writeNoRsp",
2806
+ 0,
2807
+ [{attrId: 0, dataType: 0, attrData: null}],
2808
+ {},
2809
+ );
2810
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
2811
+ let error;
2812
+ try {
2813
+ await response;
2814
+ } catch (e) {
2815
+ error = e;
2816
+ }
2817
+ expect(error.message).toStrictEqual("Data request failed with error: 'TIMEOUT'");
2818
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2819
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
2820
+ 1,
2821
+ 4,
2822
+ "dataRequest",
2823
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 6, options: 0, radius: 30, srcendpoint: 1, transid: 1},
2824
+ 99,
2825
+ );
2826
+ });
2827
+
2828
+ it("Send zcl frame group", async () => {
2829
+ basicMocks();
2830
+ await adapter.start();
2831
+
2832
+ mockZnpRequest.mockClear();
2833
+ mockQueueExecute.mockClear();
2834
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
2835
+ await adapter.sendZclFrameToGroup(25, frame, 1);
2836
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
2837
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2838
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2839
+ 4,
2840
+ "dataRequestExt",
2841
+ {
2842
+ clusterid: 0,
2843
+ data: frame.toBuffer(),
2844
+ destendpoint: 255,
2845
+ dstaddr: "0x0000000000000019",
2846
+ len: 5,
2847
+ options: 0,
2848
+ radius: 30,
2849
+ srcendpoint: 1,
2850
+ transid: 1,
2851
+ dstaddrmode: 1,
2852
+ dstpanid: 0,
2853
+ },
2854
+ 99,
2855
+ );
2856
+ });
2857
+
2858
+ it("Send zcl frame group retry on MAC channel access failure", async () => {
2859
+ basicMocks();
2860
+ dataConfirmCode = 225;
2861
+ dataConfirmCodeReset = true;
2862
+ await adapter.start();
2863
+ mockZnpRequest.mockClear();
2864
+ mockQueueExecute.mockClear();
2865
+ const frame = Zcl.Frame.create(
2866
+ Zcl.FrameType.GLOBAL,
2867
+ Zcl.Direction.CLIENT_TO_SERVER,
2868
+ false,
2869
+ undefined,
2870
+ 100,
2871
+ "writeNoRsp",
2872
+ 0,
2873
+ [{attrId: 0, dataType: 0, attrData: null}],
2874
+ {},
2875
+ );
2876
+ await adapter.sendZclFrameToGroup(25, frame, 1);
2877
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
2878
+ expect(mockZnpRequest).toHaveBeenCalledTimes(2);
2879
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2880
+ 4,
2881
+ "dataRequestExt",
2882
+ {
2883
+ clusterid: 0,
2884
+ data: frame.toBuffer(),
2885
+ destendpoint: 255,
2886
+ dstaddr: "0x0000000000000019",
2887
+ len: 6,
2888
+ options: 0,
2889
+ radius: 30,
2890
+ srcendpoint: 1,
2891
+ transid: 1,
2892
+ dstaddrmode: 1,
2893
+ dstpanid: 0,
2894
+ },
2895
+ 99,
2896
+ );
2897
+ });
2898
+
2899
+ it("Send zcl frame to all - DEFAULT", async () => {
2900
+ basicMocks();
2901
+ await adapter.start();
2902
+
2903
+ mockZnpRequest.mockClear();
2904
+ mockQueueExecute.mockClear();
2905
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
2906
+ await adapter.sendZclFrameToAll(242, frame, 250, BroadcastAddress.DEFAULT);
2907
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
2908
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2909
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2910
+ 4,
2911
+ "dataRequestExt",
2912
+ {
2913
+ clusterid: 0,
2914
+ data: frame.toBuffer(),
2915
+ destendpoint: 242,
2916
+ dstaddr: "0x000000000000fffc",
2917
+ len: 5,
2918
+ options: 0,
2919
+ radius: 30,
2920
+ srcendpoint: 250,
2921
+ transid: 1,
2922
+ dstaddrmode: 2,
2923
+ dstpanid: 0,
2924
+ },
2925
+ undefined,
2926
+ );
2927
+ });
2928
+
2929
+ it("Send zcl frame to all - RX_ON_WHEN_IDLE", async () => {
2930
+ basicMocks();
2931
+ await adapter.start();
2932
+
2933
+ mockZnpRequest.mockClear();
2934
+ mockQueueExecute.mockClear();
2935
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
2936
+ await adapter.sendZclFrameToAll(255, frame, 1, BroadcastAddress.RX_ON_WHEN_IDLE);
2937
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
2938
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2939
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2940
+ 4,
2941
+ "dataRequestExt",
2942
+ {
2943
+ clusterid: 0,
2944
+ data: frame.toBuffer(),
2945
+ destendpoint: 255,
2946
+ dstaddr: "0x000000000000fffd",
2947
+ len: 5,
2948
+ options: 0,
2949
+ radius: 30,
2950
+ srcendpoint: 1,
2951
+ transid: 1,
2952
+ dstaddrmode: 2,
2953
+ dstpanid: 0,
2954
+ },
2955
+ undefined,
2956
+ );
2957
+ });
2958
+
2959
+ it("Send zcl frame to all - SLEEPY", async () => {
2960
+ basicMocks();
2961
+ await adapter.start();
2962
+
2963
+ mockZnpRequest.mockClear();
2964
+ mockQueueExecute.mockClear();
2965
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
2966
+ await adapter.sendZclFrameToAll(255, frame, 1, BroadcastAddress.SLEEPY);
2967
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
2968
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
2969
+ expect(mockZnpRequest).toHaveBeenCalledWith(
2970
+ 4,
2971
+ "dataRequestExt",
2972
+ {
2973
+ clusterid: 0,
2974
+ data: frame.toBuffer(),
2975
+ destendpoint: 255,
2976
+ dstaddr: "0x000000000000ffff",
2977
+ len: 5,
2978
+ options: 0,
2979
+ radius: 30,
2980
+ srcendpoint: 1,
2981
+ transid: 1,
2982
+ dstaddrmode: 2,
2983
+ dstpanid: 0,
2984
+ },
2985
+ undefined,
2986
+ );
2987
+ });
2988
+
2989
+ it("Send zcl frame network address transaction number shouldnt go higher than 255", async () => {
2990
+ basicMocks();
2991
+ await adapter.start();
2992
+ let transactionID = 0;
2993
+
2994
+ mockZnpRequest.mockClear();
2995
+ mockQueueExecute.mockClear();
2996
+
2997
+ for (let i = 0; i < 300; i++) {
2998
+ if (transactionID > 200) {
2999
+ transactionID = 0;
3000
+ }
3001
+
3002
+ const frame = Zcl.Frame.create(
3003
+ Zcl.FrameType.GLOBAL,
3004
+ Zcl.Direction.CLIENT_TO_SERVER,
3005
+ true,
3006
+ undefined,
3007
+ 100,
3008
+ "writeNoRsp",
3009
+ 0,
3010
+ [{attrId: 0, dataType: 0, attrData: null}],
3011
+ {},
3012
+ );
3013
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3014
+ }
3015
+
3016
+ const got: number[] = [];
3017
+ for (let i = 0; i < 300; i++) {
3018
+ got.push(mockZnpRequest.mock.calls[i][2].transid);
3019
+ }
3020
+
3021
+ expect(got[0]).toBe(1);
3022
+ expect(got.find((g) => g === 0)).toBe(undefined);
3023
+ expect(got.find((g) => g > 255)).toBe(undefined);
3024
+ expect(got.filter((g) => g === 1).length).toBe(2);
3025
+ expect(got.filter((g) => g === 255).length).toBe(1);
3026
+ expect(mockZnpRequest).toHaveBeenCalledTimes(300);
3027
+ });
3028
+
3029
+ it("Send zcl frame group dataConfirm fails", async () => {
3030
+ basicMocks();
3031
+ await adapter.start();
3032
+ dataConfirmCode = 184;
3033
+ let error;
3034
+ mockZnpRequest.mockClear();
3035
+ mockQueueExecute.mockClear();
3036
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
3037
+ try {
3038
+ await adapter.sendZclFrameToGroup(25, frame);
3039
+ } catch (e) {
3040
+ error = e;
3041
+ }
3042
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(undefined);
3043
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3044
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3045
+ 4,
3046
+ "dataRequestExt",
3047
+ {
3048
+ clusterid: 0,
3049
+ data: frame.toBuffer(),
3050
+ destendpoint: 255,
3051
+ dstaddr: "0x0000000000000019",
3052
+ len: 5,
3053
+ options: 0,
3054
+ radius: 30,
3055
+ srcendpoint: 1,
3056
+ transid: 1,
3057
+ dstaddrmode: 1,
3058
+ dstpanid: 0,
3059
+ },
3060
+ 99,
3061
+ );
3062
+ expect(error.message).toStrictEqual("Data request failed with error: 'APS_DUPLICATE_ENTRY' (0xb8)");
3063
+ });
3064
+
3065
+ it("Send zcl frame network address and default response", async () => {
3066
+ basicMocks();
3067
+ await adapter.start();
3068
+
3069
+ mockZnpRequest.mockClear();
3070
+ mockQueueExecute.mockClear();
3071
+
3072
+ const responseMismatchFrame = Zcl.Frame.create(
3073
+ Zcl.FrameType.GLOBAL,
3074
+ Zcl.Direction.SERVER_TO_CLIENT,
3075
+ true,
3076
+ undefined,
3077
+ 102,
3078
+ "readRsp",
3079
+ 0,
3080
+ [{attrId: 0, attrData: 5, dataType: 32, status: 0}],
3081
+ {},
3082
+ );
3083
+ const responseFrame = Zcl.Frame.create(
3084
+ Zcl.FrameType.GLOBAL,
3085
+ Zcl.Direction.SERVER_TO_CLIENT,
3086
+ true,
3087
+ undefined,
3088
+ 100,
3089
+ "readRsp",
3090
+ 0,
3091
+ [{attrId: 0, attrData: 2, dataType: 32, status: 0}],
3092
+ {},
3093
+ );
3094
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
3095
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3096
+ clusterid: 0,
3097
+ srcendpoint: 20,
3098
+ srcaddr: 2,
3099
+ linkquality: 101,
3100
+ groupid: 12,
3101
+ data: responseFrame.toBuffer(),
3102
+ });
3103
+ const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3104
+ clusterid: 0,
3105
+ srcendpoint: 20,
3106
+ srcaddr: 2,
3107
+ linkquality: 101,
3108
+ groupid: 12,
3109
+ data: responseMismatchFrame.toBuffer(),
3110
+ });
3111
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3112
+ znpReceived(objectMismatch);
3113
+ znpReceived(object);
3114
+ const result = await response;
3115
+
3116
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3117
+ 4,
3118
+ "dataRequest",
3119
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
3120
+ 99,
3121
+ );
3122
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
3123
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3124
+ expect(result.endpoint).toStrictEqual(20);
3125
+ expect(result.groupID).toStrictEqual(12);
3126
+ expect(result.linkquality).toStrictEqual(101);
3127
+ expect(result.address).toStrictEqual(2);
3128
+ expect(result.groupID).toStrictEqual(12);
3129
+ expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
3130
+ });
3131
+
3132
+ it("Send zcl frame network address and default response", async () => {
3133
+ basicMocks();
3134
+ await adapter.start();
3135
+
3136
+ mockZnpRequest.mockClear();
3137
+ mockQueueExecute.mockClear();
3138
+
3139
+ const responseMismatchFrame = Zcl.Frame.create(
3140
+ Zcl.FrameType.GLOBAL,
3141
+ Zcl.Direction.SERVER_TO_CLIENT,
3142
+ true,
3143
+ undefined,
3144
+ 102,
3145
+ "readRsp",
3146
+ 0,
3147
+ [{attrId: 0, attrData: 5, dataType: 32, status: 0}],
3148
+ {},
3149
+ );
3150
+ const responseFrame = Zcl.Frame.create(
3151
+ Zcl.FrameType.GLOBAL,
3152
+ Zcl.Direction.SERVER_TO_CLIENT,
3153
+ true,
3154
+ undefined,
3155
+ 100,
3156
+ "readRsp",
3157
+ 0,
3158
+ [{attrId: 0, attrData: 2, dataType: 32, status: 0}],
3159
+ {},
3160
+ );
3161
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
3162
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3163
+ clusterid: 0,
3164
+ srcendpoint: 20,
3165
+ srcaddr: 2,
3166
+ linkquality: 101,
3167
+ groupid: 12,
3168
+ data: responseFrame.toBuffer(),
3169
+ });
3170
+ const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3171
+ clusterid: 0,
3172
+ srcendpoint: 20,
3173
+ srcaddr: 2,
3174
+ linkquality: 101,
3175
+ groupid: 12,
3176
+ data: responseMismatchFrame.toBuffer(),
3177
+ });
3178
+ const defaultReponse = Zcl.Frame.create(
3179
+ Zcl.FrameType.GLOBAL,
3180
+ Zcl.Direction.SERVER_TO_CLIENT,
3181
+ true,
3182
+ undefined,
3183
+ 100,
3184
+ "defaultRsp",
3185
+ 0,
3186
+ {cmdId: 0, status: 0},
3187
+ {},
3188
+ );
3189
+ const defaultObject = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3190
+ clusterid: 0,
3191
+ srcendpoint: 20,
3192
+ srcaddr: 2,
3193
+ linkquality: 101,
3194
+ groupid: 12,
3195
+ data: defaultReponse.toBuffer(),
3196
+ });
3197
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3198
+ znpReceived(objectMismatch);
3199
+ znpReceived(defaultObject);
3200
+ znpReceived(object);
3201
+ const result = await response;
3202
+
3203
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3204
+ 4,
3205
+ "dataRequest",
3206
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
3207
+ 99,
3208
+ );
3209
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
3210
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3211
+ expect(result.endpoint).toStrictEqual(20);
3212
+ expect(result.groupID).toStrictEqual(12);
3213
+ expect(result.linkquality).toStrictEqual(101);
3214
+ expect(result.address).toStrictEqual(2);
3215
+ expect(result.groupID).toStrictEqual(12);
3216
+ expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
3217
+ });
3218
+
3219
+ it("Send zcl frame network address data confirm fails with default response", async () => {
3220
+ basicMocks();
3221
+ await adapter.start();
3222
+ dataConfirmCode = 201;
3223
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
3224
+ let error;
3225
+ try {
3226
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3227
+ } catch (e) {
3228
+ error = e;
3229
+ }
3230
+ expect(error.message).toStrictEqual("Data request failed with error: 'NWK_UNSUPPORTED_ATTRIBUTE' (0xc9)");
3231
+ });
3232
+
3233
+ it("Send zcl frame network address data confirm fails without default response", async () => {
3234
+ basicMocks();
3235
+ await adapter.start();
3236
+ dataConfirmCode = 201;
3237
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, true, undefined, 100, "read", 0, [{attrId: 0}], {});
3238
+ let error;
3239
+ try {
3240
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3241
+ } catch (e) {
3242
+ error = e;
3243
+ }
3244
+ expect(error.message).toStrictEqual("Data request failed with error: 'NWK_UNSUPPORTED_ATTRIBUTE' (0xc9)");
3245
+ });
3246
+
3247
+ it("Send zcl frame network address timeout should discover route and retry", async () => {
3248
+ basicMocks();
3249
+ await adapter.start();
3250
+
3251
+ mockZnpRequest.mockClear();
3252
+ mockQueueExecute.mockClear();
3253
+ assocGetWithAddressNodeRelation = 2;
3254
+ const responseMismatchFrame = Zcl.Frame.create(
3255
+ Zcl.FrameType.GLOBAL,
3256
+ Zcl.Direction.SERVER_TO_CLIENT,
3257
+ true,
3258
+ undefined,
3259
+ 102,
3260
+ "readRsp",
3261
+ 0,
3262
+ [{attrId: 0, attrData: 5, dataType: 32, status: 0}],
3263
+ {},
3264
+ );
3265
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
3266
+ const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3267
+ clusterid: 0,
3268
+ srcendpoint: 20,
3269
+ srcaddr: 2,
3270
+ linkquality: 101,
3271
+ groupid: 12,
3272
+ data: responseMismatchFrame.toBuffer(),
3273
+ });
3274
+ let error;
3275
+ try {
3276
+ const spy = mockSetTimeout();
3277
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 1, false, false);
3278
+ znpReceived(objectMismatch);
3279
+ await response;
3280
+ spy.mockRestore();
3281
+ } catch (e) {
3282
+ error = e;
3283
+ }
3284
+
3285
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
3286
+ expect(mockZnpRequest).toHaveBeenCalledTimes(4);
3287
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
3288
+ 1,
3289
+ 4,
3290
+ "dataRequest",
3291
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
3292
+ 99,
3293
+ );
3294
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(2, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
3295
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: Constants.AF.DEFAULT_RADIUS});
3296
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
3297
+ 4,
3298
+ 4,
3299
+ "dataRequest",
3300
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 2},
3301
+ 99,
3302
+ );
3303
+ expect(error).toStrictEqual(new Error("Timeout - 2 - 20 - 100 - 0 - 1 after 1ms"));
3304
+ });
3305
+
3306
+ it("Send zcl frame network address timeout should discover route, rewrite child entry and retry for sleepy end device", async () => {
3307
+ basicMocks();
3308
+ await adapter.start();
3309
+
3310
+ mockZnpRequest.mockClear();
3311
+ mockQueueExecute.mockClear();
3312
+
3313
+ const responseMismatchFrame = Zcl.Frame.create(
3314
+ Zcl.FrameType.GLOBAL,
3315
+ Zcl.Direction.SERVER_TO_CLIENT,
3316
+ true,
3317
+ undefined,
3318
+ 102,
3319
+ "readRsp",
3320
+ 0,
3321
+ [{attrId: 0, attrData: 5, dataType: 32, status: 0}],
3322
+ {},
3323
+ );
3324
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
3325
+ const objectMismatch = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3326
+ clusterid: 0,
3327
+ srcendpoint: 20,
3328
+ srcaddr: 2,
3329
+ linkquality: 101,
3330
+ groupid: 12,
3331
+ data: responseMismatchFrame.toBuffer(),
3332
+ });
3333
+ let error;
3334
+ try {
3335
+ const spy = mockSetTimeout();
3336
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 1, false, false);
3337
+ znpReceived(objectMismatch);
3338
+ await response;
3339
+ spy.mockRestore();
3340
+ } catch (e) {
3341
+ error = e;
3342
+ }
3343
+
3344
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
3345
+ expect(mockZnpRequest).toHaveBeenCalledTimes(6);
3346
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
3347
+ 1,
3348
+ 4,
3349
+ "dataRequest",
3350
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
3351
+ 99,
3352
+ );
3353
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(2, 7, "assocGetWithAddress", {extaddr: "0x02", nwkaddr: 2});
3354
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(3, 7, "assocRemove", {ieeeadr: "0x02"});
3355
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(4, 7, "assocAdd", {ieeeadr: "0x02", nwkaddr: 2, noderelation: 1});
3356
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(5, 5, "extRouteDisc", {dstAddr: 2, options: 0, radius: Constants.AF.DEFAULT_RADIUS});
3357
+ expect(mockZnpRequest).toHaveBeenNthCalledWith(
3358
+ 6,
3359
+ 4,
3360
+ "dataRequest",
3361
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 2},
3362
+ 99,
3363
+ );
3364
+ expect(error).toStrictEqual(new Error("Timeout - 2 - 20 - 100 - 0 - 1 after 1ms"));
3365
+ });
3366
+
3367
+ it("Send zcl frame network address with default response timeout shouldnt care because command has response", async () => {
3368
+ basicMocks();
3369
+ await adapter.start();
3370
+
3371
+ mockZnpRequest.mockClear();
3372
+ mockQueueExecute.mockClear();
3373
+ const responseFrame = Zcl.Frame.create(
3374
+ Zcl.FrameType.GLOBAL,
3375
+ Zcl.Direction.SERVER_TO_CLIENT,
3376
+ true,
3377
+ undefined,
3378
+ 100,
3379
+ "readRsp",
3380
+ 0,
3381
+ [{attrId: 0, attrData: 2, dataType: 32, status: 0}],
3382
+ {},
3383
+ );
3384
+ const frame = Zcl.Frame.create(Zcl.FrameType.GLOBAL, Zcl.Direction.CLIENT_TO_SERVER, false, undefined, 100, "read", 0, [{attrId: 0}], {});
3385
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3386
+ clusterid: 0,
3387
+ srcendpoint: 20,
3388
+ srcaddr: 2,
3389
+ linkquality: 101,
3390
+ groupid: 12,
3391
+ data: responseFrame.toBuffer(),
3392
+ });
3393
+ const response = adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
3394
+ znpReceived(object);
3395
+
3396
+ let error = null;
3397
+ try {
3398
+ await response;
3399
+ } catch (e) {
3400
+ error = e;
3401
+ }
3402
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3403
+ 4,
3404
+ "dataRequest",
3405
+ {clusterid: 0, data: frame.toBuffer(), destendpoint: 20, dstaddr: 2, len: 5, options: 0, radius: 30, srcendpoint: 1, transid: 1},
3406
+ 99,
3407
+ );
3408
+ expect(mockQueueExecute.mock.calls[0][1]).toBe(2);
3409
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3410
+ expect(error).toStrictEqual(null);
3411
+ });
3412
+
3413
+ it("Supports backup", async () => {
3414
+ basicMocks();
3415
+ await adapter.start();
3416
+ expect(await adapter.supportsBackup()).toBeTruthy();
3417
+ });
3418
+
3419
+ it.each([
3420
+ [2, "0x1234567812345678", 0x5678],
3421
+ [3, "0x1234567812345678", "0x1234567812345678"],
3422
+ ])("Incoming message extended (inter PAN) - 16/64-bit address", async (srcAddrMode, addr, expParsedAddr) => {
3423
+ basicMocks();
3424
+ await adapter.start();
3425
+ let zclData;
3426
+ const responseFrame = Zcl.Frame.create(
3427
+ Zcl.FrameType.GLOBAL,
3428
+ Zcl.Direction.SERVER_TO_CLIENT,
3429
+ true,
3430
+ undefined,
3431
+ 100,
3432
+ "readRsp",
3433
+ 0,
3434
+ [{attrId: 0, attrData: 2, dataType: 32, status: 0}],
3435
+ {},
3436
+ );
3437
+ const responseBuffer = responseFrame.toBuffer();
3438
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
3439
+ groupid: 12,
3440
+ clusterid: 0,
3441
+ srcaddrmode: srcAddrMode,
3442
+ srcaddr: addr,
3443
+ srcendpoint: 20,
3444
+ //srcpanid
3445
+ dstendpoint: 1,
3446
+ //wasbroadcast
3447
+ linkquality: 101,
3448
+ //securityuse
3449
+ timestamp: 0x12345678,
3450
+ //transseqnumber
3451
+ len: responseBuffer.length,
3452
+ data: responseBuffer,
3453
+ });
3454
+ adapter.on("zclPayload", (p) => {
3455
+ zclData = p;
3456
+ });
3457
+ znpReceived(object);
3458
+ expect(zclData.endpoint).toStrictEqual(20);
3459
+ expect(zclData.groupID).toStrictEqual(12);
3460
+ expect(zclData.linkquality).toStrictEqual(101);
3461
+ expect(zclData.address).toStrictEqual(expParsedAddr);
3462
+ expect(zclData.groupID).toStrictEqual(12);
3463
+ expect(zclData.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
3464
+ expect(zclData.header.commandIdentifier).toBe(1);
3465
+ });
3466
+
3467
+ it.each([
3468
+ [2, "0x1234567812345678", 0x5678],
3469
+ [3, "0x1234567812345678", "0x1234567812345678"],
3470
+ ])("Incoming message extended (huge data byte count) - 16/64-bit address", async (srcAddrMode, addr, expParsedAddr) => {
3471
+ mockZnpRequestWith(incomingMsgExtHugeDataReqMock);
3472
+
3473
+ await adapter.start();
3474
+
3475
+ const responseFrame = Zcl.Frame.create(
3476
+ Zcl.FrameType.GLOBAL,
3477
+ Zcl.Direction.SERVER_TO_CLIENT,
3478
+ true,
3479
+ undefined,
3480
+ 100,
3481
+ "readRsp",
3482
+ 0,
3483
+ [
3484
+ {
3485
+ attrId: 0x1234,
3486
+ attrData: "", // can't put long string here - added below
3487
+ dataType: 0x44, // Long char string
3488
+ status: 0,
3489
+ },
3490
+ ],
3491
+ {},
3492
+ );
3493
+
3494
+ // Construct response frame manually as we exceed
3495
+ // the 250-byte limit of Zcl.Frame.toBuffer
3496
+
3497
+ const rspFrameBuf = responseFrame.toBuffer();
3498
+
3499
+ const zclLongString = Buffer.alloc(STR_500_BYTES.length + 2);
3500
+ zclLongString.writeUint16LE(Buffer.byteLength(STR_500_BYTES, "utf8"));
3501
+ zclLongString.write(STR_500_BYTES, 2, "utf8");
3502
+
3503
+ const response = Buffer.concat([
3504
+ rspFrameBuf.subarray(0, rspFrameBuf.length - 2), // remove existing ZCL long string len
3505
+ zclLongString,
3506
+ ]);
3507
+
3508
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
3509
+ groupid: 12,
3510
+ clusterid: 0,
3511
+ srcaddrmode: srcAddrMode,
3512
+ srcaddr: addr,
3513
+ srcendpoint: 20,
3514
+ //srcpanid
3515
+ dstendpoint: 1,
3516
+ //wasbroadcast
3517
+ linkquality: 101,
3518
+ //securityuse
3519
+ timestamp: 0x12345678,
3520
+ //transseqnumber
3521
+ len: response.length,
3522
+ data: Buffer.alloc(0),
3523
+ });
3524
+
3525
+ let resolveReceivedPayload: () => void;
3526
+ const receivedPayload = new Promise((resolve) => {
3527
+ resolveReceivedPayload = resolve;
3528
+ });
3529
+ let zclData;
3530
+ adapter.on("zclPayload", (p) => {
3531
+ zclData = p;
3532
+ resolveReceivedPayload();
3533
+ });
3534
+
3535
+ mockIncomingMsgExtSetHugeData(object.payload.timestamp, response);
3536
+ znpReceived(object);
3537
+
3538
+ await receivedPayload;
3539
+ expect(zclData.endpoint).toStrictEqual(20);
3540
+ expect(zclData.groupID).toStrictEqual(12);
3541
+ expect(zclData.linkquality).toStrictEqual(101);
3542
+ expect(zclData.address).toStrictEqual(expParsedAddr);
3543
+ expect(zclData.groupID).toStrictEqual(12);
3544
+ expect(zclData.data).toStrictEqual(
3545
+ Buffer.concat([
3546
+ Buffer.from([
3547
+ 24, // frame ctrl
3548
+ 100, // transseq
3549
+ 1, // read attr rsp
3550
+ 0x34, // attr id lsb
3551
+ 0x12, // attr id msb
3552
+ 0, // status
3553
+ 0x44, // data type
3554
+ ]),
3555
+ zclLongString, // 16-bit len + char data
3556
+ ]),
3557
+ );
3558
+ expect(zclData.header.commandIdentifier).toBe(1);
3559
+ });
3560
+
3561
+ it.each([
3562
+ [1, `dataRetrieve [timestamp: ${0x12345678}, index: ${0}, chunkSize: ${240}] error status: ${0x01}`],
3563
+ [2, `dataRetrieve length mismatch [${240} requested, ${240 + 1} returned`],
3564
+ ])("Incoming message extended (huge data byte count) with dataRetrieve error", async (mockErrType, expErrMsg) => {
3565
+ mockZnpRequestWith(incomingMsgExtHugeDataReqMock);
3566
+
3567
+ await adapter.start();
3568
+
3569
+ const responseFrame = Zcl.Frame.create(
3570
+ Zcl.FrameType.GLOBAL,
3571
+ Zcl.Direction.SERVER_TO_CLIENT,
3572
+ true,
3573
+ undefined,
3574
+ 100,
3575
+ "readRsp",
3576
+ 0,
3577
+ [
3578
+ {
3579
+ attrId: 0x1234,
3580
+ attrData: "", // can't put long string here - added below
3581
+ dataType: 0x44, // Long char string
3582
+ status: 0,
3583
+ },
3584
+ ],
3585
+ {},
3586
+ );
3587
+
3588
+ // Construct response frame manually as we exceed
3589
+ // the 250-byte limit of Zcl.Frame.toBuffer
3590
+
3591
+ const rspFrameBuf = responseFrame.toBuffer();
3592
+
3593
+ const zclLongString = Buffer.alloc(STR_500_BYTES.length + 2);
3594
+ zclLongString.writeUint16LE(Buffer.byteLength(STR_500_BYTES, "utf8"));
3595
+ zclLongString.write(STR_500_BYTES, 2, "utf8");
3596
+
3597
+ const response = Buffer.concat([
3598
+ rspFrameBuf.subarray(0, rspFrameBuf.length - 2), // remove existing ZCL long string len
3599
+ zclLongString,
3600
+ ]);
3601
+
3602
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
3603
+ groupid: 12,
3604
+ clusterid: 0,
3605
+ srcaddrmode: 2,
3606
+ srcaddr: "0x1234567812345678",
3607
+ srcendpoint: 20,
3608
+ //srcpanid
3609
+ dstendpoint: 1,
3610
+ //wasbroadcast
3611
+ linkquality: 101,
3612
+ //securityuse
3613
+ timestamp: 0x12345678,
3614
+ //transseqnumber
3615
+ len: response.length,
3616
+ data: Buffer.alloc(0),
3617
+ });
3618
+
3619
+ mockIncomingMsgExtSetHugeData(object.payload.timestamp, response, mockErrType);
3620
+ await znpReceived(object);
3621
+
3622
+ expect(mockLogger.error.mock.calls[0][0]).toBe(expErrMsg);
3623
+ // not captured by mock logger
3624
+ //expect(mockLogger.error.mock.calls[1][0]).toBe("Failed to retrieve chunked payload for incomingMsgExt");
3625
+ });
3626
+
3627
+ it("Incoming message raw (not ZCL)", async () => {
3628
+ basicMocks();
3629
+ await adapter.start();
3630
+ let rawData;
3631
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3632
+ clusterid: 1,
3633
+ srcendpoint: 20,
3634
+ srcaddr: 2,
3635
+ linkquality: 101,
3636
+ groupid: 12,
3637
+ data: Buffer.from([0x0, 0x1]),
3638
+ });
3639
+ adapter.on("zclPayload", (p) => {
3640
+ rawData = p;
3641
+ });
3642
+ znpReceived(object);
3643
+ expect(rawData.clusterID).toStrictEqual(1);
3644
+ expect(rawData.endpoint).toStrictEqual(20);
3645
+ expect(rawData.groupID).toStrictEqual(12);
3646
+ expect(rawData.linkquality).toStrictEqual(101);
3647
+ expect(rawData.address).toStrictEqual(2);
3648
+ expect(rawData.data).toStrictEqual(Buffer.from([0x0, 0x01]));
3649
+ });
3650
+
3651
+ it("Adapter disconnected", async () => {
3652
+ basicMocks();
3653
+ await adapter.start();
3654
+ let closeEvent = false;
3655
+ adapter.on("disconnected", () => {
3656
+ closeEvent = true;
3657
+ });
3658
+ znpClose();
3659
+ expect(closeEvent).toBeTruthy();
3660
+ });
3661
+
3662
+ it("Adapter disconnected dont emit when closing", async () => {
3663
+ basicMocks();
3664
+ await adapter.start();
3665
+ await adapter.stop();
3666
+ let closeEvent = false;
3667
+ adapter.on("disconnected", () => {
3668
+ closeEvent = true;
3669
+ });
3670
+ znpClose();
3671
+ expect(closeEvent).toBeFalsy();
3672
+ });
3673
+
3674
+ it("Device joined", async () => {
3675
+ basicMocks();
3676
+ await adapter.start();
3677
+ let deviceJoin;
3678
+ const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "tcDeviceInd", {nwkaddr: 123, extaddr: "0x123"});
3679
+ adapter.on("deviceJoined", (p) => {
3680
+ deviceJoin = p;
3681
+ });
3682
+ znpReceived(object);
3683
+ expect(deviceJoin).toStrictEqual({ieeeAddr: "0x123", networkAddress: 123});
3684
+ });
3685
+
3686
+ it("Device announce", async () => {
3687
+ basicMocks();
3688
+ await adapter.start();
3689
+ mockZnpRequest.mockClear();
3690
+ mockQueueExecute.mockClear();
3691
+ const object = mockZdoZpiObject<EndDeviceAnnounce>("endDeviceAnnceInd", 123, [
3692
+ Zdo.Status.SUCCESS,
3693
+ {
3694
+ capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES,
3695
+ eui64: "0x123",
3696
+ nwkAddress: 123,
3697
+ },
3698
+ ]);
3699
+ adapter.on("zdoResponse", (clusterId, payload) => {
3700
+ expect(clusterId).toStrictEqual(Zdo.ClusterId.END_DEVICE_ANNOUNCE);
3701
+ expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
3702
+ expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 123, capabilities: DUMMY_NODE_DESC_RSP_CAPABILITIES});
3703
+ });
3704
+ znpReceived(object);
3705
+ expect(mockZnpRequest).toHaveBeenCalledTimes(0);
3706
+ });
3707
+
3708
+ it("Device announce should discover route to end devices", async () => {
3709
+ basicMocks();
3710
+ await adapter.start();
3711
+ mockZnpRequest.mockClear();
3712
+ mockQueueExecute.mockClear();
3713
+ const object = mockZdoZpiObject<EndDeviceAnnounce>("endDeviceAnnceInd", 123, [
3714
+ Zdo.Status.SUCCESS,
3715
+ {
3716
+ capabilities: {...DUMMY_NODE_DESC_RSP_CAPABILITIES, deviceType: 0},
3717
+ eui64: "0x123",
3718
+ nwkAddress: 123,
3719
+ },
3720
+ ]);
3721
+ adapter.on("zdoResponse", (clusterId, payload) => {
3722
+ expect(clusterId).toStrictEqual(Zdo.ClusterId.END_DEVICE_ANNOUNCE);
3723
+ expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
3724
+ expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 123, capabilities: {...DUMMY_NODE_DESC_RSP_CAPABILITIES, deviceType: 0}});
3725
+ });
3726
+ znpReceived(object);
3727
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3728
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 123, options: 0, radius: 30});
3729
+
3730
+ // Should debounce route discovery.
3731
+ znpReceived(object);
3732
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3733
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 123, options: 0, radius: 30});
3734
+ });
3735
+
3736
+ it("Network address response", async () => {
3737
+ basicMocks();
3738
+ await adapter.start();
3739
+ const object = mockZdoZpiObject<NetworkAddressResponse>("nwkAddrRsp", 124, [
3740
+ Zdo.Status.SUCCESS,
3741
+ {
3742
+ eui64: "0x123",
3743
+ nwkAddress: 124,
3744
+ assocDevList: [],
3745
+ startIndex: 0,
3746
+ },
3747
+ ]);
3748
+ adapter.on("zdoResponse", (clusterId, payload) => {
3749
+ expect(clusterId).toStrictEqual(Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE);
3750
+ expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
3751
+ expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 124, assocDevList: [], startIndex: 0});
3752
+ });
3753
+ znpReceived(object);
3754
+ });
3755
+
3756
+ it("Concentrator Callback Indication", async () => {
3757
+ basicMocks();
3758
+ await adapter.start();
3759
+ const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "concentratorIndCb", {srcaddr: 124, extaddr: "0x123"});
3760
+ adapter.on("zdoResponse", (clusterId, payload) => {
3761
+ expect(clusterId).toStrictEqual(Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE);
3762
+ expect(payload[0]).toStrictEqual(Zdo.Status.SUCCESS);
3763
+ expect(payload[1]).toStrictEqual({eui64: "0x123", nwkAddress: 124, assocDevList: [], startIndex: 0});
3764
+ });
3765
+ znpReceived(object);
3766
+ });
3767
+
3768
+ it("Device leave", async () => {
3769
+ basicMocks();
3770
+ await adapter.start();
3771
+ let deviceAnnounce;
3772
+ const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123"});
3773
+ adapter.on("deviceLeave", (p) => {
3774
+ deviceAnnounce = p;
3775
+ });
3776
+ znpReceived(object);
3777
+ expect(deviceAnnounce).toStrictEqual({ieeeAddr: "0x123", networkAddress: 123});
3778
+ });
3779
+
3780
+ it("Ignore device leave with rejoin", async () => {
3781
+ basicMocks();
3782
+ await adapter.start();
3783
+ let deviceAnnounce;
3784
+ const object = mockZpiObject(Type.AREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123", rejoin: true});
3785
+ adapter.on("deviceLeave", (p) => {
3786
+ deviceAnnounce = p;
3787
+ });
3788
+ znpReceived(object);
3789
+ expect(deviceAnnounce).toStrictEqual(undefined);
3790
+ });
3791
+
3792
+ it("Do nothing wiht non areq event", async () => {
3793
+ basicMocks();
3794
+ await adapter.start();
3795
+ let deviceLeave;
3796
+ const object = mockZpiObject(Type.SREQ, Subsystem.ZDO, "leaveInd", {srcaddr: 123, extaddr: "0x123"});
3797
+ adapter.on("deviceLeave", (p) => {
3798
+ deviceLeave = p;
3799
+ });
3800
+ znpReceived(object);
3801
+ expect(deviceLeave).toStrictEqual(undefined);
3802
+ });
3803
+
3804
+ it("Get network parameters", async () => {
3805
+ basicMocks();
3806
+ await adapter.start();
3807
+ mockZnpRequest.mockClear();
3808
+ mockQueueExecute.mockClear();
3809
+ const result = await adapter.getNetworkParameters();
3810
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3811
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extNwkInfo", {});
3812
+ expect(result).toStrictEqual({channel: 21, extendedPanID: "0x00124b0009d69f77", panID: 123, nwkUpdateID: 0});
3813
+ });
3814
+
3815
+ it("Set interpan channel", async () => {
3816
+ basicMocks();
3817
+ await adapter.start();
3818
+ mockZnpRequest.mockClear();
3819
+ mockQueueExecute.mockClear();
3820
+ await adapter.setChannelInterPAN(14);
3821
+ expect(mockZnpRequest).toHaveBeenCalledTimes(2);
3822
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 1, data: [14]});
3823
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 2, data: [12]});
3824
+
3825
+ mockZnpRequest.mockClear();
3826
+ mockQueueExecute.mockClear();
3827
+ await adapter.setChannelInterPAN(15);
3828
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3829
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 1, data: [15]});
3830
+ });
3831
+
3832
+ it("Restore interpan channel", async () => {
3833
+ basicMocks();
3834
+ await adapter.start();
3835
+ mockZnpRequest.mockClear();
3836
+ mockQueueExecute.mockClear();
3837
+ await adapter.restoreChannelInterPAN();
3838
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3839
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.AF, "interPanCtl", {cmd: 0, data: []});
3840
+ });
3841
+
3842
+ it("Send zcl frame interpan", async () => {
3843
+ basicMocks();
3844
+ await adapter.start();
3845
+ mockZnpRequest.mockClear();
3846
+ mockQueueExecute.mockClear();
3847
+ await adapter.sendZclFrameInterPANToIeeeAddr(touchlinkIdentifyRequest, "0x0017880104c9cd33");
3848
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3849
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3850
+ 4,
3851
+ "dataRequestExt",
3852
+ {
3853
+ clusterid: 4096,
3854
+ data: touchlinkIdentifyRequest.toBuffer(),
3855
+ destendpoint: 254,
3856
+ dstaddr: "0x0017880104c9cd33",
3857
+ len: 9,
3858
+ options: 0,
3859
+ radius: 30,
3860
+ srcendpoint: 12,
3861
+ transid: 1,
3862
+ dstaddrmode: 3,
3863
+ dstpanid: 65535,
3864
+ },
3865
+ undefined,
3866
+ );
3867
+ });
3868
+
3869
+ it("Send zcl frame interpan with response", async () => {
3870
+ basicMocks();
3871
+ await adapter.start();
3872
+ mockZnpRequest.mockClear();
3873
+ mockQueueExecute.mockClear();
3874
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsgExt", {
3875
+ clusterid: 4096,
3876
+ srcendpoint: 0xfe,
3877
+ srcaddr: 12394,
3878
+ linkquality: 101,
3879
+ groupid: 0,
3880
+ data: touchlinkScanResponse.toBuffer(),
3881
+ });
3882
+
3883
+ let result: ZclPayload | Promise<ZclPayload> = adapter.sendZclFrameInterPANBroadcast(touchlinkScanRequest, 1000);
3884
+ znpReceived(object);
3885
+ result = await result;
3886
+
3887
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
3888
+ expect(mockZnpRequest).toHaveBeenCalledWith(
3889
+ 4,
3890
+ "dataRequestExt",
3891
+ {
3892
+ clusterid: 4096,
3893
+ data: touchlinkScanRequest.toBuffer(),
3894
+ destendpoint: 254,
3895
+ dstaddr: "0x000000000000ffff",
3896
+ len: 9,
3897
+ options: 0,
3898
+ radius: 30,
3899
+ srcendpoint: 12,
3900
+ transid: 1,
3901
+ dstaddrmode: 2,
3902
+ dstpanid: 65535,
3903
+ },
3904
+ undefined,
3905
+ );
3906
+ expect(deepClone(result)).toStrictEqual({
3907
+ clusterID: 4096,
3908
+ data: {
3909
+ type: "Buffer",
3910
+ data: [9, 12, 1, 1, 0, 0, 0, 10, 5, 6, 12, 0, 11, 0, 0, 0, 51, 205, 217, 4, 1, 33, 23, 0, 1, 12, 13, 0, 5, 0, 10, 5],
3911
+ },
3912
+ header: {
3913
+ frameControl: {frameType: 1, manufacturerSpecific: false, direction: 1, disableDefaultResponse: false, reservedBits: 0},
3914
+ transactionSequenceNumber: 12,
3915
+ commandIdentifier: 1,
3916
+ },
3917
+ address: 12394,
3918
+ endpoint: 254,
3919
+ linkquality: 101,
3920
+ groupID: 0,
3921
+ wasBroadcast: false,
3922
+ });
3923
+ });
3924
+
3925
+ it("Send zcl frame interpan throw exception when command has no response", async () => {
3926
+ basicMocks();
3927
+ await adapter.start();
3928
+ mockZnpRequest.mockClear();
3929
+ mockQueueExecute.mockClear();
3930
+ let error;
3931
+ try {
3932
+ await adapter.sendZclFrameInterPANBroadcast(touchlinkIdentifyRequest, 1000);
3933
+ } catch (e) {
3934
+ error = e;
3935
+ }
3936
+ expect(error).toStrictEqual(new Error(`Command 'identifyRequest' has no response, cannot wait for response`));
3937
+ });
3938
+
3939
+ it("Send zcl frame interpan throw exception data request fails", async () => {
3940
+ basicMocks();
3941
+ dataRequestExtCode = 99;
3942
+ await adapter.start();
3943
+ mockZnpRequest.mockClear();
3944
+ mockQueueExecute.mockClear();
3945
+ let error;
3946
+ try {
3947
+ await adapter.sendZclFrameInterPANBroadcast(touchlinkScanRequest, 1000);
3948
+ } catch (e) {
3949
+ error = e;
3950
+ }
3951
+ expect(error).toStrictEqual(new Error(`Data request failed with code '99'`));
3952
+ });
3953
+
3954
+ it("Refuse to start when ping fails", async () => {
3955
+ mockZnpRequest.mockImplementation((subsystem, command, payload, _expectedStatus) => {
3956
+ const missing = () => {
3957
+ const msg = `Not implemented - ${Subsystem[subsystem]} - ${command} - ${JSON.stringify(payload)}`;
3958
+ console.log(msg);
3959
+ throw new Error(msg);
3960
+ };
3961
+
3962
+ if (subsystem === Subsystem.SYS && command === "ping") {
3963
+ throw new Error("Couldnt lock port");
3964
+ }
3965
+
3966
+ missing();
3967
+ });
3968
+
3969
+ let error;
3970
+ try {
3971
+ await adapter.start();
3972
+ } catch (e) {
3973
+ error = e;
3974
+ }
3975
+ expect(error).toStrictEqual(new Error("Failed to connect to the adapter (Error: Couldnt lock port)"));
3976
+ });
3977
+
3978
+ it("Wait for", async () => {
3979
+ basicMocks();
3980
+ await adapter.start();
3981
+
3982
+ const responseFrame = Zcl.Frame.create(
3983
+ Zcl.FrameType.GLOBAL,
3984
+ Zcl.Direction.SERVER_TO_CLIENT,
3985
+ true,
3986
+ undefined,
3987
+ 100,
3988
+ "readRsp",
3989
+ 0,
3990
+ [{attrId: 0, attrData: 2, dataType: 32, status: 0}],
3991
+ {},
3992
+ );
3993
+ const object = mockZpiObject(Type.AREQ, Subsystem.AF, "incomingMsg", {
3994
+ clusterid: 0,
3995
+ srcendpoint: 20,
3996
+ srcaddr: 2,
3997
+ linkquality: 101,
3998
+ groupid: 12,
3999
+ data: responseFrame.toBuffer(),
4000
+ });
4001
+ const wait = adapter.waitFor(2, 20, 0, 1, 100, 0, 1, 10);
4002
+ znpReceived(object);
4003
+ const result = await wait.promise;
4004
+ expect(result.endpoint).toStrictEqual(20);
4005
+ expect(result.groupID).toStrictEqual(12);
4006
+ expect(result.linkquality).toStrictEqual(101);
4007
+ expect(result.address).toStrictEqual(2);
4008
+ expect(result.groupID).toStrictEqual(12);
4009
+ expect(result.data).toStrictEqual(Buffer.from([24, 100, 1, 0, 0, 0, 32, 2]));
4010
+ });
4011
+
4012
+ it("Command should fail when in interpan", async () => {
4013
+ const frame = Zcl.Frame.create(
4014
+ Zcl.FrameType.GLOBAL,
4015
+ Zcl.Direction.CLIENT_TO_SERVER,
4016
+ true,
4017
+ undefined,
4018
+ 100,
4019
+ "writeNoRsp",
4020
+ 0,
4021
+ [{attrId: 0, dataType: 0, attrData: null}],
4022
+ {},
4023
+ );
4024
+ basicMocks();
4025
+ await adapter.start();
4026
+
4027
+ await adapter.setChannelInterPAN(14);
4028
+ mockZnpRequest.mockClear();
4029
+ mockQueueExecute.mockClear();
4030
+ let error;
4031
+ try {
4032
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
4033
+ } catch (e) {
4034
+ error = e;
4035
+ }
4036
+ expect(error).toStrictEqual(new Error("Cannot execute command, in Inter-PAN mode"));
4037
+ expect(mockZnpRequest).toHaveBeenCalledTimes(0);
4038
+
4039
+ await adapter.restoreChannelInterPAN();
4040
+ mockZnpRequest.mockClear();
4041
+ mockQueueExecute.mockClear();
4042
+
4043
+ await adapter.sendZclFrameToEndpoint("0x02", 2, 20, frame, 10000, false, false);
4044
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
4045
+ });
4046
+
4047
+ it("Sends proper ZDO request payload for PERMIT_JOINING_REQUEST to target", async () => {
4048
+ basicMocks();
4049
+ await adapter.start();
4050
+ mockZnpRequestZdo.mockClear();
4051
+
4052
+ const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
4053
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 250, 1, []);
4054
+
4055
+ await adapter.sendZdo("0x1122334455667788", 1234, clusterId, zdoPayload, true);
4056
+
4057
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
4058
+ clusterId,
4059
+ Buffer.from([AddressMode.ADDR_16BIT, 1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]),
4060
+ undefined,
4061
+ );
4062
+ });
4063
+
4064
+ it("Sends proper ZDO request payload for PERMIT_JOINING_REQUEST broadcast", async () => {
4065
+ basicMocks();
4066
+ await adapter.start();
4067
+ mockZnpRequestZdo.mockClear();
4068
+
4069
+ const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
4070
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 250, 1, []);
4071
+
4072
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
4073
+
4074
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
4075
+ clusterId,
4076
+ Buffer.from([
4077
+ AddressMode.ADDR_BROADCAST,
4078
+ ZSpec.BroadcastAddress.DEFAULT & 0xff,
4079
+ (ZSpec.BroadcastAddress.DEFAULT >> 8) & 0xff,
4080
+ ...zdoPayload,
4081
+ ]),
4082
+ undefined,
4083
+ );
4084
+ });
4085
+
4086
+ it("Sends proper ZDO request payload for NWK_UPDATE_REQUEST UNICAST", async () => {
4087
+ basicMocks();
4088
+ await adapter.start();
4089
+ mockZnpRequestZdo.mockClear();
4090
+
4091
+ const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
4092
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, [15], 0xfe, 0, undefined, 0);
4093
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 0x123, clusterId, zdoPayload, true);
4094
+
4095
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
4096
+ clusterId,
4097
+ Buffer.from([
4098
+ 0x123 & 0xff,
4099
+ (0x123 >> 8) & 0xff,
4100
+ AddressMode.ADDR_16BIT,
4101
+ ...zdoPayload,
4102
+ 0, // scancount
4103
+ 0, // nwkmanageraddr
4104
+ 0, // nwkmanageraddr
4105
+ ]),
4106
+ undefined,
4107
+ );
4108
+ });
4109
+
4110
+ it("Sends proper ZDO request payload for NWK_UPDATE_REQUEST BROADCAST", async () => {
4111
+ basicMocks();
4112
+ await adapter.start();
4113
+ mockZnpRequestZdo.mockClear();
4114
+
4115
+ const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
4116
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, [15], 0xfe, 0, undefined, 0);
4117
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.SLEEPY, clusterId, zdoPayload, true);
4118
+
4119
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
4120
+ clusterId,
4121
+ Buffer.from([
4122
+ ZSpec.BroadcastAddress.SLEEPY & 0xff,
4123
+ (ZSpec.BroadcastAddress.SLEEPY >> 8) & 0xff,
4124
+ AddressMode.ADDR_BROADCAST,
4125
+ ...zdoPayload,
4126
+ 0, // scancount
4127
+ 0, // nwkmanageraddr
4128
+ 0, // nwkmanageraddr
4129
+ ]),
4130
+ undefined,
4131
+ );
4132
+ });
4133
+
4134
+ it("Sends proper ZDO request payload for BIND_REQUEST/UNBIND_REQUEST UNICAST", async () => {
4135
+ basicMocks();
4136
+ await adapter.start();
4137
+ mockZnpRequestZdo.mockClear();
4138
+
4139
+ const clusterId = Zdo.ClusterId.BIND_REQUEST;
4140
+ const zdoPayload = Zdo.Buffalo.buildRequest(
4141
+ false,
4142
+ clusterId,
4143
+ "0x1122334455667788",
4144
+ 3,
4145
+ Zcl.Clusters.barrierControl.ID,
4146
+ Zdo.UNICAST_BINDING,
4147
+ "0x5544332211667788",
4148
+ 0,
4149
+ 5,
4150
+ );
4151
+
4152
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
4153
+
4154
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
4155
+ });
4156
+
4157
+ it("Sends proper ZDO request payload for BIND_REQUEST/UNBIND_REQUEST MULTICAST", async () => {
4158
+ basicMocks();
4159
+ await adapter.start();
4160
+ mockZnpRequestZdo.mockClear();
4161
+
4162
+ const clusterId = Zdo.ClusterId.BIND_REQUEST;
4163
+ const zdoPayload = Zdo.Buffalo.buildRequest(
4164
+ false,
4165
+ clusterId,
4166
+ "0x1122334455667788",
4167
+ 3,
4168
+ Zcl.Clusters.barrierControl.ID,
4169
+ Zdo.MULTICAST_BINDING,
4170
+ ZSpec.BLANK_EUI64,
4171
+ 32,
4172
+ 0,
4173
+ );
4174
+
4175
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
4176
+
4177
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(
4178
+ clusterId,
4179
+ Buffer.from([
4180
+ 1234 & 0xff,
4181
+ (1234 >> 8) & 0xff,
4182
+ ...zdoPayload,
4183
+ 0, // match destination EUI64 length
4184
+ 0, // match destination EUI64 length
4185
+ 0, // match destination EUI64 length
4186
+ 0, // match destination EUI64 length
4187
+ 0, // match destination EUI64 length
4188
+ 0, // match destination EUI64 length
4189
+ 0, // endpoint
4190
+ ]),
4191
+ undefined,
4192
+ );
4193
+ });
4194
+
4195
+ it("Sends proper ZDO request payload for NETWORK_ADDRESS_REQUEST", async () => {
4196
+ basicMocks();
4197
+ await adapter.start();
4198
+ mockZnpRequestZdo.mockClear();
4199
+
4200
+ const clusterId = Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
4201
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, "0x1122334455667788", false, 0);
4202
+
4203
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
4204
+
4205
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, zdoPayload, undefined);
4206
+ });
4207
+
4208
+ it("Sends proper ZDO request payload for generic logic request", async () => {
4209
+ basicMocks();
4210
+ await adapter.start();
4211
+ mockZnpRequestZdo.mockClear();
4212
+
4213
+ const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
4214
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 1234);
4215
+
4216
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
4217
+
4218
+ expect(mockZnpRequestZdo).toHaveBeenCalledWith(clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
4219
+ });
4220
+
4221
+ it("Node descriptor request should discover route to fix potential fails", async () => {
4222
+ // https://github.com/Koenkk/zigbee2mqtt/issues/3276
4223
+ basicMocks();
4224
+ await adapter.start();
4225
+ mockZnpRequest.mockClear();
4226
+ mockZnpRequestZdo.mockClear();
4227
+ mockZnpRequestZdo.mockRejectedValueOnce(new Error("Failed"));
4228
+
4229
+ const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
4230
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 1234);
4231
+
4232
+ await adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true);
4233
+
4234
+ expect(mockZnpRequestZdo).toHaveBeenCalledTimes(2);
4235
+ expect(mockZnpRequestZdo).toHaveBeenNthCalledWith(1, clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
4236
+ expect(mockZnpRequestZdo).toHaveBeenNthCalledWith(2, clusterId, Buffer.from([1234 & 0xff, (1234 >> 8) & 0xff, ...zdoPayload]), undefined);
4237
+ expect(mockZnpRequest).toHaveBeenCalledTimes(1);
4238
+ expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, "extRouteDisc", {dstAddr: 1234, options: 0, radius: 30});
4239
+ });
4240
+
4241
+ it("Should throw error when ZDO call fails", async () => {
4242
+ basicMocks();
4243
+ await adapter.start();
4244
+ mockZnpRequest.mockClear();
4245
+ mockZnpRequestZdo.mockClear();
4246
+ mockZnpRequestZdo.mockRejectedValueOnce(new Error("Failed"));
4247
+
4248
+ const clusterId = Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST;
4249
+ const zdoPayload = Zdo.Buffalo.buildRequest(false, clusterId, 123, 0);
4250
+
4251
+ await expect(adapter.sendZdo(ZSpec.BLANK_EUI64, 1234, clusterId, zdoPayload, true)).rejects.toThrow("Failed");
4252
+ });
4253
+
4254
+ it("Should throw error when registerEndpoints fails", async () => {
4255
+ basicMocks();
4256
+ vi.spyOn(adapter, "sendZdo").mockResolvedValueOnce([Zdo.Status.NOT_ACTIVE, undefined]);
4257
+
4258
+ await expect(adapter.start()).rejects.toThrow(`Status 'NOT_ACTIVE'`);
4259
+ });
4260
+ });