@willieee802/zigbee-herdsman 0.48.3 → 0.49.0

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 (1025) 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 +1245 -0
  18. package/README.md +1 -1
  19. package/biome.json +103 -0
  20. package/examples/join-and-log.js +18 -18
  21. package/package.json +83 -70
  22. package/release-please-config.json +8 -8
  23. package/scripts/check-clusters-changes.ts +328 -0
  24. package/scripts/clusters-changes.log +584 -0
  25. package/scripts/clusters-typegen.ts +608 -0
  26. package/scripts/utils.ts +88 -0
  27. package/scripts/zap-update-clusters-report.json +303 -0
  28. package/scripts/zap-update-clusters.ts +1520 -0
  29. package/scripts/zap-update-types.ts +707 -0
  30. package/scripts/zap-xml-clusters-overrides-data.ts +52 -0
  31. package/scripts/zap-xml-clusters-overrides.ts +400 -0
  32. package/scripts/zap-xml-types.ts +146 -0
  33. package/src/adapter/adapter.ts +210 -0
  34. package/src/adapter/adapterDiscovery.ts +736 -0
  35. package/src/adapter/const.ts +12 -0
  36. package/src/adapter/deconz/adapter/deconzAdapter.ts +888 -0
  37. package/src/adapter/deconz/driver/constants.ts +246 -0
  38. package/src/adapter/deconz/driver/driver.ts +1528 -0
  39. package/src/adapter/deconz/driver/frame.ts +11 -0
  40. package/src/adapter/deconz/driver/frameParser.ts +766 -0
  41. package/src/adapter/deconz/driver/parser.ts +45 -0
  42. package/src/adapter/deconz/driver/writer.ts +22 -0
  43. package/src/adapter/deconz/types.d.ts +13 -0
  44. package/src/adapter/ember/adapter/emberAdapter.ts +2262 -0
  45. package/src/adapter/ember/adapter/endpoints.ts +86 -0
  46. package/src/adapter/ember/adapter/oneWaitress.ts +324 -0
  47. package/src/adapter/ember/adapter/tokensManager.ts +780 -0
  48. package/src/adapter/ember/consts.ts +178 -0
  49. package/src/adapter/ember/enums.ts +1746 -0
  50. package/src/adapter/ember/ezsp/buffalo.ts +1392 -0
  51. package/src/adapter/ember/ezsp/consts.ts +148 -0
  52. package/src/adapter/ember/ezsp/enums.ts +1114 -0
  53. package/src/adapter/ember/ezsp/ezsp.ts +9073 -0
  54. package/src/adapter/ember/ezspError.ts +10 -0
  55. package/src/adapter/ember/types.ts +866 -0
  56. package/src/adapter/ember/uart/ash.ts +1933 -0
  57. package/src/adapter/ember/uart/consts.ts +109 -0
  58. package/src/adapter/ember/uart/enums.ts +192 -0
  59. package/src/adapter/ember/uart/parser.ts +42 -0
  60. package/src/adapter/ember/uart/queues.ts +247 -0
  61. package/src/adapter/ember/uart/writer.ts +50 -0
  62. package/src/adapter/ember/utils/initters.ts +58 -0
  63. package/src/adapter/ember/utils/math.ts +71 -0
  64. package/src/adapter/events.ts +21 -0
  65. package/src/adapter/ezsp/adapter/backup.ts +100 -0
  66. package/src/adapter/ezsp/adapter/ezspAdapter.ts +632 -0
  67. package/src/adapter/ezsp/driver/commands.ts +2497 -0
  68. package/src/adapter/ezsp/driver/consts.ts +11 -0
  69. package/src/adapter/ezsp/driver/driver.ts +1002 -0
  70. package/src/adapter/ezsp/driver/ezsp.ts +802 -0
  71. package/src/adapter/ezsp/driver/frame.ts +101 -0
  72. package/src/adapter/ezsp/driver/index.ts +4 -0
  73. package/src/adapter/ezsp/driver/multicast.ts +78 -0
  74. package/src/adapter/ezsp/driver/parser.ts +81 -0
  75. package/src/adapter/ezsp/driver/types/basic.ts +201 -0
  76. package/src/adapter/ezsp/driver/types/index.ts +239 -0
  77. package/src/adapter/ezsp/driver/types/named.ts +2330 -0
  78. package/src/adapter/ezsp/driver/types/struct.ts +844 -0
  79. package/src/adapter/ezsp/driver/uart.ts +460 -0
  80. package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +44 -0
  81. package/src/adapter/ezsp/driver/utils/index.ts +32 -0
  82. package/src/adapter/ezsp/driver/writer.ts +64 -0
  83. package/src/adapter/index.ts +3 -0
  84. package/src/adapter/serialPort.ts +58 -0
  85. package/src/adapter/tstype.ts +57 -0
  86. package/src/adapter/utils.ts +41 -0
  87. package/src/adapter/z-stack/adapter/adapter-backup.ts +509 -0
  88. package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +457 -0
  89. package/src/adapter/z-stack/adapter/endpoints.ts +60 -0
  90. package/src/adapter/z-stack/adapter/manager.ts +543 -0
  91. package/src/adapter/z-stack/adapter/tstype.ts +6 -0
  92. package/src/adapter/z-stack/adapter/zStackAdapter.ts +1350 -0
  93. package/src/adapter/z-stack/constants/af.ts +27 -0
  94. package/src/adapter/z-stack/constants/common.ts +285 -0
  95. package/src/adapter/z-stack/constants/dbg.ts +23 -0
  96. package/src/adapter/z-stack/constants/index.ts +11 -0
  97. package/src/adapter/z-stack/constants/mac.ts +128 -0
  98. package/src/adapter/z-stack/constants/sapi.ts +25 -0
  99. package/src/adapter/z-stack/constants/sys.ts +72 -0
  100. package/src/adapter/z-stack/constants/util.ts +82 -0
  101. package/src/adapter/z-stack/constants/utils.ts +14 -0
  102. package/src/adapter/z-stack/constants/zdo.ts +103 -0
  103. package/src/adapter/z-stack/models/startup-options.ts +13 -0
  104. package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +44 -0
  105. package/src/adapter/z-stack/structs/entries/address-manager-table.ts +19 -0
  106. package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +12 -0
  107. package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +21 -0
  108. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +19 -0
  109. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +21 -0
  110. package/src/adapter/z-stack/structs/entries/channel-list.ts +8 -0
  111. package/src/adapter/z-stack/structs/entries/has-configured.ts +16 -0
  112. package/src/adapter/z-stack/structs/entries/index.ts +16 -0
  113. package/src/adapter/z-stack/structs/entries/nib.ts +66 -0
  114. package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +15 -0
  115. package/src/adapter/z-stack/structs/entries/nwk-key.ts +13 -0
  116. package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +8 -0
  117. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +20 -0
  118. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +19 -0
  119. package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +33 -0
  120. package/src/adapter/z-stack/structs/entries/security-manager-table.ts +22 -0
  121. package/src/adapter/z-stack/structs/index.ts +4 -0
  122. package/src/adapter/z-stack/structs/serializable-memory-object.ts +14 -0
  123. package/src/adapter/z-stack/structs/struct.ts +367 -0
  124. package/src/adapter/z-stack/structs/table.ts +198 -0
  125. package/src/adapter/z-stack/unpi/constants.ts +33 -0
  126. package/src/adapter/z-stack/unpi/frame.ts +62 -0
  127. package/src/adapter/z-stack/unpi/index.ts +4 -0
  128. package/src/adapter/z-stack/unpi/parser.ts +67 -0
  129. package/src/adapter/z-stack/unpi/writer.ts +37 -0
  130. package/src/adapter/z-stack/utils/channel-list.ts +40 -0
  131. package/src/adapter/z-stack/utils/index.ts +2 -0
  132. package/src/adapter/z-stack/utils/network-options.ts +26 -0
  133. package/src/adapter/z-stack/znp/buffaloZnp.ts +175 -0
  134. package/src/adapter/z-stack/znp/definition.ts +2713 -0
  135. package/src/adapter/z-stack/znp/index.ts +2 -0
  136. package/src/adapter/z-stack/znp/parameterType.ts +22 -0
  137. package/src/adapter/z-stack/znp/tstype.ts +44 -0
  138. package/src/adapter/z-stack/znp/utils.ts +10 -0
  139. package/src/adapter/z-stack/znp/znp.ts +345 -0
  140. package/src/adapter/z-stack/znp/zpiObject.ts +148 -0
  141. package/src/adapter/zboss/adapter/zbossAdapter.ts +535 -0
  142. package/src/adapter/zboss/commands.ts +1184 -0
  143. package/src/adapter/zboss/consts.ts +9 -0
  144. package/src/adapter/zboss/driver.ts +422 -0
  145. package/src/adapter/zboss/enums.ts +360 -0
  146. package/src/adapter/zboss/frame.ts +227 -0
  147. package/src/adapter/zboss/reader.ts +65 -0
  148. package/src/adapter/zboss/types.ts +0 -0
  149. package/src/adapter/zboss/uart.ts +428 -0
  150. package/src/adapter/zboss/utils.ts +58 -0
  151. package/src/adapter/zboss/writer.ts +49 -0
  152. package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +25 -0
  153. package/src/adapter/zigate/adapter/zigateAdapter.ts +633 -0
  154. package/src/adapter/zigate/driver/LICENSE +17 -0
  155. package/src/adapter/zigate/driver/buffaloZiGate.ts +210 -0
  156. package/src/adapter/zigate/driver/commandType.ts +418 -0
  157. package/src/adapter/zigate/driver/constants.ts +150 -0
  158. package/src/adapter/zigate/driver/frame.ts +197 -0
  159. package/src/adapter/zigate/driver/messageType.ts +287 -0
  160. package/src/adapter/zigate/driver/parameterType.ts +32 -0
  161. package/src/adapter/zigate/driver/ziGateObject.ts +146 -0
  162. package/src/adapter/zigate/driver/zigate.ts +422 -0
  163. package/src/adapter/zoh/adapter/utils.ts +27 -0
  164. package/src/adapter/zoh/adapter/zohAdapter.ts +931 -0
  165. package/src/buffalo/buffalo.ts +336 -0
  166. package/src/buffalo/index.ts +1 -0
  167. package/src/controller/controller.ts +1159 -0
  168. package/src/controller/database.ts +148 -0
  169. package/src/controller/events.ts +52 -0
  170. package/src/controller/greenPower.ts +613 -0
  171. package/src/controller/helpers/index.ts +1 -0
  172. package/src/controller/helpers/installCodes.ts +107 -0
  173. package/src/controller/helpers/ota.ts +575 -0
  174. package/src/controller/helpers/request.ts +96 -0
  175. package/src/controller/helpers/requestQueue.ts +126 -0
  176. package/src/controller/helpers/zclFrameConverter.ts +64 -0
  177. package/src/controller/helpers/zclTransactionSequenceNumber.ts +15 -0
  178. package/src/controller/index.ts +6 -0
  179. package/src/controller/model/device.ts +1791 -0
  180. package/src/controller/model/endpoint.ts +1235 -0
  181. package/src/controller/model/entity.ts +43 -0
  182. package/src/controller/model/group.ts +446 -0
  183. package/src/controller/model/index.ts +5 -0
  184. package/src/controller/model/konnextConfig.ts +6 -0
  185. package/src/controller/model/zigbeeEntity.ts +30 -0
  186. package/src/controller/touchlink.ts +195 -0
  187. package/src/controller/tstype.ts +374 -0
  188. package/src/index.ts +14 -0
  189. package/src/models/backup-storage-legacy.ts +48 -0
  190. package/src/models/backup-storage-unified.ts +47 -0
  191. package/src/models/backup.ts +37 -0
  192. package/src/models/index.ts +5 -0
  193. package/src/models/network-options.ts +11 -0
  194. package/src/utils/aes.ts +218 -0
  195. package/src/utils/async-mutex.ts +31 -0
  196. package/src/utils/backup.ts +152 -0
  197. package/src/utils/index.ts +5 -0
  198. package/src/utils/logger.ts +20 -0
  199. package/src/utils/patchBigIntSerialization.ts +8 -0
  200. package/src/utils/queue.ts +79 -0
  201. package/src/utils/timeService.ts +139 -0
  202. package/src/utils/utils.ts +19 -0
  203. package/src/utils/wait.ts +5 -0
  204. package/src/utils/waitress.ts +96 -0
  205. package/src/zspec/consts.ts +89 -0
  206. package/src/zspec/enums.ts +22 -0
  207. package/src/zspec/index.ts +3 -0
  208. package/src/zspec/tstypes.ts +18 -0
  209. package/src/zspec/utils.ts +247 -0
  210. package/src/zspec/zcl/buffaloZcl.ts +1073 -0
  211. package/src/zspec/zcl/definition/cluster.ts +7845 -0
  212. package/src/zspec/zcl/definition/clusters-types.ts +8577 -0
  213. package/src/zspec/zcl/definition/consts.ts +24 -0
  214. package/src/zspec/zcl/definition/datatypes.ts +2454 -0
  215. package/src/zspec/zcl/definition/enums.ts +224 -0
  216. package/src/zspec/zcl/definition/foundation.ts +342 -0
  217. package/src/zspec/zcl/definition/manufacturerCode.ts +730 -0
  218. package/src/zspec/zcl/definition/status.ts +69 -0
  219. package/src/zspec/zcl/definition/tstype.ts +446 -0
  220. package/src/zspec/zcl/index.ts +11 -0
  221. package/src/zspec/zcl/utils.ts +521 -0
  222. package/src/zspec/zcl/zclFrame.ts +383 -0
  223. package/src/zspec/zcl/zclHeader.ts +102 -0
  224. package/src/zspec/zcl/zclStatusError.ts +10 -0
  225. package/src/zspec/zdo/buffaloZdo.ts +2336 -0
  226. package/src/zspec/zdo/definition/clusters.ts +722 -0
  227. package/src/zspec/zdo/definition/consts.ts +16 -0
  228. package/src/zspec/zdo/definition/enums.ts +99 -0
  229. package/src/zspec/zdo/definition/status.ts +105 -0
  230. package/src/zspec/zdo/definition/tstypes.ts +1062 -0
  231. package/src/zspec/zdo/index.ts +7 -0
  232. package/src/zspec/zdo/utils.ts +76 -0
  233. package/src/zspec/zdo/zdoStatusError.ts +10 -0
  234. package/test/adapter/adapter.test.ts +1276 -0
  235. package/test/adapter/ember/ash.test.ts +337 -0
  236. package/test/adapter/ember/consts.ts +131 -0
  237. package/test/adapter/ember/emberAdapter.test.ts +3447 -0
  238. package/test/adapter/ember/ezsp.test.ts +389 -0
  239. package/test/adapter/ember/ezspBuffalo.test.ts +93 -0
  240. package/test/adapter/ember/ezspError.test.ts +12 -0
  241. package/test/adapter/ember/math.test.ts +190 -0
  242. package/test/adapter/ezsp/frame.test.ts +30 -0
  243. package/test/adapter/ezsp/uart.test.ts +181 -0
  244. package/test/adapter/z-stack/adapter.test.ts +4260 -0
  245. package/test/adapter/z-stack/constants.test.ts +33 -0
  246. package/test/adapter/z-stack/structs.test.ts +115 -0
  247. package/test/adapter/z-stack/unpi.test.ts +213 -0
  248. package/test/adapter/z-stack/znp.test.ts +1288 -0
  249. package/test/adapter/zboss/fixZdoResponse.test.ts +179 -0
  250. package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +81 -0
  251. package/test/adapter/zigate/zdo.test.ts +187 -0
  252. package/test/adapter/zoh/utils.test.ts +36 -0
  253. package/test/adapter/zoh/zohAdapter.test.ts +1451 -0
  254. package/test/benchOptions.ts +14 -0
  255. package/test/buffalo.test.ts +431 -0
  256. package/test/controller.bench.ts +215 -0
  257. package/test/controller.test.ts +10030 -0
  258. package/test/data/integrity-code-1166-012B-24031511-upgradeMe-RB 249 T.zigbee +0 -0
  259. package/test/data/manuf-tags-tradfri-cv-cct-unified_release_prod_v587757105_33e34452-9267-4665-bc5a-844c8f61f063.ota +0 -0
  260. package/test/data/padded-tretakt_smart_plug_soc-0x1100-2.4.25-prod.ota.ota.signed +0 -0
  261. package/test/data/telink-aes-A60_RGBW_T-0x00B6-0x03483712-MF_DIS.OTA +0 -0
  262. package/test/data/zbminir2_v1.0.8.ota +0 -0
  263. package/test/device-ota.test.ts +3332 -0
  264. package/test/greenpower.test.ts +1409 -0
  265. package/test/mockAdapters.ts +95 -0
  266. package/test/mockDevices.ts +623 -0
  267. package/test/requests.bench.ts +321 -0
  268. package/test/testUtils.ts +20 -0
  269. package/test/timeService.test.ts +214 -0
  270. package/test/tsconfig.json +9 -0
  271. package/test/utils/math.ts +19 -0
  272. package/test/utils.test.ts +352 -0
  273. package/test/vitest.config.mts +28 -0
  274. package/test/vitest.ts +9 -0
  275. package/test/zcl.test.ts +2858 -0
  276. package/test/zspec/utils.test.ts +68 -0
  277. package/test/zspec/zcl/buffalo.test.ts +1316 -0
  278. package/test/zspec/zcl/frame.test.ts +1056 -0
  279. package/test/zspec/zcl/utils.test.ts +650 -0
  280. package/test/zspec/zdo/buffalo.test.ts +1850 -0
  281. package/test/zspec/zdo/utils.test.ts +241 -0
  282. package/tsconfig.json +8 -10
  283. package/.babelrc.js +0 -6
  284. package/.eslintignore +0 -3
  285. package/dist/adapter/adapter.d.ts +0 -64
  286. package/dist/adapter/adapter.d.ts.map +0 -1
  287. package/dist/adapter/adapter.js +0 -157
  288. package/dist/adapter/adapter.js.map +0 -1
  289. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +0 -71
  290. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +0 -1
  291. package/dist/adapter/deconz/adapter/deconzAdapter.js +0 -1072
  292. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +0 -1
  293. package/dist/adapter/deconz/adapter/index.d.ts +0 -3
  294. package/dist/adapter/deconz/adapter/index.d.ts.map +0 -1
  295. package/dist/adapter/deconz/adapter/index.js +0 -11
  296. package/dist/adapter/deconz/adapter/index.js.map +0 -1
  297. package/dist/adapter/deconz/driver/constants.d.ts +0 -105
  298. package/dist/adapter/deconz/driver/constants.d.ts.map +0 -1
  299. package/dist/adapter/deconz/driver/constants.js +0 -56
  300. package/dist/adapter/deconz/driver/constants.js.map +0 -1
  301. package/dist/adapter/deconz/driver/driver.d.ts +0 -82
  302. package/dist/adapter/deconz/driver/driver.d.ts.map +0 -1
  303. package/dist/adapter/deconz/driver/driver.js +0 -751
  304. package/dist/adapter/deconz/driver/driver.js.map +0 -1
  305. package/dist/adapter/deconz/driver/frame.d.ts +0 -7
  306. package/dist/adapter/deconz/driver/frame.d.ts.map +0 -1
  307. package/dist/adapter/deconz/driver/frame.js +0 -14
  308. package/dist/adapter/deconz/driver/frame.js.map +0 -1
  309. package/dist/adapter/deconz/driver/frameParser.d.ts +0 -3
  310. package/dist/adapter/deconz/driver/frameParser.d.ts.map +0 -1
  311. package/dist/adapter/deconz/driver/frameParser.js +0 -444
  312. package/dist/adapter/deconz/driver/frameParser.js.map +0 -1
  313. package/dist/adapter/deconz/driver/parser.d.ts +0 -13
  314. package/dist/adapter/deconz/driver/parser.d.ts.map +0 -1
  315. package/dist/adapter/deconz/driver/parser.js +0 -64
  316. package/dist/adapter/deconz/driver/parser.js.map +0 -1
  317. package/dist/adapter/deconz/driver/writer.d.ts +0 -9
  318. package/dist/adapter/deconz/driver/writer.d.ts.map +0 -1
  319. package/dist/adapter/deconz/driver/writer.js +0 -45
  320. package/dist/adapter/deconz/driver/writer.js.map +0 -1
  321. package/dist/adapter/ember/adapter/emberAdapter.d.ts +0 -806
  322. package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +0 -1
  323. package/dist/adapter/ember/adapter/emberAdapter.js +0 -2942
  324. package/dist/adapter/ember/adapter/emberAdapter.js.map +0 -1
  325. package/dist/adapter/ember/adapter/endpoints.d.ts +0 -27
  326. package/dist/adapter/ember/adapter/endpoints.d.ts.map +0 -1
  327. package/dist/adapter/ember/adapter/endpoints.js +0 -68
  328. package/dist/adapter/ember/adapter/endpoints.js.map +0 -1
  329. package/dist/adapter/ember/adapter/index.d.ts +0 -3
  330. package/dist/adapter/ember/adapter/index.d.ts.map +0 -1
  331. package/dist/adapter/ember/adapter/index.js +0 -6
  332. package/dist/adapter/ember/adapter/index.js.map +0 -1
  333. package/dist/adapter/ember/adapter/oneWaitress.d.ts +0 -108
  334. package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +0 -1
  335. package/dist/adapter/ember/adapter/oneWaitress.js +0 -241
  336. package/dist/adapter/ember/adapter/oneWaitress.js.map +0 -1
  337. package/dist/adapter/ember/adapter/requestQueue.d.ts +0 -57
  338. package/dist/adapter/ember/adapter/requestQueue.d.ts.map +0 -1
  339. package/dist/adapter/ember/adapter/requestQueue.js +0 -139
  340. package/dist/adapter/ember/adapter/requestQueue.js.map +0 -1
  341. package/dist/adapter/ember/adapter/tokensManager.d.ts +0 -69
  342. package/dist/adapter/ember/adapter/tokensManager.d.ts.map +0 -1
  343. package/dist/adapter/ember/adapter/tokensManager.js +0 -688
  344. package/dist/adapter/ember/adapter/tokensManager.js.map +0 -1
  345. package/dist/adapter/ember/consts.d.ts +0 -191
  346. package/dist/adapter/ember/consts.d.ts.map +0 -1
  347. package/dist/adapter/ember/consts.js +0 -246
  348. package/dist/adapter/ember/consts.js.map +0 -1
  349. package/dist/adapter/ember/enums.d.ts +0 -2172
  350. package/dist/adapter/ember/enums.d.ts.map +0 -1
  351. package/dist/adapter/ember/enums.js +0 -2375
  352. package/dist/adapter/ember/enums.js.map +0 -1
  353. package/dist/adapter/ember/ezsp/buffalo.d.ts +0 -156
  354. package/dist/adapter/ember/ezsp/buffalo.d.ts.map +0 -1
  355. package/dist/adapter/ember/ezsp/buffalo.js +0 -1033
  356. package/dist/adapter/ember/ezsp/buffalo.js.map +0 -1
  357. package/dist/adapter/ember/ezsp/consts.d.ts +0 -116
  358. package/dist/adapter/ember/ezsp/consts.d.ts.map +0 -1
  359. package/dist/adapter/ember/ezsp/consts.js +0 -128
  360. package/dist/adapter/ember/ezsp/consts.js.map +0 -1
  361. package/dist/adapter/ember/ezsp/enums.d.ts +0 -879
  362. package/dist/adapter/ember/ezsp/enums.d.ts.map +0 -1
  363. package/dist/adapter/ember/ezsp/enums.js +0 -948
  364. package/dist/adapter/ember/ezsp/enums.js.map +0 -1
  365. package/dist/adapter/ember/ezsp/ezsp.d.ts +0 -2662
  366. package/dist/adapter/ember/ezsp/ezsp.d.ts.map +0 -1
  367. package/dist/adapter/ember/ezsp/ezsp.js +0 -6454
  368. package/dist/adapter/ember/ezsp/ezsp.js.map +0 -1
  369. package/dist/adapter/ember/types.d.ts +0 -733
  370. package/dist/adapter/ember/types.d.ts.map +0 -1
  371. package/dist/adapter/ember/types.js +0 -3
  372. package/dist/adapter/ember/types.js.map +0 -1
  373. package/dist/adapter/ember/uart/ash.d.ts +0 -464
  374. package/dist/adapter/ember/uart/ash.d.ts.map +0 -1
  375. package/dist/adapter/ember/uart/ash.js +0 -1633
  376. package/dist/adapter/ember/uart/ash.js.map +0 -1
  377. package/dist/adapter/ember/uart/consts.d.ts +0 -91
  378. package/dist/adapter/ember/uart/consts.d.ts.map +0 -1
  379. package/dist/adapter/ember/uart/consts.js +0 -100
  380. package/dist/adapter/ember/uart/consts.js.map +0 -1
  381. package/dist/adapter/ember/uart/enums.d.ts +0 -191
  382. package/dist/adapter/ember/uart/enums.d.ts.map +0 -1
  383. package/dist/adapter/ember/uart/enums.js +0 -197
  384. package/dist/adapter/ember/uart/enums.js.map +0 -1
  385. package/dist/adapter/ember/uart/parser.d.ts +0 -10
  386. package/dist/adapter/ember/uart/parser.d.ts.map +0 -1
  387. package/dist/adapter/ember/uart/parser.js +0 -37
  388. package/dist/adapter/ember/uart/parser.js.map +0 -1
  389. package/dist/adapter/ember/uart/queues.d.ts +0 -85
  390. package/dist/adapter/ember/uart/queues.d.ts.map +0 -1
  391. package/dist/adapter/ember/uart/queues.js +0 -214
  392. package/dist/adapter/ember/uart/queues.js.map +0 -1
  393. package/dist/adapter/ember/uart/writer.d.ts +0 -15
  394. package/dist/adapter/ember/uart/writer.d.ts.map +0 -1
  395. package/dist/adapter/ember/uart/writer.js +0 -46
  396. package/dist/adapter/ember/uart/writer.js.map +0 -1
  397. package/dist/adapter/ember/utils/initters.d.ts +0 -20
  398. package/dist/adapter/ember/utils/initters.d.ts.map +0 -1
  399. package/dist/adapter/ember/utils/initters.js +0 -58
  400. package/dist/adapter/ember/utils/initters.js.map +0 -1
  401. package/dist/adapter/ember/utils/math.d.ts +0 -51
  402. package/dist/adapter/ember/utils/math.d.ts.map +0 -1
  403. package/dist/adapter/ember/utils/math.js +0 -102
  404. package/dist/adapter/ember/utils/math.js.map +0 -1
  405. package/dist/adapter/ember/zdo.d.ts +0 -925
  406. package/dist/adapter/ember/zdo.d.ts.map +0 -1
  407. package/dist/adapter/ember/zdo.js +0 -723
  408. package/dist/adapter/ember/zdo.js.map +0 -1
  409. package/dist/adapter/events.d.ts +0 -42
  410. package/dist/adapter/events.d.ts.map +0 -1
  411. package/dist/adapter/events.js +0 -13
  412. package/dist/adapter/events.js.map +0 -1
  413. package/dist/adapter/ezsp/adapter/backup.d.ts +0 -13
  414. package/dist/adapter/ezsp/adapter/backup.d.ts.map +0 -1
  415. package/dist/adapter/ezsp/adapter/backup.js +0 -101
  416. package/dist/adapter/ezsp/adapter/backup.js.map +0 -1
  417. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +0 -65
  418. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +0 -1
  419. package/dist/adapter/ezsp/adapter/ezspAdapter.js +0 -634
  420. package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +0 -1
  421. package/dist/adapter/ezsp/adapter/index.d.ts +0 -3
  422. package/dist/adapter/ezsp/adapter/index.d.ts.map +0 -1
  423. package/dist/adapter/ezsp/adapter/index.js +0 -11
  424. package/dist/adapter/ezsp/adapter/index.js.map +0 -1
  425. package/dist/adapter/ezsp/driver/commands.d.ts +0 -37
  426. package/dist/adapter/ezsp/driver/commands.d.ts.map +0 -1
  427. package/dist/adapter/ezsp/driver/commands.js +0 -2387
  428. package/dist/adapter/ezsp/driver/commands.js.map +0 -1
  429. package/dist/adapter/ezsp/driver/consts.d.ts +0 -11
  430. package/dist/adapter/ezsp/driver/consts.d.ts.map +0 -1
  431. package/dist/adapter/ezsp/driver/consts.js +0 -14
  432. package/dist/adapter/ezsp/driver/consts.js.map +0 -1
  433. package/dist/adapter/ezsp/driver/driver.d.ts +0 -109
  434. package/dist/adapter/ezsp/driver/driver.d.ts.map +0 -1
  435. package/dist/adapter/ezsp/driver/driver.js +0 -796
  436. package/dist/adapter/ezsp/driver/driver.js.map +0 -1
  437. package/dist/adapter/ezsp/driver/ezsp.d.ts +0 -106
  438. package/dist/adapter/ezsp/driver/ezsp.d.ts.map +0 -1
  439. package/dist/adapter/ezsp/driver/ezsp.js +0 -664
  440. package/dist/adapter/ezsp/driver/ezsp.js.map +0 -1
  441. package/dist/adapter/ezsp/driver/frame.d.ts +0 -40
  442. package/dist/adapter/ezsp/driver/frame.d.ts.map +0 -1
  443. package/dist/adapter/ezsp/driver/frame.js +0 -101
  444. package/dist/adapter/ezsp/driver/frame.js.map +0 -1
  445. package/dist/adapter/ezsp/driver/index.d.ts +0 -4
  446. package/dist/adapter/ezsp/driver/index.d.ts.map +0 -1
  447. package/dist/adapter/ezsp/driver/index.js +0 -9
  448. package/dist/adapter/ezsp/driver/index.js.map +0 -1
  449. package/dist/adapter/ezsp/driver/multicast.d.ts +0 -13
  450. package/dist/adapter/ezsp/driver/multicast.d.ts.map +0 -1
  451. package/dist/adapter/ezsp/driver/multicast.js +0 -74
  452. package/dist/adapter/ezsp/driver/multicast.js.map +0 -1
  453. package/dist/adapter/ezsp/driver/parser.d.ts +0 -12
  454. package/dist/adapter/ezsp/driver/parser.d.ts.map +0 -1
  455. package/dist/adapter/ezsp/driver/parser.js +0 -105
  456. package/dist/adapter/ezsp/driver/parser.js.map +0 -1
  457. package/dist/adapter/ezsp/driver/types/basic.d.ts +0 -63
  458. package/dist/adapter/ezsp/driver/types/basic.d.ts.map +0 -1
  459. package/dist/adapter/ezsp/driver/types/basic.js +0 -209
  460. package/dist/adapter/ezsp/driver/types/basic.js.map +0 -1
  461. package/dist/adapter/ezsp/driver/types/index.d.ts +0 -10
  462. package/dist/adapter/ezsp/driver/types/index.d.ts.map +0 -1
  463. package/dist/adapter/ezsp/driver/types/index.js +0 -139
  464. package/dist/adapter/ezsp/driver/types/index.js.map +0 -1
  465. package/dist/adapter/ezsp/driver/types/named.d.ts +0 -1288
  466. package/dist/adapter/ezsp/driver/types/named.d.ts.map +0 -1
  467. package/dist/adapter/ezsp/driver/types/named.js +0 -2330
  468. package/dist/adapter/ezsp/driver/types/named.js.map +0 -1
  469. package/dist/adapter/ezsp/driver/types/struct.d.ts +0 -271
  470. package/dist/adapter/ezsp/driver/types/struct.d.ts.map +0 -1
  471. package/dist/adapter/ezsp/driver/types/struct.js +0 -804
  472. package/dist/adapter/ezsp/driver/types/struct.js.map +0 -1
  473. package/dist/adapter/ezsp/driver/uart.d.ts +0 -49
  474. package/dist/adapter/ezsp/driver/uart.d.ts.map +0 -1
  475. package/dist/adapter/ezsp/driver/uart.js +0 -383
  476. package/dist/adapter/ezsp/driver/uart.js.map +0 -1
  477. package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts +0 -3
  478. package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts.map +0 -1
  479. package/dist/adapter/ezsp/driver/utils/crc16ccitt.js +0 -56
  480. package/dist/adapter/ezsp/driver/utils/crc16ccitt.js.map +0 -1
  481. package/dist/adapter/ezsp/driver/utils/index.d.ts +0 -20
  482. package/dist/adapter/ezsp/driver/utils/index.d.ts.map +0 -1
  483. package/dist/adapter/ezsp/driver/utils/index.js +0 -73
  484. package/dist/adapter/ezsp/driver/utils/index.js.map +0 -1
  485. package/dist/adapter/ezsp/driver/writer.d.ts +0 -14
  486. package/dist/adapter/ezsp/driver/writer.d.ts.map +0 -1
  487. package/dist/adapter/ezsp/driver/writer.js +0 -83
  488. package/dist/adapter/ezsp/driver/writer.js.map +0 -1
  489. package/dist/adapter/index.d.ts +0 -5
  490. package/dist/adapter/index.d.ts.map +0 -1
  491. package/dist/adapter/index.js +0 -36
  492. package/dist/adapter/index.js.map +0 -1
  493. package/dist/adapter/serialPort.d.ts +0 -14
  494. package/dist/adapter/serialPort.d.ts.map +0 -1
  495. package/dist/adapter/serialPort.js +0 -47
  496. package/dist/adapter/serialPort.js.map +0 -1
  497. package/dist/adapter/serialPortUtils.d.ts +0 -13
  498. package/dist/adapter/serialPortUtils.d.ts.map +0 -1
  499. package/dist/adapter/serialPortUtils.js +0 -19
  500. package/dist/adapter/serialPortUtils.js.map +0 -1
  501. package/dist/adapter/socketPortUtils.d.ts +0 -11
  502. package/dist/adapter/socketPortUtils.d.ts.map +0 -1
  503. package/dist/adapter/socketPortUtils.js +0 -17
  504. package/dist/adapter/socketPortUtils.js.map +0 -1
  505. package/dist/adapter/tstype.d.ts +0 -86
  506. package/dist/adapter/tstype.d.ts.map +0 -1
  507. package/dist/adapter/tstype.js +0 -3
  508. package/dist/adapter/tstype.js.map +0 -1
  509. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts +0 -62
  510. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts.map +0 -1
  511. package/dist/adapter/z-stack/adapter/adapter-backup.js +0 -459
  512. package/dist/adapter/z-stack/adapter/adapter-backup.js.map +0 -1
  513. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts +0 -151
  514. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts.map +0 -1
  515. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +0 -259
  516. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +0 -1
  517. package/dist/adapter/z-stack/adapter/endpoints.d.ts +0 -12
  518. package/dist/adapter/z-stack/adapter/endpoints.d.ts.map +0 -1
  519. package/dist/adapter/z-stack/adapter/endpoints.js +0 -74
  520. package/dist/adapter/z-stack/adapter/endpoints.js.map +0 -1
  521. package/dist/adapter/z-stack/adapter/index.d.ts +0 -3
  522. package/dist/adapter/z-stack/adapter/index.d.ts.map +0 -1
  523. package/dist/adapter/z-stack/adapter/index.js +0 -9
  524. package/dist/adapter/z-stack/adapter/index.js.map +0 -1
  525. package/dist/adapter/z-stack/adapter/manager.d.ts +0 -84
  526. package/dist/adapter/z-stack/adapter/manager.d.ts.map +0 -1
  527. package/dist/adapter/z-stack/adapter/manager.js +0 -474
  528. package/dist/adapter/z-stack/adapter/manager.js.map +0 -1
  529. package/dist/adapter/z-stack/adapter/tstype.d.ts +0 -7
  530. package/dist/adapter/z-stack/adapter/tstype.d.ts.map +0 -1
  531. package/dist/adapter/z-stack/adapter/tstype.js +0 -10
  532. package/dist/adapter/z-stack/adapter/tstype.js.map +0 -1
  533. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +0 -86
  534. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +0 -1
  535. package/dist/adapter/z-stack/adapter/zStackAdapter.js +0 -912
  536. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +0 -1
  537. package/dist/adapter/z-stack/constants/af.d.ts +0 -24
  538. package/dist/adapter/z-stack/constants/af.d.ts.map +0 -1
  539. package/dist/adapter/z-stack/constants/af.js +0 -28
  540. package/dist/adapter/z-stack/constants/af.js.map +0 -1
  541. package/dist/adapter/z-stack/constants/common.d.ts +0 -279
  542. package/dist/adapter/z-stack/constants/common.d.ts.map +0 -1
  543. package/dist/adapter/z-stack/constants/common.js +0 -293
  544. package/dist/adapter/z-stack/constants/common.js.map +0 -1
  545. package/dist/adapter/z-stack/constants/dbg.d.ts +0 -23
  546. package/dist/adapter/z-stack/constants/dbg.d.ts.map +0 -1
  547. package/dist/adapter/z-stack/constants/dbg.js +0 -25
  548. package/dist/adapter/z-stack/constants/dbg.js.map +0 -1
  549. package/dist/adapter/z-stack/constants/index.d.ts +0 -11
  550. package/dist/adapter/z-stack/constants/index.d.ts.map +0 -1
  551. package/dist/adapter/z-stack/constants/index.js +0 -48
  552. package/dist/adapter/z-stack/constants/index.js.map +0 -1
  553. package/dist/adapter/z-stack/constants/mac.d.ts +0 -128
  554. package/dist/adapter/z-stack/constants/mac.d.ts.map +0 -1
  555. package/dist/adapter/z-stack/constants/mac.js +0 -130
  556. package/dist/adapter/z-stack/constants/mac.js.map +0 -1
  557. package/dist/adapter/z-stack/constants/sapi.d.ts +0 -25
  558. package/dist/adapter/z-stack/constants/sapi.d.ts.map +0 -1
  559. package/dist/adapter/z-stack/constants/sapi.js +0 -27
  560. package/dist/adapter/z-stack/constants/sapi.js.map +0 -1
  561. package/dist/adapter/z-stack/constants/sys.d.ts +0 -72
  562. package/dist/adapter/z-stack/constants/sys.d.ts.map +0 -1
  563. package/dist/adapter/z-stack/constants/sys.js +0 -74
  564. package/dist/adapter/z-stack/constants/sys.js.map +0 -1
  565. package/dist/adapter/z-stack/constants/util.d.ts +0 -82
  566. package/dist/adapter/z-stack/constants/util.d.ts.map +0 -1
  567. package/dist/adapter/z-stack/constants/util.js +0 -84
  568. package/dist/adapter/z-stack/constants/util.js.map +0 -1
  569. package/dist/adapter/z-stack/constants/utils.d.ts +0 -5
  570. package/dist/adapter/z-stack/constants/utils.d.ts.map +0 -1
  571. package/dist/adapter/z-stack/constants/utils.js +0 -15
  572. package/dist/adapter/z-stack/constants/utils.js.map +0 -1
  573. package/dist/adapter/z-stack/constants/zdo.d.ts +0 -103
  574. package/dist/adapter/z-stack/constants/zdo.d.ts.map +0 -1
  575. package/dist/adapter/z-stack/constants/zdo.js +0 -105
  576. package/dist/adapter/z-stack/constants/zdo.js.map +0 -1
  577. package/dist/adapter/z-stack/models/index.d.ts +0 -2
  578. package/dist/adapter/z-stack/models/index.d.ts.map +0 -1
  579. package/dist/adapter/z-stack/models/index.js +0 -18
  580. package/dist/adapter/z-stack/models/index.js.map +0 -1
  581. package/dist/adapter/z-stack/models/startup-options.d.ts +0 -13
  582. package/dist/adapter/z-stack/models/startup-options.d.ts.map +0 -1
  583. package/dist/adapter/z-stack/models/startup-options.js +0 -3
  584. package/dist/adapter/z-stack/models/startup-options.js.map +0 -1
  585. package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts +0 -24
  586. package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts.map +0 -1
  587. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js +0 -46
  588. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js.map +0 -1
  589. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts +0 -11
  590. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts.map +0 -1
  591. package/dist/adapter/z-stack/structs/entries/address-manager-table.js +0 -23
  592. package/dist/adapter/z-stack/structs/entries/address-manager-table.js.map +0 -1
  593. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts +0 -11
  594. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts.map +0 -1
  595. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js +0 -22
  596. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js.map +0 -1
  597. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts +0 -11
  598. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts.map +0 -1
  599. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js +0 -24
  600. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js.map +0 -1
  601. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts +0 -11
  602. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts.map +0 -1
  603. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js +0 -25
  604. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js.map +0 -1
  605. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts +0 -11
  606. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts.map +0 -1
  607. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js +0 -24
  608. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js.map +0 -1
  609. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts +0 -9
  610. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts.map +0 -1
  611. package/dist/adapter/z-stack/structs/entries/channel-list.js +0 -16
  612. package/dist/adapter/z-stack/structs/entries/channel-list.js.map +0 -1
  613. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts +0 -9
  614. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts.map +0 -1
  615. package/dist/adapter/z-stack/structs/entries/has-configured.js +0 -17
  616. package/dist/adapter/z-stack/structs/entries/has-configured.js.map +0 -1
  617. package/dist/adapter/z-stack/structs/entries/index.d.ts +0 -17
  618. package/dist/adapter/z-stack/structs/entries/index.d.ts.map +0 -1
  619. package/dist/adapter/z-stack/structs/entries/index.js +0 -33
  620. package/dist/adapter/z-stack/structs/entries/index.js.map +0 -1
  621. package/dist/adapter/z-stack/structs/entries/nib.d.ts +0 -11
  622. package/dist/adapter/z-stack/structs/entries/nib.d.ts.map +0 -1
  623. package/dist/adapter/z-stack/structs/entries/nib.js +0 -69
  624. package/dist/adapter/z-stack/structs/entries/nib.js.map +0 -1
  625. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts +0 -11
  626. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts.map +0 -1
  627. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js +0 -19
  628. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js.map +0 -1
  629. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts +0 -9
  630. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts.map +0 -1
  631. package/dist/adapter/z-stack/structs/entries/nwk-key.js +0 -16
  632. package/dist/adapter/z-stack/structs/entries/nwk-key.js.map +0 -1
  633. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts +0 -9
  634. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts.map +0 -1
  635. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js +0 -16
  636. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js.map +0 -1
  637. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts +0 -14
  638. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts.map +0 -1
  639. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js +0 -24
  640. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js.map +0 -1
  641. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts +0 -11
  642. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts.map +0 -1
  643. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js +0 -23
  644. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js.map +0 -1
  645. package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts +0 -21
  646. package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts.map +0 -1
  647. package/dist/adapter/z-stack/structs/entries/security-manager-entry.js +0 -37
  648. package/dist/adapter/z-stack/structs/entries/security-manager-entry.js.map +0 -1
  649. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts +0 -11
  650. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts.map +0 -1
  651. package/dist/adapter/z-stack/structs/entries/security-manager-table.js +0 -25
  652. package/dist/adapter/z-stack/structs/entries/security-manager-table.js.map +0 -1
  653. package/dist/adapter/z-stack/structs/index.d.ts +0 -5
  654. package/dist/adapter/z-stack/structs/index.d.ts.map +0 -1
  655. package/dist/adapter/z-stack/structs/index.js +0 -21
  656. package/dist/adapter/z-stack/structs/index.js.map +0 -1
  657. package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts +0 -14
  658. package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts.map +0 -1
  659. package/dist/adapter/z-stack/structs/serializable-memory-object.js +0 -3
  660. package/dist/adapter/z-stack/structs/serializable-memory-object.js.map +0 -1
  661. package/dist/adapter/z-stack/structs/struct.d.ts +0 -100
  662. package/dist/adapter/z-stack/structs/struct.d.ts.map +0 -1
  663. package/dist/adapter/z-stack/structs/struct.js +0 -297
  664. package/dist/adapter/z-stack/structs/struct.js.map +0 -1
  665. package/dist/adapter/z-stack/structs/table.d.ts +0 -95
  666. package/dist/adapter/z-stack/structs/table.d.ts.map +0 -1
  667. package/dist/adapter/z-stack/structs/table.js +0 -164
  668. package/dist/adapter/z-stack/structs/table.js.map +0 -1
  669. package/dist/adapter/z-stack/unpi/constants.d.ts +0 -29
  670. package/dist/adapter/z-stack/unpi/constants.d.ts.map +0 -1
  671. package/dist/adapter/z-stack/unpi/constants.js +0 -40
  672. package/dist/adapter/z-stack/unpi/constants.js.map +0 -1
  673. package/dist/adapter/z-stack/unpi/frame.d.ts +0 -17
  674. package/dist/adapter/z-stack/unpi/frame.d.ts.map +0 -1
  675. package/dist/adapter/z-stack/unpi/frame.js +0 -55
  676. package/dist/adapter/z-stack/unpi/frame.js.map +0 -1
  677. package/dist/adapter/z-stack/unpi/index.d.ts +0 -6
  678. package/dist/adapter/z-stack/unpi/index.d.ts.map +0 -1
  679. package/dist/adapter/z-stack/unpi/index.js +0 -38
  680. package/dist/adapter/z-stack/unpi/index.js.map +0 -1
  681. package/dist/adapter/z-stack/unpi/parser.d.ts +0 -13
  682. package/dist/adapter/z-stack/unpi/parser.d.ts.map +0 -1
  683. package/dist/adapter/z-stack/unpi/parser.js +0 -86
  684. package/dist/adapter/z-stack/unpi/parser.js.map +0 -1
  685. package/dist/adapter/z-stack/unpi/writer.d.ts +0 -12
  686. package/dist/adapter/z-stack/unpi/writer.d.ts.map +0 -1
  687. package/dist/adapter/z-stack/unpi/writer.js +0 -55
  688. package/dist/adapter/z-stack/unpi/writer.js.map +0 -1
  689. package/dist/adapter/z-stack/utils/channel-list.d.ts +0 -21
  690. package/dist/adapter/z-stack/utils/channel-list.d.ts.map +0 -1
  691. package/dist/adapter/z-stack/utils/channel-list.js +0 -41
  692. package/dist/adapter/z-stack/utils/channel-list.js.map +0 -1
  693. package/dist/adapter/z-stack/utils/index.d.ts +0 -3
  694. package/dist/adapter/z-stack/utils/index.d.ts.map +0 -1
  695. package/dist/adapter/z-stack/utils/index.js +0 -19
  696. package/dist/adapter/z-stack/utils/index.js.map +0 -1
  697. package/dist/adapter/z-stack/utils/network-options.d.ts +0 -9
  698. package/dist/adapter/z-stack/utils/network-options.d.ts.map +0 -1
  699. package/dist/adapter/z-stack/utils/network-options.js +0 -23
  700. package/dist/adapter/z-stack/utils/network-options.js.map +0 -1
  701. package/dist/adapter/z-stack/znp/buffaloZnp.d.ts +0 -14
  702. package/dist/adapter/z-stack/znp/buffaloZnp.d.ts.map +0 -1
  703. package/dist/adapter/z-stack/znp/buffaloZnp.js +0 -243
  704. package/dist/adapter/z-stack/znp/buffaloZnp.js.map +0 -1
  705. package/dist/adapter/z-stack/znp/definition.d.ts +0 -6
  706. package/dist/adapter/z-stack/znp/definition.d.ts.map +0 -1
  707. package/dist/adapter/z-stack/znp/definition.js +0 -3052
  708. package/dist/adapter/z-stack/znp/definition.js.map +0 -1
  709. package/dist/adapter/z-stack/znp/index.d.ts +0 -4
  710. package/dist/adapter/z-stack/znp/index.d.ts.map +0 -1
  711. package/dist/adapter/z-stack/znp/index.js +0 -11
  712. package/dist/adapter/z-stack/znp/index.js.map +0 -1
  713. package/dist/adapter/z-stack/znp/parameterType.d.ts +0 -23
  714. package/dist/adapter/z-stack/znp/parameterType.d.ts.map +0 -1
  715. package/dist/adapter/z-stack/znp/parameterType.js +0 -26
  716. package/dist/adapter/z-stack/znp/parameterType.js.map +0 -1
  717. package/dist/adapter/z-stack/znp/tstype.d.ts +0 -23
  718. package/dist/adapter/z-stack/znp/tstype.d.ts.map +0 -1
  719. package/dist/adapter/z-stack/znp/tstype.js +0 -3
  720. package/dist/adapter/z-stack/znp/tstype.js.map +0 -1
  721. package/dist/adapter/z-stack/znp/znp.d.ts +0 -47
  722. package/dist/adapter/z-stack/znp/znp.d.ts.map +0 -1
  723. package/dist/adapter/z-stack/znp/znp.js +0 -322
  724. package/dist/adapter/z-stack/znp/znp.js.map +0 -1
  725. package/dist/adapter/z-stack/znp/zpiObject.d.ts +0 -20
  726. package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +0 -1
  727. package/dist/adapter/z-stack/znp/zpiObject.js +0 -103
  728. package/dist/adapter/z-stack/znp/zpiObject.js.map +0 -1
  729. package/dist/adapter/zigate/adapter/index.d.ts +0 -3
  730. package/dist/adapter/zigate/adapter/index.d.ts.map +0 -1
  731. package/dist/adapter/zigate/adapter/index.js +0 -11
  732. package/dist/adapter/zigate/adapter/index.js.map +0 -1
  733. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +0 -72
  734. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +0 -1
  735. package/dist/adapter/zigate/adapter/zigateAdapter.js +0 -681
  736. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +0 -1
  737. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts +0 -18
  738. package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +0 -1
  739. package/dist/adapter/zigate/driver/buffaloZiGate.js +0 -190
  740. package/dist/adapter/zigate/driver/buffaloZiGate.js.map +0 -1
  741. package/dist/adapter/zigate/driver/commandType.d.ts +0 -43
  742. package/dist/adapter/zigate/driver/commandType.d.ts.map +0 -1
  743. package/dist/adapter/zigate/driver/commandType.js +0 -390
  744. package/dist/adapter/zigate/driver/commandType.js.map +0 -1
  745. package/dist/adapter/zigate/driver/constants.d.ts +0 -277
  746. package/dist/adapter/zigate/driver/constants.d.ts.map +0 -1
  747. package/dist/adapter/zigate/driver/constants.js +0 -372
  748. package/dist/adapter/zigate/driver/constants.js.map +0 -1
  749. package/dist/adapter/zigate/driver/frame.d.ts +0 -27
  750. package/dist/adapter/zigate/driver/frame.d.ts.map +0 -1
  751. package/dist/adapter/zigate/driver/frame.js +0 -173
  752. package/dist/adapter/zigate/driver/frame.js.map +0 -1
  753. package/dist/adapter/zigate/driver/messageType.d.ts +0 -13
  754. package/dist/adapter/zigate/driver/messageType.d.ts.map +0 -1
  755. package/dist/adapter/zigate/driver/messageType.js +0 -284
  756. package/dist/adapter/zigate/driver/messageType.js.map +0 -1
  757. package/dist/adapter/zigate/driver/parameterType.d.ts +0 -28
  758. package/dist/adapter/zigate/driver/parameterType.d.ts.map +0 -1
  759. package/dist/adapter/zigate/driver/parameterType.js +0 -33
  760. package/dist/adapter/zigate/driver/parameterType.js.map +0 -1
  761. package/dist/adapter/zigate/driver/ziGateObject.d.ts +0 -24
  762. package/dist/adapter/zigate/driver/ziGateObject.d.ts.map +0 -1
  763. package/dist/adapter/zigate/driver/ziGateObject.js +0 -111
  764. package/dist/adapter/zigate/driver/ziGateObject.js.map +0 -1
  765. package/dist/adapter/zigate/driver/zigate.d.ts +0 -50
  766. package/dist/adapter/zigate/driver/zigate.d.ts.map +0 -1
  767. package/dist/adapter/zigate/driver/zigate.js +0 -289
  768. package/dist/adapter/zigate/driver/zigate.js.map +0 -1
  769. package/dist/buffalo/buffalo.d.ts +0 -55
  770. package/dist/buffalo/buffalo.d.ts.map +0 -1
  771. package/dist/buffalo/buffalo.js +0 -230
  772. package/dist/buffalo/buffalo.js.map +0 -1
  773. package/dist/buffalo/index.d.ts +0 -3
  774. package/dist/buffalo/index.d.ts.map +0 -1
  775. package/dist/buffalo/index.js +0 -9
  776. package/dist/buffalo/index.js.map +0 -1
  777. package/dist/controller/controller.d.ts +0 -119
  778. package/dist/controller/controller.d.ts.map +0 -1
  779. package/dist/controller/controller.js +0 -700
  780. package/dist/controller/controller.js.map +0 -1
  781. package/dist/controller/database.d.ts +0 -20
  782. package/dist/controller/database.d.ts.map +0 -1
  783. package/dist/controller/database.js +0 -94
  784. package/dist/controller/database.js.map +0 -1
  785. package/dist/controller/events.d.ts +0 -59
  786. package/dist/controller/events.d.ts.map +0 -1
  787. package/dist/controller/events.js +0 -113
  788. package/dist/controller/events.js.map +0 -1
  789. package/dist/controller/greenPower.d.ts +0 -14
  790. package/dist/controller/greenPower.d.ts.map +0 -1
  791. package/dist/controller/greenPower.js +0 -216
  792. package/dist/controller/greenPower.js.map +0 -1
  793. package/dist/controller/helpers/index.d.ts +0 -3
  794. package/dist/controller/helpers/index.d.ts.map +0 -1
  795. package/dist/controller/helpers/index.js +0 -29
  796. package/dist/controller/helpers/index.js.map +0 -1
  797. package/dist/controller/helpers/request.d.ts +0 -22
  798. package/dist/controller/helpers/request.d.ts.map +0 -1
  799. package/dist/controller/helpers/request.js +0 -78
  800. package/dist/controller/helpers/request.js.map +0 -1
  801. package/dist/controller/helpers/requestQueue.d.ts +0 -13
  802. package/dist/controller/helpers/requestQueue.d.ts.map +0 -1
  803. package/dist/controller/helpers/requestQueue.js +0 -106
  804. package/dist/controller/helpers/requestQueue.js.map +0 -1
  805. package/dist/controller/helpers/zclFrameConverter.d.ts +0 -9
  806. package/dist/controller/helpers/zclFrameConverter.d.ts.map +0 -1
  807. package/dist/controller/helpers/zclFrameConverter.js +0 -70
  808. package/dist/controller/helpers/zclFrameConverter.js.map +0 -1
  809. package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts +0 -6
  810. package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts.map +0 -1
  811. package/dist/controller/helpers/zclTransactionSequenceNumber.js +0 -14
  812. package/dist/controller/helpers/zclTransactionSequenceNumber.js.map +0 -1
  813. package/dist/controller/index.d.ts +0 -6
  814. package/dist/controller/index.d.ts.map +0 -1
  815. package/dist/controller/index.js +0 -9
  816. package/dist/controller/index.js.map +0 -1
  817. package/dist/controller/model/device.d.ts +0 -140
  818. package/dist/controller/model/device.d.ts.map +0 -1
  819. package/dist/controller/model/device.js +0 -746
  820. package/dist/controller/model/device.js.map +0 -1
  821. package/dist/controller/model/endpoint.d.ts +0 -134
  822. package/dist/controller/model/endpoint.d.ts.map +0 -1
  823. package/dist/controller/model/endpoint.js +0 -667
  824. package/dist/controller/model/endpoint.js.map +0 -1
  825. package/dist/controller/model/entity.d.ts +0 -15
  826. package/dist/controller/model/entity.d.ts.map +0 -1
  827. package/dist/controller/model/entity.js +0 -27
  828. package/dist/controller/model/entity.js.map +0 -1
  829. package/dist/controller/model/group.d.ts +0 -39
  830. package/dist/controller/model/group.d.ts.map +0 -1
  831. package/dist/controller/model/group.js +0 -226
  832. package/dist/controller/model/group.js.map +0 -1
  833. package/dist/controller/model/index.d.ts +0 -6
  834. package/dist/controller/model/index.d.ts.map +0 -1
  835. package/dist/controller/model/index.js +0 -15
  836. package/dist/controller/model/index.js.map +0 -1
  837. package/dist/controller/model/konnextConfig.d.ts +0 -7
  838. package/dist/controller/model/konnextConfig.d.ts.map +0 -1
  839. package/dist/controller/model/konnextConfig.js +0 -3
  840. package/dist/controller/model/konnextConfig.js.map +0 -1
  841. package/dist/controller/touchlink.d.ts +0 -20
  842. package/dist/controller/touchlink.d.ts.map +0 -1
  843. package/dist/controller/touchlink.js +0 -157
  844. package/dist/controller/touchlink.js.map +0 -1
  845. package/dist/controller/tstype.d.ts +0 -21
  846. package/dist/controller/tstype.d.ts.map +0 -1
  847. package/dist/controller/tstype.js +0 -9
  848. package/dist/controller/tstype.js.map +0 -1
  849. package/dist/index.d.ts +0 -6
  850. package/dist/index.d.ts.map +0 -1
  851. package/dist/index.js +0 -37
  852. package/dist/index.js.map +0 -1
  853. package/dist/models/backup-storage-legacy.d.ts +0 -27
  854. package/dist/models/backup-storage-legacy.d.ts.map +0 -1
  855. package/dist/models/backup-storage-legacy.js +0 -3
  856. package/dist/models/backup-storage-legacy.js.map +0 -1
  857. package/dist/models/backup-storage-unified.d.ts +0 -50
  858. package/dist/models/backup-storage-unified.d.ts.map +0 -1
  859. package/dist/models/backup-storage-unified.js +0 -3
  860. package/dist/models/backup-storage-unified.js.map +0 -1
  861. package/dist/models/backup.d.ts +0 -38
  862. package/dist/models/backup.d.ts.map +0 -1
  863. package/dist/models/backup.js +0 -3
  864. package/dist/models/backup.js.map +0 -1
  865. package/dist/models/index.d.ts +0 -5
  866. package/dist/models/index.d.ts.map +0 -1
  867. package/dist/models/index.js +0 -21
  868. package/dist/models/index.js.map +0 -1
  869. package/dist/models/network-options.d.ts +0 -13
  870. package/dist/models/network-options.d.ts.map +0 -1
  871. package/dist/models/network-options.js +0 -3
  872. package/dist/models/network-options.js.map +0 -1
  873. package/dist/utils/aes.d.ts +0 -40
  874. package/dist/utils/aes.d.ts.map +0 -1
  875. package/dist/utils/aes.js +0 -198
  876. package/dist/utils/aes.js.map +0 -1
  877. package/dist/utils/assertString.d.ts +0 -3
  878. package/dist/utils/assertString.d.ts.map +0 -1
  879. package/dist/utils/assertString.js +0 -9
  880. package/dist/utils/assertString.js.map +0 -1
  881. package/dist/utils/backup.d.ts +0 -21
  882. package/dist/utils/backup.d.ts.map +0 -1
  883. package/dist/utils/backup.js +0 -190
  884. package/dist/utils/backup.js.map +0 -1
  885. package/dist/utils/equalsPartial.d.ts +0 -3
  886. package/dist/utils/equalsPartial.d.ts.map +0 -1
  887. package/dist/utils/equalsPartial.js +0 -12
  888. package/dist/utils/equalsPartial.js.map +0 -1
  889. package/dist/utils/index.d.ts +0 -10
  890. package/dist/utils/index.d.ts.map +0 -1
  891. package/dist/utils/index.js +0 -46
  892. package/dist/utils/index.js.map +0 -1
  893. package/dist/utils/isNumberArray.d.ts +0 -3
  894. package/dist/utils/isNumberArray.d.ts.map +0 -1
  895. package/dist/utils/isNumberArray.js +0 -7
  896. package/dist/utils/isNumberArray.js.map +0 -1
  897. package/dist/utils/logger.d.ts +0 -9
  898. package/dist/utils/logger.d.ts.map +0 -1
  899. package/dist/utils/logger.js +0 -14
  900. package/dist/utils/logger.js.map +0 -1
  901. package/dist/utils/queue.d.ts +0 -12
  902. package/dist/utils/queue.d.ts.map +0 -1
  903. package/dist/utils/queue.js +0 -62
  904. package/dist/utils/queue.js.map +0 -1
  905. package/dist/utils/realpathSync.d.ts +0 -3
  906. package/dist/utils/realpathSync.d.ts.map +0 -1
  907. package/dist/utils/realpathSync.js +0 -13
  908. package/dist/utils/realpathSync.js.map +0 -1
  909. package/dist/utils/wait.d.ts +0 -3
  910. package/dist/utils/wait.d.ts.map +0 -1
  911. package/dist/utils/wait.js +0 -9
  912. package/dist/utils/wait.js.map +0 -1
  913. package/dist/utils/waitress.d.ts +0 -22
  914. package/dist/utils/waitress.d.ts.map +0 -1
  915. package/dist/utils/waitress.js +0 -69
  916. package/dist/utils/waitress.js.map +0 -1
  917. package/dist/zspec/consts.d.ts +0 -60
  918. package/dist/zspec/consts.d.ts.map +0 -1
  919. package/dist/zspec/consts.js +0 -64
  920. package/dist/zspec/consts.js.map +0 -1
  921. package/dist/zspec/enums.d.ts +0 -19
  922. package/dist/zspec/enums.d.ts.map +0 -1
  923. package/dist/zspec/enums.js +0 -28
  924. package/dist/zspec/enums.js.map +0 -1
  925. package/dist/zspec/index.d.ts +0 -4
  926. package/dist/zspec/index.d.ts.map +0 -1
  927. package/dist/zspec/index.js +0 -43
  928. package/dist/zspec/index.js.map +0 -1
  929. package/dist/zspec/tstypes.d.ts +0 -19
  930. package/dist/zspec/tstypes.d.ts.map +0 -1
  931. package/dist/zspec/tstypes.js +0 -3
  932. package/dist/zspec/tstypes.js.map +0 -1
  933. package/dist/zspec/utils.d.ts +0 -14
  934. package/dist/zspec/utils.d.ts.map +0 -1
  935. package/dist/zspec/utils.js +0 -29
  936. package/dist/zspec/utils.js.map +0 -1
  937. package/dist/zspec/zcl/buffaloZcl.d.ts +0 -55
  938. package/dist/zspec/zcl/buffaloZcl.d.ts.map +0 -1
  939. package/dist/zspec/zcl/buffaloZcl.js +0 -929
  940. package/dist/zspec/zcl/buffaloZcl.js.map +0 -1
  941. package/dist/zspec/zcl/definition/cluster.d.ts +0 -3
  942. package/dist/zspec/zcl/definition/cluster.d.ts.map +0 -1
  943. package/dist/zspec/zcl/definition/cluster.js +0 -5500
  944. package/dist/zspec/zcl/definition/cluster.js.map +0 -1
  945. package/dist/zspec/zcl/definition/consts.d.ts +0 -9
  946. package/dist/zspec/zcl/definition/consts.d.ts.map +0 -1
  947. package/dist/zspec/zcl/definition/consts.js +0 -27
  948. package/dist/zspec/zcl/definition/consts.js.map +0 -1
  949. package/dist/zspec/zcl/definition/enums.d.ts +0 -177
  950. package/dist/zspec/zcl/definition/enums.d.ts.map +0 -1
  951. package/dist/zspec/zcl/definition/enums.js +0 -187
  952. package/dist/zspec/zcl/definition/enums.js.map +0 -1
  953. package/dist/zspec/zcl/definition/foundation.d.ts +0 -11
  954. package/dist/zspec/zcl/definition/foundation.d.ts.map +0 -1
  955. package/dist/zspec/zcl/definition/foundation.js +0 -241
  956. package/dist/zspec/zcl/definition/foundation.js.map +0 -1
  957. package/dist/zspec/zcl/definition/manufacturerCode.d.ts +0 -727
  958. package/dist/zspec/zcl/definition/manufacturerCode.d.ts.map +0 -1
  959. package/dist/zspec/zcl/definition/manufacturerCode.js +0 -733
  960. package/dist/zspec/zcl/definition/manufacturerCode.js.map +0 -1
  961. package/dist/zspec/zcl/definition/status.d.ts +0 -69
  962. package/dist/zspec/zcl/definition/status.d.ts.map +0 -1
  963. package/dist/zspec/zcl/definition/status.js +0 -74
  964. package/dist/zspec/zcl/definition/status.js.map +0 -1
  965. package/dist/zspec/zcl/definition/tstype.d.ts +0 -114
  966. package/dist/zspec/zcl/definition/tstype.d.ts.map +0 -1
  967. package/dist/zspec/zcl/definition/tstype.js +0 -4
  968. package/dist/zspec/zcl/definition/tstype.js.map +0 -1
  969. package/dist/zspec/zcl/index.d.ts +0 -11
  970. package/dist/zspec/zcl/index.d.ts.map +0 -1
  971. package/dist/zspec/zcl/index.js +0 -47
  972. package/dist/zspec/zcl/index.js.map +0 -1
  973. package/dist/zspec/zcl/utils.d.ts +0 -7
  974. package/dist/zspec/zcl/utils.d.ts.map +0 -1
  975. package/dist/zspec/zcl/utils.js +0 -234
  976. package/dist/zspec/zcl/utils.js.map +0 -1
  977. package/dist/zspec/zcl/zclFrame.d.ts +0 -36
  978. package/dist/zspec/zcl/zclFrame.d.ts.map +0 -1
  979. package/dist/zspec/zcl/zclFrame.js +0 -304
  980. package/dist/zspec/zcl/zclFrame.js.map +0 -1
  981. package/dist/zspec/zcl/zclHeader.d.ts +0 -17
  982. package/dist/zspec/zcl/zclHeader.d.ts.map +0 -1
  983. package/dist/zspec/zcl/zclHeader.js +0 -88
  984. package/dist/zspec/zcl/zclHeader.js.map +0 -1
  985. package/dist/zspec/zcl/zclStatusError.d.ts +0 -6
  986. package/dist/zspec/zcl/zclStatusError.d.ts.map +0 -1
  987. package/dist/zspec/zcl/zclStatusError.js +0 -13
  988. package/dist/zspec/zcl/zclStatusError.js.map +0 -1
  989. package/dist/zspec/zdo/buffaloZdo.d.ts +0 -438
  990. package/dist/zspec/zdo/buffaloZdo.d.ts.map +0 -1
  991. package/dist/zspec/zdo/buffaloZdo.js +0 -1892
  992. package/dist/zspec/zdo/buffaloZdo.js.map +0 -1
  993. package/dist/zspec/zdo/definition/clusters.d.ts +0 -624
  994. package/dist/zspec/zdo/definition/clusters.d.ts.map +0 -1
  995. package/dist/zspec/zdo/definition/clusters.js +0 -687
  996. package/dist/zspec/zdo/definition/clusters.js.map +0 -1
  997. package/dist/zspec/zdo/definition/consts.d.ts +0 -13
  998. package/dist/zspec/zdo/definition/consts.d.ts.map +0 -1
  999. package/dist/zspec/zdo/definition/consts.js +0 -16
  1000. package/dist/zspec/zdo/definition/consts.js.map +0 -1
  1001. package/dist/zspec/zdo/definition/enums.d.ts +0 -75
  1002. package/dist/zspec/zdo/definition/enums.d.ts.map +0 -1
  1003. package/dist/zspec/zdo/definition/enums.js +0 -97
  1004. package/dist/zspec/zdo/definition/enums.js.map +0 -1
  1005. package/dist/zspec/zdo/definition/status.d.ts +0 -99
  1006. package/dist/zspec/zdo/definition/status.d.ts.map +0 -1
  1007. package/dist/zspec/zdo/definition/status.js +0 -109
  1008. package/dist/zspec/zdo/definition/status.js.map +0 -1
  1009. package/dist/zspec/zdo/definition/tstypes.d.ts +0 -787
  1010. package/dist/zspec/zdo/definition/tstypes.d.ts.map +0 -1
  1011. package/dist/zspec/zdo/definition/tstypes.js +0 -3
  1012. package/dist/zspec/zdo/definition/tstypes.js.map +0 -1
  1013. package/dist/zspec/zdo/index.d.ts +0 -7
  1014. package/dist/zspec/zdo/index.d.ts.map +0 -1
  1015. package/dist/zspec/zdo/index.js +0 -39
  1016. package/dist/zspec/zdo/index.js.map +0 -1
  1017. package/dist/zspec/zdo/utils.d.ts +0 -25
  1018. package/dist/zspec/zdo/utils.d.ts.map +0 -1
  1019. package/dist/zspec/zdo/utils.js +0 -75
  1020. package/dist/zspec/zdo/utils.js.map +0 -1
  1021. package/dist/zspec/zdo/zdoStatusError.d.ts +0 -6
  1022. package/dist/zspec/zdo/zdoStatusError.d.ts.map +0 -1
  1023. package/dist/zspec/zdo/zdoStatusError.js +0 -13
  1024. package/dist/zspec/zdo/zdoStatusError.js.map +0 -1
  1025. package/typedoc-tsconfig.json +0 -44
@@ -0,0 +1,2262 @@
1
+ import {randomBytes} from "node:crypto";
2
+ import {readFileSync, renameSync} from "node:fs";
3
+ import path from "node:path";
4
+
5
+ import equals from "fast-deep-equal/es6";
6
+ import type {Backup} from "../../../models";
7
+ import {BackupUtils, Queue, wait} from "../../../utils";
8
+ import {logger} from "../../../utils/logger";
9
+ import * as ZSpec from "../../../zspec";
10
+ import type {Eui64, ExtendedPanId, NodeId, PanId} from "../../../zspec/tstypes";
11
+ import * as Zcl from "../../../zspec/zcl";
12
+ import * as Zdo from "../../../zspec/zdo";
13
+ import type * as ZdoTypes from "../../../zspec/zdo/definition/tstypes";
14
+ import {Adapter, type TsType} from "../..";
15
+ import {WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE} from "../../const";
16
+ import type {DeviceJoinedPayload, DeviceLeavePayload, ZclPayload} from "../../events";
17
+ import {readBackup} from "../../utils";
18
+ import {
19
+ EMBER_HIGH_RAM_CONCENTRATOR,
20
+ EMBER_LOW_RAM_CONCENTRATOR,
21
+ EMBER_MIN_BROADCAST_ADDRESS,
22
+ INTERPAN_APS_FRAME_TYPE,
23
+ INVALID_RADIO_CHANNEL,
24
+ LONG_DEST_FRAME_CONTROL,
25
+ MAC_ACK_REQUIRED,
26
+ MAXIMUM_INTERPAN_LENGTH,
27
+ SECURITY_LEVEL_Z3,
28
+ SHORT_DEST_FRAME_CONTROL,
29
+ STACK_PROFILE_ZIGBEE_PRO,
30
+ STUB_NWK_FRAME_CONTROL,
31
+ ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY,
32
+ } from "../consts";
33
+ import {
34
+ EmberApsOption,
35
+ EmberDeviceUpdate,
36
+ EmberExtendedSecurityBitmask,
37
+ EmberIncomingMessageType,
38
+ EmberInitialSecurityBitmask,
39
+ EmberInterpanMessageType,
40
+ EmberJoinDecision,
41
+ EmberJoinMethod,
42
+ EmberNetworkInitBitmask,
43
+ EmberNetworkStatus,
44
+ EmberNodeType,
45
+ EmberOutgoingMessageType,
46
+ EmberSourceRouteDiscoveryMode,
47
+ EmberTransmitPriority,
48
+ EmberVersionType,
49
+ EzspStatus,
50
+ IEEE802154CcaMode,
51
+ SecManKeyType,
52
+ SLStatus,
53
+ } from "../enums";
54
+ import {EzspBuffalo} from "../ezsp/buffalo";
55
+ import {EMBER_ENCRYPTION_KEY_SIZE, EZSP_MIN_PROTOCOL_VERSION, EZSP_PROTOCOL_VERSION, EZSP_STACK_TYPE_MESH} from "../ezsp/consts";
56
+ import {EzspConfigId, EzspDecisionBitmask, EzspDecisionId, EzspPolicyId, EzspValueId} from "../ezsp/enums";
57
+ import {Ezsp} from "../ezsp/ezsp";
58
+ import {EzspError} from "../ezspError";
59
+ import type {
60
+ EmberApsFrame,
61
+ EmberInitialSecurityState,
62
+ EmberKeyData,
63
+ EmberMulticastId,
64
+ EmberMulticastTableEntry,
65
+ EmberNetworkInitStruct,
66
+ EmberNetworkParameters,
67
+ EmberVersion,
68
+ SecManAPSKeyMetadata,
69
+ SecManContext,
70
+ SecManKey,
71
+ } from "../types";
72
+ import {initNetworkCache, initSecurityManagerContext} from "../utils/initters";
73
+ import {lowHighBytes} from "../utils/math";
74
+ import {FIXED_ENDPOINTS} from "./endpoints";
75
+ import {EmberOneWaitress, OneWaitressEvents} from "./oneWaitress";
76
+
77
+ const NS = "zh:ember";
78
+
79
+ export type NetworkCache = {
80
+ //-- basic network info
81
+ eui64: Eui64;
82
+ parameters: EmberNetworkParameters;
83
+ };
84
+
85
+ /**
86
+ * Use for a link key backup.
87
+ *
88
+ * Each entry notes the EUI64 of the device it is paired to and the key data.
89
+ * This key may be hashed and not the actual link key currently in use.
90
+ */
91
+ export type LinkKeyBackupData = {
92
+ deviceEui64: Eui64;
93
+ key: EmberKeyData;
94
+ outgoingFrameCounter: number;
95
+ incomingFrameCounter: number;
96
+ };
97
+
98
+ enum NetworkInitAction {
99
+ /** Ain't that nice! */
100
+ DONE = 0,
101
+ /** Config mismatch, must leave network. */
102
+ LEAVE = 1,
103
+ /** Config mismatched, left network. Will evaluate forming from backup or config next. */
104
+ LEFT = 2,
105
+ /** Form the network using config. No backup, or backup mismatch. */
106
+ FORM_CONFIG = 3,
107
+ /** Re-form the network using full backed-up data. */
108
+ FORM_BACKUP = 4,
109
+ }
110
+
111
+ /**
112
+ * Application generated ZDO messages use sequence numbers 0-127, and the stack
113
+ * uses sequence numbers 128-255. This simplifies life by eliminating the need
114
+ * for coordination between the two entities, and allows both to send ZDO
115
+ * messages with non-conflicting sequence numbers.
116
+ */
117
+ const APPLICATION_ZDO_SEQUENCE_MASK = 0x7f;
118
+ /* Default radius used for broadcast ZDO requests. uint8_t */
119
+ const ZDO_REQUEST_RADIUS = 0xff;
120
+ /** Oldest supported EZSP version for backups. Don't take the risk to restore a broken network until older backup versions can be investigated. */
121
+ const BACKUP_OLDEST_SUPPORTED_EZSP_VERSION = 12;
122
+ /**
123
+ * 9sec is minimum recommended for `ezspBroadcastNextNetworkKey` to have propagated throughout network.
124
+ * NOTE: This is blocking the request queue, so we shouldn't go crazy high.
125
+ */
126
+ const BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME = 15000;
127
+
128
+ const QUEUE_MAX_SEND_ATTEMPTS = 3;
129
+ const QUEUE_BUSY_DEFER_MSEC = 500;
130
+ const QUEUE_NETWORK_DOWN_DEFER_MSEC = 1500;
131
+
132
+ type StackConfig = {
133
+ CONCENTRATOR_RAM_TYPE: "high" | "low";
134
+ /**
135
+ * Minimum Time between broadcasts (in seconds) <1-60>
136
+ * Default: 10
137
+ * The minimum amount of time that must pass between MTORR broadcasts.
138
+ */
139
+ CONCENTRATOR_MIN_TIME: number;
140
+ /**
141
+ * Maximum Time between broadcasts (in seconds) <30-300>
142
+ * Default: 60
143
+ * The maximum amount of time that can pass between MTORR broadcasts.
144
+ */
145
+ CONCENTRATOR_MAX_TIME: number;
146
+ /**
147
+ * Route Error Threshold <1-100>
148
+ * Default: 3
149
+ * The number of route errors that will trigger a re-broadcast of the MTORR.
150
+ */
151
+ CONCENTRATOR_ROUTE_ERROR_THRESHOLD: number;
152
+ /**
153
+ * Delivery Failure Threshold <1-100>
154
+ * Default: 1
155
+ * The number of APS delivery failures that will trigger a re-broadcast of the MTORR.
156
+ */
157
+ CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD: number;
158
+ /**
159
+ * Maximum number of hops for Broadcast <0-30>
160
+ * Default: 0
161
+ * The maximum number of hops that the MTORR broadcast will be allowed to have.
162
+ * A value of 0 will be converted to the EMBER_MAX_HOPS value set by the stack.
163
+ */
164
+ CONCENTRATOR_MAX_HOPS: number;
165
+ /** <6-64> (Default: 6) @see EzspConfigId.MAX_END_DEVICE_CHILDREN */
166
+ MAX_END_DEVICE_CHILDREN: number;
167
+ /** <-> (Default: 10000) @see EzspValueId.TRANSIENT_DEVICE_TIMEOUT */
168
+ TRANSIENT_DEVICE_TIMEOUT: number;
169
+ /** <0-14> (Default: 8) @see EzspConfigId.END_DEVICE_POLL_TIMEOUT */
170
+ END_DEVICE_POLL_TIMEOUT: number;
171
+ /** <0-65535> (Default: 300) @see EzspConfigId.TRANSIENT_KEY_TIMEOUT_S */
172
+ TRANSIENT_KEY_TIMEOUT_S: number;
173
+ /**@see Ezsp.ezspSetRadioIeee802154CcaMode */
174
+ CCA_MODE?: keyof typeof IEEE802154CcaMode;
175
+ };
176
+
177
+ /**
178
+ * Default stack configuration values.
179
+ * @see https://www.silabs.com/documents/public/user-guides/ug100-ezsp-reference-guide.pdf 2.3.1 for descriptions/RAM costs
180
+ *
181
+ * https://github.com/darkxst/silabs-firmware-builder/tree/main/manifests
182
+ * https://github.com/NabuCasa/silabs-firmware/wiki/Zigbee-EmberZNet-NCP-firmware-configuration#skyconnect
183
+ * https://github.com/SiliconLabs/UnifySDK/blob/main/applications/zigbeed/project_files/zigbeed.slcp
184
+ */
185
+ export const DEFAULT_STACK_CONFIG: Readonly<StackConfig> = {
186
+ CONCENTRATOR_RAM_TYPE: "high",
187
+ CONCENTRATOR_MIN_TIME: 5, // zigpc: 10
188
+ CONCENTRATOR_MAX_TIME: 60, // zigpc: 60
189
+ CONCENTRATOR_ROUTE_ERROR_THRESHOLD: 3, // zigpc: 3
190
+ CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD: 1, // zigpc: 1, ZigbeeMinimalHost: 3
191
+ CONCENTRATOR_MAX_HOPS: 0, // zigpc: 0
192
+ MAX_END_DEVICE_CHILDREN: 32, // zigpc: 6, nabucasa: 32, Dongle-E (Sonoff firmware): 32
193
+ TRANSIENT_DEVICE_TIMEOUT: 10000,
194
+ END_DEVICE_POLL_TIMEOUT: 8, // zigpc: 8
195
+ TRANSIENT_KEY_TIMEOUT_S: 300, // zigpc: 65535
196
+ CCA_MODE: undefined, // not set by default
197
+ };
198
+ /** Default behavior is to disable app key requests */
199
+ const ALLOW_APP_KEY_REQUESTS = false;
200
+ /** @see EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE */
201
+ const TRUST_CENTER_ADDRESS_CACHE_SIZE = 2;
202
+
203
+ /**
204
+ * NOTE: This from SDK is currently ignored here because of issues in below links:
205
+ * - BUGZID 12261: Concentrators use MTORRs for route discovery and should not enable route discovery in the APS options.
206
+ * - https://community.silabs.com/s/question/0D58Y00008DRfDCSA1/coordinator-cant-send-unicast-to-sleepy-node-after-reboot
207
+ * - https://community.silabs.com/s/question/0D58Y0000B4nTb7SQE/largedense-network-communication-problem-source-route-table-not-big-enough
208
+ *
209
+ * Removing `ENABLE_ROUTE_DISCOVERY` leads to devices that won't reconnect/go offline, and various other issues. Keeping it for now.
210
+ */
211
+ export const DEFAULT_APS_OPTIONS = EmberApsOption.RETRY | EmberApsOption.ENABLE_ROUTE_DISCOVERY | EmberApsOption.ENABLE_ADDRESS_DISCOVERY;
212
+ /** Time for a request to get a callback response. ASH is 2400*6 for ACK timeout. */
213
+ const DEFAULT_REQUEST_TIMEOUT = 15000; // msec
214
+ /** Time for a network-related request to get a response (usually via event). */
215
+ const DEFAULT_NETWORK_REQUEST_TIMEOUT = 10000; // nothing on the network to bother requests, should be much faster than this
216
+ /** Time between watchdog counters reading/clearing */
217
+ const WATCHDOG_COUNTERS_FEED_INTERVAL = 3600000; // every hour...
218
+ /** Default manufacturer code reported by coordinator. */
219
+ const DEFAULT_MANUFACTURER_CODE = Zcl.ManufacturerCode.SILICON_LABORATORIES;
220
+
221
+ /**
222
+ * Relay calls between Z2M and EZSP-layer and handle any error that might occur via queue & waitress.
223
+ *
224
+ * Anything post `start` that requests anything from the EZSP layer must run through the request queue for proper execution flow.
225
+ */
226
+ export class EmberAdapter extends Adapter {
227
+ /** Current manufacturer code assigned to the coordinator. Used for join workarounds... */
228
+ private manufacturerCode: Zcl.ManufacturerCode;
229
+ public readonly stackConfig: StackConfig;
230
+
231
+ private ezsp: Ezsp;
232
+ private version: {ezsp: number; revision: string} & EmberVersion;
233
+
234
+ private readonly queue: Queue;
235
+ private readonly oneWaitress: EmberOneWaitress;
236
+ /** Periodically retrieve counters then clear them. */
237
+ private watchdogCountersHandle?: NodeJS.Timeout;
238
+
239
+ /** Sequence number used for ZDO requests. static uint8_t */
240
+ private zdoRequestSequence: number;
241
+
242
+ private interpanLock: boolean;
243
+
244
+ /**
245
+ * Cached network params to avoid NCP calls. Prevents frequent EZSP transactions.
246
+ * NOTE: Do not use directly, use getter functions for it that check if valid or need retrieval from NCP.
247
+ */
248
+ private networkCache: NetworkCache;
249
+ private multicastTable: EmberMulticastId[];
250
+
251
+ constructor(
252
+ networkOptions: TsType.NetworkOptions,
253
+ serialPortOptions: TsType.SerialPortOptions,
254
+ backupPath: string,
255
+ adapterOptions: TsType.AdapterOptions,
256
+ ) {
257
+ super(networkOptions, serialPortOptions, backupPath, adapterOptions);
258
+ this.hasZdoMessageOverhead = true;
259
+ this.manufacturerID = Zcl.ManufacturerCode.SILICON_LABORATORIES;
260
+
261
+ this.version = {
262
+ ezsp: 0,
263
+ revision: "unknown",
264
+ build: 0,
265
+ major: 0,
266
+ minor: 0,
267
+ patch: 0,
268
+ special: 0,
269
+ type: EmberVersionType.GA,
270
+ };
271
+ this.zdoRequestSequence = 0; // start at 1
272
+ this.interpanLock = false;
273
+ this.networkCache = initNetworkCache();
274
+ this.manufacturerCode = DEFAULT_MANUFACTURER_CODE; // will be set in NCP in initEzsp
275
+ this.multicastTable = [];
276
+
277
+ this.stackConfig = this.loadStackConfig();
278
+ this.queue = new Queue(this.adapterOptions.concurrent || 16); // ORed to avoid 0 (not checked in settings/queue constructor)
279
+ this.oneWaitress = new EmberOneWaitress();
280
+
281
+ this.ezsp = new Ezsp(serialPortOptions);
282
+
283
+ this.ezsp.on("zdoResponse", this.onZDOResponse.bind(this));
284
+ this.ezsp.on("incomingMessage", this.onIncomingMessage.bind(this));
285
+ this.ezsp.on("touchlinkMessage", this.onTouchlinkMessage.bind(this));
286
+ this.ezsp.on("stackStatus", this.onStackStatus.bind(this));
287
+ this.ezsp.on("trustCenterJoin", this.onTrustCenterJoin.bind(this));
288
+ this.ezsp.on("messageSent", this.onMessageSent.bind(this));
289
+ this.ezsp.once("ncpNeedsResetAndInit", this.onNcpNeedsResetAndInit.bind(this));
290
+ }
291
+
292
+ private loadStackConfig(): StackConfig {
293
+ // store stack config in same dir as backup
294
+ const configPath = path.join(path.dirname(this.backupPath), "stack_config.json");
295
+
296
+ try {
297
+ const customConfig: StackConfig = JSON.parse(readFileSync(configPath, "utf8"));
298
+ // set any undefined config to default
299
+ const config: StackConfig = {...DEFAULT_STACK_CONFIG, ...customConfig};
300
+
301
+ const inRange = (value: number, min: number, max: number): boolean => !(value == null || value < min || value > max);
302
+
303
+ if (!["high", "low"].includes(config.CONCENTRATOR_RAM_TYPE)) {
304
+ config.CONCENTRATOR_RAM_TYPE = DEFAULT_STACK_CONFIG.CONCENTRATOR_RAM_TYPE;
305
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_RAM_TYPE, using default.", NS);
306
+ }
307
+
308
+ if (!inRange(config.CONCENTRATOR_MIN_TIME, 1, 60) || config.CONCENTRATOR_MIN_TIME >= config.CONCENTRATOR_MAX_TIME) {
309
+ config.CONCENTRATOR_MIN_TIME = DEFAULT_STACK_CONFIG.CONCENTRATOR_MIN_TIME;
310
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MIN_TIME, using default.", NS);
311
+ }
312
+
313
+ if (!inRange(config.CONCENTRATOR_MAX_TIME, 30, 300) || config.CONCENTRATOR_MAX_TIME <= config.CONCENTRATOR_MIN_TIME) {
314
+ config.CONCENTRATOR_MAX_TIME = DEFAULT_STACK_CONFIG.CONCENTRATOR_MAX_TIME;
315
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MAX_TIME, using default.", NS);
316
+ }
317
+
318
+ if (!inRange(config.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, 1, 100)) {
319
+ config.CONCENTRATOR_ROUTE_ERROR_THRESHOLD = DEFAULT_STACK_CONFIG.CONCENTRATOR_ROUTE_ERROR_THRESHOLD;
320
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_ROUTE_ERROR_THRESHOLD, using default.", NS);
321
+ }
322
+
323
+ if (!inRange(config.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, 1, 100)) {
324
+ config.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD = DEFAULT_STACK_CONFIG.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD;
325
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, using default.", NS);
326
+ }
327
+
328
+ if (!inRange(config.CONCENTRATOR_MAX_HOPS, 0, 30)) {
329
+ config.CONCENTRATOR_MAX_HOPS = DEFAULT_STACK_CONFIG.CONCENTRATOR_MAX_HOPS;
330
+ logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MAX_HOPS, using default.", NS);
331
+ }
332
+
333
+ if (!inRange(config.MAX_END_DEVICE_CHILDREN, 6, 64)) {
334
+ config.MAX_END_DEVICE_CHILDREN = DEFAULT_STACK_CONFIG.MAX_END_DEVICE_CHILDREN;
335
+ logger.error("[STACK CONFIG] Invalid MAX_END_DEVICE_CHILDREN, using default.", NS);
336
+ }
337
+
338
+ if (!inRange(config.TRANSIENT_DEVICE_TIMEOUT, 0, 65535)) {
339
+ config.TRANSIENT_DEVICE_TIMEOUT = DEFAULT_STACK_CONFIG.TRANSIENT_DEVICE_TIMEOUT;
340
+ logger.error("[STACK CONFIG] Invalid TRANSIENT_DEVICE_TIMEOUT, using default.", NS);
341
+ }
342
+
343
+ if (!inRange(config.END_DEVICE_POLL_TIMEOUT, 0, 14)) {
344
+ config.END_DEVICE_POLL_TIMEOUT = DEFAULT_STACK_CONFIG.END_DEVICE_POLL_TIMEOUT;
345
+ logger.error("[STACK CONFIG] Invalid END_DEVICE_POLL_TIMEOUT, using default.", NS);
346
+ }
347
+
348
+ if (!inRange(config.TRANSIENT_KEY_TIMEOUT_S, 0, 65535)) {
349
+ config.TRANSIENT_KEY_TIMEOUT_S = DEFAULT_STACK_CONFIG.TRANSIENT_KEY_TIMEOUT_S;
350
+ logger.error("[STACK CONFIG] Invalid TRANSIENT_KEY_TIMEOUT_S, using default.", NS);
351
+ }
352
+
353
+ config.CCA_MODE = config.CCA_MODE ?? undefined; // always default to undefined
354
+
355
+ if (config.CCA_MODE && IEEE802154CcaMode[config.CCA_MODE] === undefined) {
356
+ config.CCA_MODE = undefined;
357
+ logger.error("[STACK CONFIG] Invalid CCA_MODE, ignoring.", NS);
358
+ }
359
+
360
+ logger.info(`Using stack config ${JSON.stringify(config)}.`, NS);
361
+ return config;
362
+ } catch {
363
+ /* empty */
364
+ }
365
+
366
+ logger.info("Using default stack config.", NS);
367
+ return DEFAULT_STACK_CONFIG;
368
+ }
369
+
370
+ /**
371
+ * Emitted from @see Ezsp.ezspStackStatusHandler
372
+ * @param status
373
+ */
374
+ private async onStackStatus(status: SLStatus): Promise<void> {
375
+ // to be extra careful, should clear network cache upon receiving this.
376
+ this.clearNetworkCache();
377
+
378
+ switch (status) {
379
+ case SLStatus.NETWORK_UP: {
380
+ this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_UP);
381
+ logger.info("[STACK STATUS] Network up.", NS);
382
+ break;
383
+ }
384
+ case SLStatus.NETWORK_DOWN: {
385
+ this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_DOWN);
386
+ logger.info("[STACK STATUS] Network down.", NS);
387
+ break;
388
+ }
389
+ case SLStatus.ZIGBEE_NETWORK_OPENED: {
390
+ this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_OPENED);
391
+ logger.info("[STACK STATUS] Network opened.", NS);
392
+ break;
393
+ }
394
+ case SLStatus.ZIGBEE_NETWORK_CLOSED: {
395
+ this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_CLOSED);
396
+ logger.info("[STACK STATUS] Network closed.", NS);
397
+
398
+ if (this.manufacturerCode !== DEFAULT_MANUFACTURER_CODE) {
399
+ await this.queue.execute<void>(async () => {
400
+ logger.debug("[WORKAROUND] Reverting coordinator manufacturer code to default.", NS);
401
+ await this.ezsp.ezspSetManufacturerCode(DEFAULT_MANUFACTURER_CODE);
402
+
403
+ this.manufacturerCode = DEFAULT_MANUFACTURER_CODE;
404
+ });
405
+ }
406
+
407
+ break;
408
+ }
409
+ case SLStatus.ZIGBEE_CHANNEL_CHANGED: {
410
+ // invalidate cache
411
+ this.networkCache.parameters.radioChannel = INVALID_RADIO_CHANNEL;
412
+ logger.info("[STACK STATUS] Channel changed.", NS);
413
+ break;
414
+ }
415
+ default: {
416
+ logger.debug(`[STACK STATUS] ${SLStatus[status]}.`, NS);
417
+ break;
418
+ }
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Emitted from @see Ezsp.ezspMessageSentHandler
424
+ * WARNING: Cannot rely on `ezspMessageSentHandler` > `ezspIncomingMessageHandler` order, some devices mix it up!
425
+ *
426
+ * @param type
427
+ * @param indexOrDestination
428
+ * @param apsFrame
429
+ * @param messageTag
430
+ * @param status
431
+ */
432
+ private async onMessageSent(
433
+ status: SLStatus,
434
+ type: EmberOutgoingMessageType,
435
+ indexOrDestination: number,
436
+ apsFrame: EmberApsFrame,
437
+ messageTag: number,
438
+ ): Promise<void> {
439
+ switch (status) {
440
+ case SLStatus.ZIGBEE_DELIVERY_FAILED: {
441
+ logger.debug(
442
+ () =>
443
+ `~x~> DELIVERY_FAILED [indexOrDestination=${indexOrDestination} apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`,
444
+ NS,
445
+ );
446
+
447
+ // no ACK was received from the destination
448
+ switch (type) {
449
+ case EmberOutgoingMessageType.BROADCAST:
450
+ case EmberOutgoingMessageType.BROADCAST_WITH_ALIAS:
451
+ case EmberOutgoingMessageType.MULTICAST:
452
+ case EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
453
+ // BC/MC not checking for message sent, avoid unnecessary waitress lookups
454
+ logger.error(`Delivery of ${EmberOutgoingMessageType[type]} failed for '${indexOrDestination}'.`, NS);
455
+ break;
456
+ }
457
+ default: {
458
+ // reject any waitress early (don't wait for timeout if we know we're gonna get there eventually)
459
+ this.oneWaitress.deliveryFailedFor(indexOrDestination, apsFrame);
460
+ break;
461
+ }
462
+ }
463
+
464
+ break;
465
+ }
466
+ case SLStatus.OK: {
467
+ if (
468
+ type === EmberOutgoingMessageType.MULTICAST &&
469
+ apsFrame.destinationEndpoint === 0xff &&
470
+ apsFrame.groupId < EMBER_MIN_BROADCAST_ADDRESS &&
471
+ !this.multicastTable.includes(apsFrame.groupId)
472
+ ) {
473
+ // workaround for devices using multicast for state update (coordinator passthrough)
474
+ const tableIdx = this.multicastTable.length;
475
+ const multicastEntry: EmberMulticastTableEntry = {
476
+ multicastId: apsFrame.groupId,
477
+ endpoint: FIXED_ENDPOINTS[0].endpoint,
478
+ networkIndex: FIXED_ENDPOINTS[0].networkIndex,
479
+ };
480
+ // set immediately to avoid potential race
481
+ this.multicastTable.push(multicastEntry.multicastId);
482
+
483
+ try {
484
+ await this.queue.execute<void>(async () => {
485
+ const status = await this.ezsp.ezspSetMulticastTableEntry(tableIdx, multicastEntry);
486
+
487
+ if (status !== SLStatus.OK) {
488
+ throw new Error(
489
+ `Failed to register group '${multicastEntry.multicastId}' in multicast table with status=${SLStatus[status]}.`,
490
+ );
491
+ }
492
+
493
+ logger.debug(() => `Registered multicast table entry (${tableIdx}): ${JSON.stringify(multicastEntry)}.`, NS);
494
+ });
495
+ } catch (error) {
496
+ // remove to allow retry on next occurrence
497
+ this.multicastTable.splice(tableIdx, 1);
498
+ logger.error((error as Error).message, NS);
499
+ }
500
+ }
501
+
502
+ break;
503
+ }
504
+ }
505
+ // shouldn't be any other status
506
+ }
507
+
508
+ /**
509
+ * Emitted from @see Ezsp.ezspIncomingMessageHandler
510
+ *
511
+ * @param apsFrame The APS frame associated with the response.
512
+ * @param sender The sender of the response. Should match `payload.nodeId` in many responses.
513
+ * @param messageContents The content of the response.
514
+ */
515
+ private onZDOResponse(apsFrame: EmberApsFrame, sender: NodeId, messageContents: Buffer): void {
516
+ const result = Zdo.Buffalo.readResponse(this.hasZdoMessageOverhead, apsFrame.clusterId, messageContents);
517
+
518
+ if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
519
+ // special case to properly resolve a NETWORK_ADDRESS_RESPONSE following a NETWORK_ADDRESS_REQUEST (based on EUI64 from ZDO payload)
520
+ // NOTE: if response has invalid status (no EUI64 available), response waiter will eventually time out
521
+ if (Zdo.Buffalo.checkStatus<Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE>(result)) {
522
+ this.oneWaitress.resolveZDO(result[1].eui64, apsFrame, result);
523
+ }
524
+ } else {
525
+ this.oneWaitress.resolveZDO(sender, apsFrame, result);
526
+ }
527
+
528
+ this.emit("zdoResponse", apsFrame.clusterId, result);
529
+ }
530
+
531
+ /**
532
+ * Emitted from @see Ezsp.ezspIncomingMessageHandler @see Ezsp.ezspGpepIncomingMessageHandler
533
+ *
534
+ * @param type
535
+ * @param apsFrame
536
+ * @param lastHopLqi
537
+ * @param sender
538
+ * @param messageContents
539
+ */
540
+ private onIncomingMessage(
541
+ type: EmberIncomingMessageType,
542
+ apsFrame: EmberApsFrame,
543
+ lastHopLqi: number,
544
+ sender: NodeId,
545
+ messageContents: Buffer,
546
+ ): void {
547
+ const payload: ZclPayload = {
548
+ clusterID: apsFrame.clusterId,
549
+ header: Zcl.Header.fromBuffer(messageContents),
550
+ address: sender,
551
+ data: messageContents,
552
+ endpoint: apsFrame.sourceEndpoint,
553
+ linkquality: lastHopLqi,
554
+ groupID: apsFrame.groupId,
555
+ wasBroadcast: type === EmberIncomingMessageType.BROADCAST || type === EmberIncomingMessageType.BROADCAST_LOOPBACK,
556
+ destinationEndpoint: apsFrame.destinationEndpoint,
557
+ };
558
+
559
+ this.oneWaitress.resolveZCL(payload);
560
+ this.emit("zclPayload", payload);
561
+ }
562
+
563
+ /**
564
+ * Emitted from @see Ezsp.ezspMacFilterMatchMessageHandler when the message is a valid InterPAN touchlink message.
565
+ *
566
+ * @param _sourcePanId
567
+ * @param sourceAddress
568
+ * @param groupId
569
+ * @param lastHopLqi
570
+ * @param messageContents
571
+ */
572
+ private onTouchlinkMessage(_sourcePanId: PanId, sourceAddress: Eui64, groupId: number, lastHopLqi: number, messageContents: Buffer): void {
573
+ const endpoint = FIXED_ENDPOINTS[0].endpoint;
574
+ const payload: ZclPayload = {
575
+ clusterID: Zcl.Clusters.touchlink.ID,
576
+ data: messageContents,
577
+ header: Zcl.Header.fromBuffer(messageContents),
578
+ address: sourceAddress,
579
+ endpoint: endpoint, // arbitrary since not sent over-the-air
580
+ linkquality: lastHopLqi,
581
+ groupID: groupId,
582
+ wasBroadcast: true, // XXX: since always sent broadcast atm...
583
+ destinationEndpoint: endpoint,
584
+ };
585
+
586
+ this.oneWaitress.resolveZCL(payload);
587
+ this.emit("zclPayload", payload);
588
+ }
589
+
590
+ /**
591
+ * Emitted from @see Ezsp.ezspTrustCenterJoinHandler
592
+ * Also from @see Ezsp.ezspIdConflictHandler as a DEVICE_LEFT
593
+ *
594
+ * @param newNodeId
595
+ * @param newNodeEui64
596
+ * @param status
597
+ * @param policyDecision
598
+ * @param parentOfNewNodeId
599
+ */
600
+ private async onTrustCenterJoin(
601
+ newNodeId: NodeId,
602
+ newNodeEui64: Eui64,
603
+ status: EmberDeviceUpdate,
604
+ policyDecision: EmberJoinDecision,
605
+ parentOfNewNodeId: NodeId,
606
+ ): Promise<void> {
607
+ if (status === EmberDeviceUpdate.DEVICE_LEFT) {
608
+ const payload: DeviceLeavePayload = {
609
+ networkAddress: newNodeId,
610
+ ieeeAddr: newNodeEui64,
611
+ };
612
+
613
+ this.emit("deviceLeave", payload);
614
+ } else {
615
+ if (policyDecision !== EmberJoinDecision.DENY_JOIN) {
616
+ const payload: DeviceJoinedPayload = {
617
+ networkAddress: newNodeId,
618
+ ieeeAddr: newNodeEui64,
619
+ };
620
+
621
+ // set workaround manuf code if necessary, or revert to default if previous joined device required workaround and new one does not
622
+ const joinManufCode = WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE[newNodeEui64.substring(0, 8)] ?? DEFAULT_MANUFACTURER_CODE;
623
+
624
+ if (this.manufacturerCode !== joinManufCode) {
625
+ await this.queue.execute<void>(async () => {
626
+ logger.debug(`[WORKAROUND] Setting coordinator manufacturer code to ${Zcl.ManufacturerCode[joinManufCode]}.`, NS);
627
+ await this.ezsp.ezspSetManufacturerCode(joinManufCode);
628
+
629
+ this.manufacturerCode = joinManufCode;
630
+
631
+ this.emit("deviceJoined", payload);
632
+ });
633
+ } else {
634
+ this.emit("deviceJoined", payload);
635
+ }
636
+ } else {
637
+ logger.warning(`[TRUST CENTER] Device ${newNodeId}:${newNodeEui64} was denied joining via ${parentOfNewNodeId}.`, NS);
638
+ }
639
+ }
640
+ }
641
+
642
+ private async watchdogCounters(): Promise<void> {
643
+ await this.queue.execute<void>(async () => {
644
+ // listed as per EmberCounterType
645
+ const ncpCounters = await this.ezsp.ezspReadAndClearCounters();
646
+
647
+ logger.info(`[NCP COUNTERS] ${ncpCounters.join(",")}`, NS);
648
+
649
+ const ashCounters = this.ezsp.ash.readAndClearCounters();
650
+
651
+ logger.info(`[ASH COUNTERS] ${ashCounters.join(",")}`, NS);
652
+ });
653
+ }
654
+
655
+ /**
656
+ * Proceed to execute the long list of commands required to setup comms between Host<>NCP.
657
+ * This is called by start and on internal reset.
658
+ */
659
+ private async initEzsp(): Promise<TsType.StartResult> {
660
+ let result: TsType.StartResult = "resumed";
661
+
662
+ // NOTE: something deep in this call can throw too
663
+ const startResult = await this.ezsp.start();
664
+
665
+ if (startResult !== EzspStatus.SUCCESS) {
666
+ throw new Error(`Failed to start EZSP layer with status=${EzspStatus[startResult]}.`);
667
+ }
668
+
669
+ // call before any other command, else fails
670
+ await this.emberVersion();
671
+
672
+ /** The address cache needs to be initialized and used with the source routing code for the trust center to operate properly. */
673
+ await this.emberSetEzspConfigValue(EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE, TRUST_CENTER_ADDRESS_CACHE_SIZE);
674
+ /** MAC indirect timeout should be 7.68 secs (STACK_PROFILE_ZIGBEE_PRO) */
675
+ await this.emberSetEzspConfigValue(EzspConfigId.INDIRECT_TRANSMISSION_TIMEOUT, 7680);
676
+ /** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 (STACK_PROFILE_ZIGBEE_PRO) */
677
+ await this.emberSetEzspConfigValue(EzspConfigId.MAX_HOPS, 30);
678
+ await this.emberSetEzspConfigValue(EzspConfigId.SUPPORTED_NETWORKS, 1);
679
+ // allow other devices to modify the binding table
680
+ await this.emberSetEzspPolicy(
681
+ EzspPolicyId.BINDING_MODIFICATION_POLICY,
682
+ EzspDecisionId.CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS,
683
+ );
684
+ // return message tag only in ezspMessageSentHandler()
685
+ await this.emberSetEzspPolicy(EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, EzspDecisionId.MESSAGE_TAG_ONLY_IN_CALLBACK);
686
+ await this.emberSetEzspValue(EzspValueId.TRANSIENT_DEVICE_TIMEOUT, 2, lowHighBytes(this.stackConfig.TRANSIENT_DEVICE_TIMEOUT));
687
+ await this.ezsp.ezspSetManufacturerCode(this.manufacturerCode);
688
+ // network security init
689
+ await this.emberSetEzspConfigValue(EzspConfigId.STACK_PROFILE, STACK_PROFILE_ZIGBEE_PRO);
690
+ await this.emberSetEzspConfigValue(EzspConfigId.SECURITY_LEVEL, SECURITY_LEVEL_Z3);
691
+ // common configs
692
+ await this.emberSetEzspConfigValue(EzspConfigId.MAX_END_DEVICE_CHILDREN, this.stackConfig.MAX_END_DEVICE_CHILDREN);
693
+ await this.emberSetEzspConfigValue(EzspConfigId.END_DEVICE_POLL_TIMEOUT, this.stackConfig.END_DEVICE_POLL_TIMEOUT);
694
+ await this.emberSetEzspConfigValue(EzspConfigId.TRANSIENT_KEY_TIMEOUT_S, this.stackConfig.TRANSIENT_KEY_TIMEOUT_S);
695
+ // XXX: temp-fix: forces a side-effect in the firmware that prevents broadcast issues in environments with unusual interferences
696
+ await this.emberSetEzspValue(EzspValueId.CCA_THRESHOLD, 1, [0]);
697
+
698
+ if (this.stackConfig.CCA_MODE) {
699
+ // validated in `loadStackConfig`
700
+ await this.ezsp.ezspSetRadioIeee802154CcaMode(IEEE802154CcaMode[this.stackConfig.CCA_MODE]);
701
+ }
702
+
703
+ // WARNING: From here on EZSP commands that affect memory allocation on the NCP should no longer be called (like resizing tables)
704
+
705
+ await this.registerFixedEndpoints();
706
+ this.clearNetworkCache();
707
+
708
+ result = await this.initTrustCenter();
709
+
710
+ // after network UP, as per SDK, ensures clean slate
711
+ await this.initNCPConcentrator();
712
+
713
+ // populate network cache info
714
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
715
+
716
+ if (status !== SLStatus.OK) {
717
+ throw new Error(`Failed to get network parameters with status=${SLStatus[status]}.`);
718
+ }
719
+
720
+ if (this.adapterOptions.transmitPower != null && parameters.radioTxPower !== this.adapterOptions.transmitPower) {
721
+ const status = await this.ezsp.ezspSetRadioPower(this.adapterOptions.transmitPower);
722
+
723
+ if (status !== SLStatus.OK) {
724
+ // soft-fail, don't prevent start
725
+ logger.error(`Failed to set transmit power to ${this.adapterOptions.transmitPower} status=${SLStatus[status]}.`, NS);
726
+ }
727
+ }
728
+
729
+ this.networkCache.parameters = parameters;
730
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
731
+
732
+ logger.debug(() => `[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`, NS);
733
+
734
+ this.watchdogCountersHandle = setInterval(this.watchdogCounters.bind(this), WATCHDOG_COUNTERS_FEED_INTERVAL);
735
+
736
+ return result;
737
+ }
738
+
739
+ /**
740
+ * NCP concentrator init. Also enables source route discovery mode with RESCHEDULE.
741
+ *
742
+ * From AN1233:
743
+ * To function correctly in a Zigbee PRO network, a trust center also requires that:
744
+ *
745
+ * 1. The trust center application must act as a concentrator (either high or low RAM).
746
+ * 2. The trust center application must have support for source routing.
747
+ * It must record the source routes and properly handle requests by the stack for a particular source route.
748
+ * 3. The trust center application must use an address cache for security, in order to maintain a mapping of IEEE address to short ID.
749
+ *
750
+ * Failure to satisfy all of the above requirements may result in failures when joining/rejoining devices to the network across multiple hops
751
+ * (through a target node that is neither the trust center nor one of its neighboring routers.)
752
+ */
753
+ private async initNCPConcentrator(): Promise<void> {
754
+ const status = await this.ezsp.ezspSetConcentrator(
755
+ true,
756
+ this.stackConfig.CONCENTRATOR_RAM_TYPE === "low" ? EMBER_LOW_RAM_CONCENTRATOR : EMBER_HIGH_RAM_CONCENTRATOR,
757
+ this.stackConfig.CONCENTRATOR_MIN_TIME,
758
+ this.stackConfig.CONCENTRATOR_MAX_TIME,
759
+ this.stackConfig.CONCENTRATOR_ROUTE_ERROR_THRESHOLD,
760
+ this.stackConfig.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD,
761
+ this.stackConfig.CONCENTRATOR_MAX_HOPS,
762
+ );
763
+
764
+ if (status !== SLStatus.OK) {
765
+ throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${SLStatus[status]}.`);
766
+ }
767
+
768
+ const remainTilMTORR = await this.ezsp.ezspSetSourceRouteDiscoveryMode(EmberSourceRouteDiscoveryMode.RESCHEDULE);
769
+
770
+ logger.info(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`, NS);
771
+ }
772
+
773
+ /**
774
+ * Register fixed endpoints and set any related multicast entries that need to be.
775
+ */
776
+ private async registerFixedEndpoints(): Promise<void> {
777
+ for (const ep of FIXED_ENDPOINTS) {
778
+ const [epStatus] = await this.ezsp.ezspGetEndpointFlags(ep.endpoint);
779
+
780
+ // endpoint not already registered
781
+ if (epStatus !== SLStatus.OK) {
782
+ // check to see if ezspAddEndpoint needs to be called
783
+ // if ezspInit is called without NCP reset, ezspAddEndpoint is not necessary and will return an error
784
+ const status = await this.ezsp.ezspAddEndpoint(
785
+ ep.endpoint,
786
+ ep.profileId,
787
+ ep.deviceId,
788
+ ep.deviceVersion,
789
+ ep.inClusterList.slice(), // copy
790
+ ep.outClusterList.slice(), // copy
791
+ );
792
+
793
+ if (status === SLStatus.OK) {
794
+ logger.debug(`Registered endpoint '${ep.endpoint}'.`, NS);
795
+ } else {
796
+ throw new Error(`Failed to register endpoint '${ep.endpoint}' with status=${SLStatus[status]}.`);
797
+ }
798
+ } else {
799
+ logger.debug(`Endpoint '${ep.endpoint}' already registered.`, NS);
800
+ }
801
+
802
+ for (const multicastId of ep.multicastIds) {
803
+ const multicastEntry: EmberMulticastTableEntry = {
804
+ multicastId,
805
+ endpoint: ep.endpoint,
806
+ networkIndex: ep.networkIndex,
807
+ };
808
+
809
+ const status = await this.ezsp.ezspSetMulticastTableEntry(this.multicastTable.length, multicastEntry);
810
+
811
+ if (status !== SLStatus.OK) {
812
+ throw new Error(`Failed to register group '${multicastId}' in multicast table with status=${SLStatus[status]}.`);
813
+ }
814
+
815
+ logger.debug(() => `Registered multicast table entry (${this.multicastTable.length}): ${JSON.stringify(multicastEntry)}.`, NS);
816
+ this.multicastTable.push(multicastEntry.multicastId);
817
+ }
818
+ }
819
+ }
820
+
821
+ /**
822
+ *
823
+ * @returns True if the network needed to be formed.
824
+ */
825
+ private async initTrustCenter(): Promise<TsType.StartResult> {
826
+ // init TC policies
827
+ {
828
+ let status = await this.emberSetEzspPolicy(EzspPolicyId.TC_KEY_REQUEST_POLICY, EzspDecisionId.ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY);
829
+
830
+ if (status !== SLStatus.OK) {
831
+ throw new Error(
832
+ `[INIT TC] Failed to set EzspPolicyId TC_KEY_REQUEST_POLICY to ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY with status=${SLStatus[status]}.`,
833
+ );
834
+ }
835
+
836
+ /* v8 ignore next */
837
+ const appKeyRequestsPolicy = ALLOW_APP_KEY_REQUESTS ? EzspDecisionId.ALLOW_APP_KEY_REQUESTS : EzspDecisionId.DENY_APP_KEY_REQUESTS;
838
+ status = await this.emberSetEzspPolicy(EzspPolicyId.APP_KEY_REQUEST_POLICY, appKeyRequestsPolicy);
839
+
840
+ if (status !== SLStatus.OK) {
841
+ throw new Error(
842
+ `[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${EzspDecisionId[appKeyRequestsPolicy]} with status=${SLStatus[status]}.`,
843
+ );
844
+ }
845
+
846
+ status = await this.emberSetJoinPolicy(EmberJoinDecision.USE_PRECONFIGURED_KEY);
847
+
848
+ if (status !== SLStatus.OK) {
849
+ throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${SLStatus[status]}.`);
850
+ }
851
+ }
852
+
853
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
854
+ const configNetworkKey = Buffer.from(this.networkOptions.networkKey!);
855
+ const networkInitStruct: EmberNetworkInitStruct = {
856
+ bitmask: EmberNetworkInitBitmask.PARENT_INFO_IN_TOKEN | EmberNetworkInitBitmask.END_DEVICE_REJOIN_ON_REBOOT,
857
+ };
858
+ const initStatus = await this.ezsp.ezspNetworkInit(networkInitStruct);
859
+
860
+ logger.debug(`[INIT TC] Network init status=${SLStatus[initStatus]}.`, NS);
861
+
862
+ if (initStatus !== SLStatus.OK && initStatus !== SLStatus.NOT_JOINED) {
863
+ throw new Error(`[INIT TC] Failed network init request with status=${SLStatus[initStatus]}.`);
864
+ }
865
+
866
+ let action: NetworkInitAction = NetworkInitAction.DONE;
867
+
868
+ if (initStatus === SLStatus.OK) {
869
+ // network
870
+ await this.oneWaitress.startWaitingForEvent(
871
+ {eventName: OneWaitressEvents.STACK_STATUS_NETWORK_UP},
872
+ DEFAULT_NETWORK_REQUEST_TIMEOUT,
873
+ "[INIT TC] Network init",
874
+ );
875
+
876
+ const [npStatus, nodeType, netParams] = await this.ezsp.ezspGetNetworkParameters();
877
+
878
+ logger.debug(() => `[INIT TC] Current adapter network: nodeType=${EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS);
879
+
880
+ if (
881
+ npStatus === SLStatus.OK &&
882
+ nodeType === EmberNodeType.COORDINATOR &&
883
+ this.networkOptions.panID === netParams.panId &&
884
+ equals(this.networkOptions.extendedPanID, netParams.extendedPanId)
885
+ ) {
886
+ // config matches adapter so far, no error, we can check the network key
887
+ const context = initSecurityManagerContext();
888
+ context.coreKeyType = SecManKeyType.NETWORK;
889
+ context.keyIndex = 0;
890
+ const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
891
+
892
+ if (nkStatus !== SLStatus.OK) {
893
+ throw new Error(`[INIT TC] Failed to export Network Key with status=${SLStatus[nkStatus]}.`);
894
+ }
895
+
896
+ // config doesn't match adapter anymore
897
+ if (!networkKey.contents.equals(configNetworkKey)) {
898
+ action = NetworkInitAction.LEAVE;
899
+ }
900
+ } else {
901
+ // config doesn't match adapter
902
+ action = NetworkInitAction.LEAVE;
903
+ }
904
+
905
+ if (action === NetworkInitAction.LEAVE) {
906
+ logger.info("[INIT TC] Adapter network does not match config. Leaving network...", NS);
907
+ const leaveStatus = await this.ezsp.ezspLeaveNetwork();
908
+
909
+ if (leaveStatus !== SLStatus.OK) {
910
+ throw new Error(`[INIT TC] Failed leave network request with status=${SLStatus[leaveStatus]}.`);
911
+ }
912
+
913
+ await this.oneWaitress.startWaitingForEvent(
914
+ {eventName: OneWaitressEvents.STACK_STATUS_NETWORK_DOWN},
915
+ DEFAULT_NETWORK_REQUEST_TIMEOUT,
916
+ "[INIT TC] Leave network",
917
+ );
918
+
919
+ await wait(200); // settle down
920
+
921
+ action = NetworkInitAction.LEFT;
922
+ }
923
+ }
924
+
925
+ const backup = this.getStoredBackup();
926
+
927
+ if (initStatus === SLStatus.NOT_JOINED || action === NetworkInitAction.LEFT) {
928
+ // no network
929
+ if (backup !== undefined) {
930
+ if (
931
+ this.networkOptions.panID === backup.networkOptions.panId &&
932
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
933
+ Buffer.from(this.networkOptions.extendedPanID!).equals(backup.networkOptions.extendedPanId) &&
934
+ this.networkOptions.channelList.includes(backup.logicalChannel) &&
935
+ configNetworkKey.equals(backup.networkOptions.networkKey)
936
+ ) {
937
+ // config matches backup
938
+ action = NetworkInitAction.FORM_BACKUP;
939
+ } else {
940
+ // config doesn't match backup
941
+ logger.info("[INIT TC] Config does not match backup.", NS);
942
+ action = NetworkInitAction.FORM_CONFIG;
943
+ }
944
+ } else {
945
+ // no backup
946
+ logger.info("[INIT TC] No valid backup found.", NS);
947
+ action = NetworkInitAction.FORM_CONFIG;
948
+ }
949
+ }
950
+
951
+ //---- from here on, we assume everything is in place for whatever decision was taken above
952
+
953
+ let result: TsType.StartResult = "resumed";
954
+
955
+ switch (action) {
956
+ case NetworkInitAction.FORM_BACKUP: {
957
+ logger.info("[INIT TC] Forming from backup.", NS);
958
+ // `backup` valid in this `action` path (not detected by TS)
959
+ /* v8 ignore start */
960
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
961
+ const keyList: LinkKeyBackupData[] = backup!.devices.map((device) => ({
962
+ deviceEui64: ZSpec.Utils.eui64BEBufferToHex(device.ieeeAddress),
963
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
964
+ key: {contents: device.linkKey!.key},
965
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
966
+ outgoingFrameCounter: device.linkKey!.txCounter,
967
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
968
+ incomingFrameCounter: device.linkKey!.rxCounter,
969
+ }));
970
+ /* v8 ignore stop */
971
+
972
+ // before forming
973
+ await this.importLinkKeys(keyList);
974
+
975
+ await this.formNetwork(
976
+ true /*from backup*/,
977
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
978
+ backup!.networkOptions.networkKey,
979
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
980
+ backup!.networkKeyInfo.sequenceNumber,
981
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
982
+ backup!.networkKeyInfo.frameCounter,
983
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
984
+ backup!.networkOptions.panId,
985
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
986
+ Array.from(backup!.networkOptions.extendedPanId),
987
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
988
+ backup!.logicalChannel,
989
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
990
+ backup!.ezsp!.hashed_tclk!, // valid from getStoredBackup
991
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
992
+ backup!.networkUpdateId,
993
+ );
994
+
995
+ result = "restored";
996
+ break;
997
+ }
998
+ case NetworkInitAction.FORM_CONFIG: {
999
+ logger.info("[INIT TC] Forming from config.", NS);
1000
+ await this.formNetwork(
1001
+ false /*from config*/,
1002
+ configNetworkKey,
1003
+ 0,
1004
+ 0,
1005
+ this.networkOptions.panID,
1006
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
1007
+ this.networkOptions.extendedPanID!,
1008
+ this.networkOptions.channelList[0],
1009
+ randomBytes(EMBER_ENCRYPTION_KEY_SIZE), // rnd TC link key
1010
+ 0,
1011
+ );
1012
+
1013
+ result = "reset";
1014
+ break;
1015
+ }
1016
+ case NetworkInitAction.DONE: {
1017
+ logger.info("[INIT TC] Adapter network matches config.", NS);
1018
+ break;
1019
+ }
1020
+ }
1021
+
1022
+ // can't let frame counter wrap to zero (uint32_t), will force a broadcast after init if getting too close
1023
+ if (backup != null && backup.networkKeyInfo.frameCounter > 0xfeeeeeee) {
1024
+ // XXX: while this remains a pretty low occurrence in most (small) networks,
1025
+ // currently Z2M won't support the key update because of one-way config...
1026
+ // need to investigate handling this properly
1027
+
1028
+ // logger.warning(`[INIT TC] Network key frame counter is reaching its limit. Scheduling broadcast to update network key. `
1029
+ // + `This may result in some devices (especially battery-powered) temporarily losing connection.`, NS);
1030
+ // // XXX: no idea here on the proper timer value, but this will block the network for several seconds on exec
1031
+ // // (probably have to take the behavior of sleepy-end devices into account to improve chances of reaching everyone right away?)
1032
+ // setTimeout(async () => {
1033
+ // this.requestQueue.enqueue(async (): Promise<SLStatus> => {
1034
+ // await this.broadcastNetworkKeyUpdate();
1035
+
1036
+ // return SLStatus.OK;
1037
+ // }, logger.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected
1038
+ // }, 300000);
1039
+ logger.warning("[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.", NS);
1040
+ }
1041
+
1042
+ return result;
1043
+ }
1044
+
1045
+ /**
1046
+ * Form a network using given parameters.
1047
+ */
1048
+ private async formNetwork(
1049
+ fromBackup: boolean,
1050
+ networkKey: Buffer,
1051
+ networkKeySequenceNumber: number,
1052
+ networkKeyFrameCounter: number,
1053
+ panId: PanId,
1054
+ extendedPanId: ExtendedPanId,
1055
+ radioChannel: number,
1056
+ tcLinkKey: Buffer,
1057
+ nwkUpdateId: number,
1058
+ ): Promise<void> {
1059
+ const state: EmberInitialSecurityState = {
1060
+ bitmask:
1061
+ EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY |
1062
+ EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY |
1063
+ EmberInitialSecurityBitmask.HAVE_NETWORK_KEY |
1064
+ EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY |
1065
+ EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY,
1066
+ preconfiguredKey: {contents: tcLinkKey},
1067
+ networkKey: {contents: networkKey},
1068
+ networkKeySequenceNumber: networkKeySequenceNumber,
1069
+ preconfiguredTrustCenterEui64: ZSpec.BLANK_EUI64,
1070
+ };
1071
+
1072
+ if (fromBackup) {
1073
+ state.bitmask |= EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET;
1074
+
1075
+ const status = await this.ezsp.ezspSetNWKFrameCounter(networkKeyFrameCounter);
1076
+
1077
+ if (status !== SLStatus.OK) {
1078
+ throw new Error(`[INIT FORM] Failed to set NWK frame counter with status=${SLStatus[status]}.`);
1079
+ }
1080
+
1081
+ // status = await this.ezsp.ezspSetAPSFrameCounter(tcLinkKeyFrameCounter);
1082
+
1083
+ // if (status !== SLStatus.OK) {
1084
+ // throw new Error(`[INIT FORM] Failed to set TC APS frame counter with status=${SLStatus[status]}.`);
1085
+ // }
1086
+ }
1087
+
1088
+ let status = await this.ezsp.ezspSetInitialSecurityState(state);
1089
+
1090
+ if (status !== SLStatus.OK) {
1091
+ throw new Error(`[INIT FORM] Failed to set initial security state with status=${SLStatus[status]}.`);
1092
+ }
1093
+
1094
+ const extended: EmberExtendedSecurityBitmask =
1095
+ EmberExtendedSecurityBitmask.JOINER_GLOBAL_LINK_KEY | EmberExtendedSecurityBitmask.NWK_LEAVE_REQUEST_NOT_ALLOWED;
1096
+ status = await this.ezsp.ezspSetExtendedSecurityBitmask(extended);
1097
+
1098
+ if (status !== SLStatus.OK) {
1099
+ throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${SLStatus[status]}.`);
1100
+ }
1101
+
1102
+ if (!fromBackup) {
1103
+ status = await this.ezsp.ezspClearKeyTable();
1104
+
1105
+ if (status !== SLStatus.OK) {
1106
+ logger.error(`[INIT FORM] Failed to clear key table with status=${SLStatus[status]}.`, NS);
1107
+ }
1108
+ }
1109
+
1110
+ const netParams: EmberNetworkParameters = {
1111
+ panId,
1112
+ extendedPanId,
1113
+ radioTxPower: this.adapterOptions.transmitPower || 5,
1114
+ radioChannel,
1115
+ joinMethod: EmberJoinMethod.MAC_ASSOCIATION,
1116
+ nwkManagerId: ZSpec.COORDINATOR_ADDRESS,
1117
+ nwkUpdateId,
1118
+ channels: ZSpec.ALL_802_15_4_CHANNELS_MASK,
1119
+ };
1120
+
1121
+ logger.info(() => `[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`, NS);
1122
+
1123
+ status = await this.ezsp.ezspFormNetwork(netParams);
1124
+
1125
+ if (status !== SLStatus.OK) {
1126
+ throw new Error(`[INIT FORM] Failed form network request with status=${SLStatus[status]}.`);
1127
+ }
1128
+
1129
+ await this.oneWaitress.startWaitingForEvent(
1130
+ {eventName: OneWaitressEvents.STACK_STATUS_NETWORK_UP},
1131
+ DEFAULT_NETWORK_REQUEST_TIMEOUT,
1132
+ "[INIT FORM] Form network",
1133
+ );
1134
+
1135
+ status = await this.ezsp.ezspStartWritingStackTokens();
1136
+
1137
+ logger.debug(`[INIT FORM] Start writing stack tokens status=${SLStatus[status]}.`, NS);
1138
+ logger.info("[INIT FORM] New network formed!", NS);
1139
+ }
1140
+
1141
+ /**
1142
+ * Loads currently stored backup and returns it in internal backup model.
1143
+ */
1144
+ private getStoredBackup(): Backup | undefined {
1145
+ const data = readBackup(this.backupPath);
1146
+ if (!data) return undefined;
1147
+
1148
+ if ("metadata" in data && data.metadata?.format === "zigpy/open-coordinator-backup" && data.metadata?.version) {
1149
+ if (data.metadata?.version !== 1) {
1150
+ throw new Error(`[BACKUP] Unsupported open coordinator backup version (version=${data.metadata?.version}).`);
1151
+ }
1152
+
1153
+ if (!data.stack_specific?.ezsp || !data.metadata.internal.ezspVersion) {
1154
+ throw new Error("[BACKUP] Current backup file is not for EmberZNet stack.");
1155
+ }
1156
+
1157
+ if (data.metadata.internal.ezspVersion < BACKUP_OLDEST_SUPPORTED_EZSP_VERSION) {
1158
+ renameSync(this.backupPath, `${this.backupPath}.old`);
1159
+ logger.warning("[BACKUP] Current backup file is from an unsupported EZSP version. Renaming and ignoring.", NS);
1160
+ return undefined;
1161
+ }
1162
+
1163
+ return BackupUtils.fromUnifiedBackup(data);
1164
+ }
1165
+
1166
+ throw new Error("[BACKUP] Unknown backup format.");
1167
+ }
1168
+
1169
+ /**
1170
+ * Export link keys for backup.
1171
+ *
1172
+ * @return List of keys data with AES hashed keys
1173
+ */
1174
+ public async exportLinkKeys(): Promise<LinkKeyBackupData[]> {
1175
+ const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(EzspConfigId.KEY_TABLE_SIZE);
1176
+
1177
+ if (confStatus !== SLStatus.OK) {
1178
+ throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${SLStatus[confStatus]}.`);
1179
+ }
1180
+
1181
+ let context: SecManContext;
1182
+ let plaintextKey: SecManKey;
1183
+ let apsKeyMeta: SecManAPSKeyMetadata;
1184
+ let status: SLStatus;
1185
+ const keyList: LinkKeyBackupData[] = [];
1186
+
1187
+ for (let i = 0; i < keyTableSize; i++) {
1188
+ [status, context, plaintextKey, apsKeyMeta] = await this.ezsp.ezspExportLinkKeyByIndex(i);
1189
+ logger.debug(`[BACKUP] Export link key at index ${i}, status=${SLStatus[status]}.`, NS);
1190
+
1191
+ // only include key if we could retrieve one at index and hash it properly
1192
+ if (status === SLStatus.OK) {
1193
+ // Rather than give the real link key, the backup contains a hashed version of the key.
1194
+ // This is done to prevent a compromise of the backup data from compromising the current link keys.
1195
+ // This is per the Smart Energy spec.
1196
+ const hashedKey = ZSpec.Utils.aes128MmoHash(plaintextKey.contents);
1197
+
1198
+ keyList.push({
1199
+ deviceEui64: context.eui64,
1200
+ key: {contents: hashedKey},
1201
+ outgoingFrameCounter: apsKeyMeta.outgoingFrameCounter,
1202
+ incomingFrameCounter: apsKeyMeta.incomingFrameCounter,
1203
+ });
1204
+ }
1205
+ }
1206
+
1207
+ logger.info(`[BACKUP] Retrieved ${keyList.length} link keys.`, NS);
1208
+
1209
+ return keyList;
1210
+ }
1211
+
1212
+ /**
1213
+ * Import link keys from backup.
1214
+ *
1215
+ * @param backupData
1216
+ */
1217
+ public async importLinkKeys(backupData: LinkKeyBackupData[]): Promise<void> {
1218
+ if (!backupData?.length) {
1219
+ return;
1220
+ }
1221
+
1222
+ const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(EzspConfigId.KEY_TABLE_SIZE);
1223
+
1224
+ if (confStatus !== SLStatus.OK) {
1225
+ throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${SLStatus[confStatus]}.`);
1226
+ }
1227
+
1228
+ if (backupData.length > keyTableSize) {
1229
+ throw new Error(`[BACKUP] Current key table of ${keyTableSize} is too small to import backup of ${backupData.length}!`);
1230
+ }
1231
+
1232
+ const networkStatus = await this.ezsp.ezspNetworkState();
1233
+
1234
+ if (networkStatus !== EmberNetworkStatus.NO_NETWORK) {
1235
+ throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${EmberNetworkStatus[networkStatus]}.`);
1236
+ }
1237
+
1238
+ let status: SLStatus;
1239
+
1240
+ for (let i = 0; i < keyTableSize; i++) {
1241
+ // erase any key index not present in backup but available on the NCP
1242
+ status =
1243
+ i >= backupData.length
1244
+ ? await this.ezsp.ezspEraseKeyTableEntry(i)
1245
+ : await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key);
1246
+
1247
+ if (status !== SLStatus.OK) {
1248
+ throw new Error(
1249
+ `[BACKUP] Failed to ${i >= backupData.length ? "erase" : "set"} key table entry at index ${i} with status=${SLStatus[status]}.`,
1250
+ );
1251
+ }
1252
+ }
1253
+
1254
+ logger.info(`[BACKUP] Imported ${backupData.length} keys.`, NS);
1255
+ }
1256
+
1257
+ /**
1258
+ * Routine to update the network key and broadcast the update to the network after a set time.
1259
+ * NOTE: This should run at a large interval, but before the uint32_t of the frame counter is able to reach all Fs (can't wrap to 0).
1260
+ * This may disrupt sleepy end devices that miss the update, but they should be able to TC rejoin (in most cases...).
1261
+ * On the other hand, the more often this runs, the more secure the network is...
1262
+ */
1263
+ public async broadcastNetworkKeyUpdate(): Promise<void> {
1264
+ return await this.queue.execute<void>(async () => {
1265
+ logger.warning("[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.", NS);
1266
+
1267
+ // zero-filled = let stack generate new random network key
1268
+ let status = await this.ezsp.ezspBroadcastNextNetworkKey({contents: Buffer.alloc(EMBER_ENCRYPTION_KEY_SIZE)});
1269
+
1270
+ if (status !== SLStatus.OK) {
1271
+ throw new Error(`[TRUST CENTER] Failed to broadcast next network key with status=${SLStatus[status]}.`);
1272
+ }
1273
+
1274
+ // XXX: this will block other requests for a while, but should ensure the key propagates without interference?
1275
+ // could also stop dispatching entirely and do this outside the queue if necessary/better
1276
+ await wait(BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME);
1277
+
1278
+ status = await this.ezsp.ezspBroadcastNetworkKeySwitch();
1279
+
1280
+ if (status !== SLStatus.OK) {
1281
+ // XXX: Not sure how likely this is, but this is bad, probably should hard fail?
1282
+ throw new Error(`[TRUST CENTER] Failed to broadcast network key switch with status=${SLStatus[status]}.`);
1283
+ }
1284
+ });
1285
+ }
1286
+
1287
+ /**
1288
+ * Received when EZSP layer alerts of a problem that needs the NCP to be reset.
1289
+ * @param status
1290
+ */
1291
+ private onNcpNeedsResetAndInit(_status: EzspStatus): void {
1292
+ this.emit("disconnected");
1293
+ }
1294
+
1295
+ //---- START Events
1296
+
1297
+ //---- END Events
1298
+
1299
+ //---- START Cache-enabled EZSP wrappers
1300
+
1301
+ /**
1302
+ * Clear the cached network values (set to invalid values).
1303
+ */
1304
+ public clearNetworkCache(): void {
1305
+ this.networkCache = initNetworkCache();
1306
+ }
1307
+
1308
+ /**
1309
+ * Return the EUI 64 of the local node
1310
+ * This call caches the results on the host to prevent frequent EZSP transactions.
1311
+ * Check against BLANK_EUI64 for validity.
1312
+ */
1313
+ public async emberGetEui64(): Promise<Eui64> {
1314
+ if (this.networkCache.eui64 === ZSpec.BLANK_EUI64) {
1315
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
1316
+ }
1317
+
1318
+ return this.networkCache.eui64;
1319
+ }
1320
+
1321
+ /**
1322
+ * Return the PAN ID of the local node.
1323
+ * This call caches the results on the host to prevent frequent EZSP transactions.
1324
+ * Check against INVALID_PAN_ID for validity.
1325
+ */
1326
+ public async emberGetPanId(): Promise<PanId> {
1327
+ if (this.networkCache.parameters.panId === ZSpec.INVALID_PAN_ID) {
1328
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1329
+
1330
+ if (status === SLStatus.OK) {
1331
+ this.networkCache.parameters = parameters;
1332
+ } else {
1333
+ throw new Error(`Failed to get PAN ID (via network parameters) with status=${SLStatus[status]}.`);
1334
+ }
1335
+ }
1336
+
1337
+ return this.networkCache.parameters.panId;
1338
+ }
1339
+
1340
+ /**
1341
+ * Return the Extended PAN ID of the local node.
1342
+ * This call caches the results on the host to prevent frequent EZSP transactions.
1343
+ * Check against BLANK_EXTENDED_PAN_ID for validity.
1344
+ */
1345
+ public async emberGetExtendedPanId(): Promise<ExtendedPanId> {
1346
+ if (equals(this.networkCache.parameters.extendedPanId, ZSpec.BLANK_EXTENDED_PAN_ID)) {
1347
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1348
+
1349
+ if (status === SLStatus.OK) {
1350
+ this.networkCache.parameters = parameters;
1351
+ } else {
1352
+ throw new Error(`Failed to get Extended PAN ID (via network parameters) with status=${SLStatus[status]}.`);
1353
+ }
1354
+ }
1355
+
1356
+ return this.networkCache.parameters.extendedPanId;
1357
+ }
1358
+
1359
+ /**
1360
+ * Return the radio channel (uint8_t) of the current network.
1361
+ * This call caches the results on the host to prevent frequent EZSP transactions.
1362
+ * Check against INVALID_RADIO_CHANNEL for validity.
1363
+ */
1364
+ public async emberGetRadioChannel(): Promise<number> {
1365
+ if (this.networkCache.parameters.radioChannel === INVALID_RADIO_CHANNEL) {
1366
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1367
+
1368
+ if (status === SLStatus.OK) {
1369
+ this.networkCache.parameters = parameters;
1370
+ } else {
1371
+ throw new Error(`Failed to get radio channel (via network parameters) with status=${SLStatus[status]}.`);
1372
+ }
1373
+ }
1374
+
1375
+ return this.networkCache.parameters.radioChannel;
1376
+ }
1377
+
1378
+ //---- END Cache-enabled EZSP wrappers
1379
+
1380
+ //---- START EZSP wrappers
1381
+
1382
+ /**
1383
+ * Ensure the Host & NCP are aligned on protocols using version.
1384
+ * Cache the retrieved information.
1385
+ *
1386
+ * NOTE: currently throws on mismatch until support for lower versions is implemented (not planned atm)
1387
+ *
1388
+ * Does nothing if ncpNeedsResetAndInit == true.
1389
+ */
1390
+ private async emberVersion(): Promise<void> {
1391
+ // send the Host version number to the NCP.
1392
+ // The NCP returns the EZSP version that the NCP is running along with the stackType and stackVersion
1393
+ let [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(EZSP_PROTOCOL_VERSION);
1394
+
1395
+ // verify that the stack type is what is expected
1396
+ if (ncpStackType !== EZSP_STACK_TYPE_MESH) {
1397
+ throw new Error(`Stack type ${ncpStackType} is not expected!`);
1398
+ }
1399
+
1400
+ if (ncpEzspProtocolVer === EZSP_PROTOCOL_VERSION) {
1401
+ logger.debug(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) matches Host.`, NS);
1402
+ } else if (ncpEzspProtocolVer < EZSP_PROTOCOL_VERSION && ncpEzspProtocolVer >= EZSP_MIN_PROTOCOL_VERSION) {
1403
+ [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(ncpEzspProtocolVer);
1404
+
1405
+ logger.info(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) lower than Host. Switched.`, NS);
1406
+ } else {
1407
+ throw new Error(
1408
+ `Adapter EZSP protocol version (${ncpEzspProtocolVer}) is not supported by Host [${EZSP_MIN_PROTOCOL_VERSION}-${EZSP_PROTOCOL_VERSION}].`,
1409
+ );
1410
+ }
1411
+
1412
+ this.ezsp.setProtocolVersion(ncpEzspProtocolVer);
1413
+ logger.debug(`Adapter info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS);
1414
+
1415
+ const [status, versionStruct] = await this.ezsp.ezspGetVersionStruct();
1416
+
1417
+ if (status !== SLStatus.OK) {
1418
+ // Should never happen with support of only EZSP v13+
1419
+ throw new Error("NCP has old-style version number. Not supported.");
1420
+ }
1421
+
1422
+ this.version = {
1423
+ ezsp: ncpEzspProtocolVer,
1424
+ revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${EmberVersionType[versionStruct.type]}]`,
1425
+ ...versionStruct,
1426
+ };
1427
+
1428
+ if (versionStruct.type !== EmberVersionType.GA) {
1429
+ logger.warning(`Adapter is running a non-GA version (${EmberVersionType[versionStruct.type]}).`, NS);
1430
+ }
1431
+
1432
+ logger.info(() => `Adapter version info: ${JSON.stringify(this.version)}`, NS);
1433
+ }
1434
+
1435
+ /**
1436
+ * This function sets an EZSP config value.
1437
+ * WARNING: Do not call for values that cannot be set after init without first resetting NCP (like table sizes).
1438
+ * To avoid an extra NCP call, this does not check for it.
1439
+ * @param configId
1440
+ * @param value uint16_t
1441
+ * @returns
1442
+ */
1443
+ private async emberSetEzspConfigValue(configId: EzspConfigId, value: number): Promise<SLStatus> {
1444
+ const status = await this.ezsp.ezspSetConfigurationValue(configId, value);
1445
+
1446
+ logger.debug(`[EzspConfigId] SET '${EzspConfigId[configId]}' TO '${value}' with status=${SLStatus[status]}.`, NS);
1447
+
1448
+ if (status !== SLStatus.OK) {
1449
+ logger.info(
1450
+ `[EzspConfigId] Failed to SET '${EzspConfigId[configId]}' TO '${value}' with status=${SLStatus[status]}. Firmware value will be used instead.`,
1451
+ NS,
1452
+ );
1453
+ }
1454
+
1455
+ return status;
1456
+ }
1457
+
1458
+ /**
1459
+ * This function sets an EZSP value.
1460
+ * @param valueId
1461
+ * @param valueLength uint8_t
1462
+ * @param value uint8_t *
1463
+ * @returns
1464
+ */
1465
+ private async emberSetEzspValue(valueId: EzspValueId, valueLength: number, value: number[]): Promise<SLStatus> {
1466
+ const status = await this.ezsp.ezspSetValue(valueId, valueLength, value);
1467
+
1468
+ logger.debug(`[EzspValueId] SET '${EzspValueId[valueId]}' TO '${value}' with status=${SLStatus[status]}.`, NS);
1469
+
1470
+ return status;
1471
+ }
1472
+
1473
+ /**
1474
+ * This function sets an EZSP policy.
1475
+ * @param policyId
1476
+ * @param decisionId Can be bitop
1477
+ * @returns
1478
+ */
1479
+ private async emberSetEzspPolicy(policyId: EzspPolicyId, decisionId: number): Promise<SLStatus> {
1480
+ const status = await this.ezsp.ezspSetPolicy(policyId, decisionId);
1481
+
1482
+ logger.debug(`[EzspPolicyId] SET '${EzspPolicyId[policyId]}' TO '${decisionId}' with status=${SLStatus[status]}.`, NS);
1483
+
1484
+ return status;
1485
+ }
1486
+
1487
+ /**
1488
+ * Set the trust center policy bitmask using decision.
1489
+ * @param decision
1490
+ * @returns
1491
+ */
1492
+ private async emberSetJoinPolicy(decision: EmberJoinDecision): Promise<SLStatus> {
1493
+ let policy: number = EzspDecisionBitmask.DEFAULT_CONFIGURATION;
1494
+
1495
+ switch (decision) {
1496
+ case EmberJoinDecision.USE_PRECONFIGURED_KEY: {
1497
+ policy = EzspDecisionBitmask.ALLOW_JOINS | EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
1498
+ break;
1499
+ }
1500
+ case EmberJoinDecision.ALLOW_REJOINS_ONLY: {
1501
+ policy = EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
1502
+ break;
1503
+ }
1504
+ /*case EmberJoinDecision.SEND_KEY_IN_THE_CLEAR: {
1505
+ policy = EzspDecisionBitmask.ALLOW_JOINS | EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS | EzspDecisionBitmask.SEND_KEY_IN_CLEAR;
1506
+ break;
1507
+ }*/
1508
+ }
1509
+
1510
+ return await this.emberSetEzspPolicy(EzspPolicyId.TRUST_CENTER_POLICY, policy);
1511
+ }
1512
+
1513
+ //---- END EZSP wrappers
1514
+
1515
+ //---- START Ember ZDO
1516
+
1517
+ /**
1518
+ * ZDO
1519
+ * Get the next device request sequence number.
1520
+ *
1521
+ * Requests have sequence numbers so that they can be matched up with the
1522
+ * responses. To avoid complexities, the library uses numbers with the high
1523
+ * bit clear and the stack uses numbers with the high bit set.
1524
+ *
1525
+ * @return uint8_t The next device request sequence number
1526
+ */
1527
+ private nextZDORequestSequence(): number {
1528
+ this.zdoRequestSequence = ++this.zdoRequestSequence & APPLICATION_ZDO_SEQUENCE_MASK;
1529
+ return this.zdoRequestSequence;
1530
+ }
1531
+
1532
+ //---- END Ember ZDO
1533
+
1534
+ //-- START Adapter implementation
1535
+
1536
+ public async start(): Promise<TsType.StartResult> {
1537
+ logger.info("======== Ember Adapter Starting ========", NS);
1538
+ const result = await this.initEzsp();
1539
+
1540
+ return result;
1541
+ }
1542
+
1543
+ public async stop(): Promise<void> {
1544
+ clearInterval(this.watchdogCountersHandle);
1545
+ await this.ezsp.stop();
1546
+ this.ezsp.removeAllListeners();
1547
+
1548
+ logger.info("======== Ember Adapter Stopped ========", NS);
1549
+ }
1550
+
1551
+ public async getCoordinatorIEEE(): Promise<string> {
1552
+ return await this.queue.execute(async () => {
1553
+ this.checkInterpanLock();
1554
+
1555
+ // in all likelihood this will be retrieved from cache
1556
+ return await this.emberGetEui64();
1557
+ });
1558
+ }
1559
+
1560
+ public async getCoordinatorVersion(): Promise<TsType.CoordinatorVersion> {
1561
+ return await Promise.resolve({type: "EmberZNet", meta: this.version});
1562
+ }
1563
+
1564
+ // queued
1565
+ public async reset(type: "soft" | "hard"): Promise<void> {
1566
+ // NOTE: although this function is legacy atm, a couple of new untested EZSP functions that could also prove useful:
1567
+ // this.ezsp.ezspTokenFactoryReset(true/*excludeOutgoingFC*/, true/*excludeBootCounter*/);
1568
+ // this.ezsp.ezspResetNode()
1569
+ /* v8 ignore next */ // weird coverage bug
1570
+ await Promise.reject(new Error(`Not supported '${type}'.`));
1571
+ }
1572
+
1573
+ public async supportsBackup(): Promise<boolean> {
1574
+ return await Promise.resolve(true);
1575
+ }
1576
+
1577
+ // queued
1578
+ public async backup(_ieeeAddressesInDatabase: string[]): Promise<Backup> {
1579
+ return await this.queue.execute<Backup>(async () => {
1580
+ // grab fresh version here, bypass cache
1581
+ const [netStatus, , netParams] = await this.ezsp.ezspGetNetworkParameters();
1582
+
1583
+ if (netStatus !== SLStatus.OK) {
1584
+ throw new Error(`[BACKUP] Failed to get network parameters with status=${SLStatus[netStatus]}.`);
1585
+ }
1586
+
1587
+ // update cache
1588
+ this.networkCache.parameters = netParams;
1589
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
1590
+
1591
+ const [netKeyStatus, netKeyInfo] = await this.ezsp.ezspGetNetworkKeyInfo();
1592
+
1593
+ if (netKeyStatus !== SLStatus.OK) {
1594
+ throw new Error(`[BACKUP] Failed to get network keys info with status=${SLStatus[netKeyStatus]}.`);
1595
+ }
1596
+
1597
+ if (!netKeyInfo.networkKeySet) {
1598
+ throw new Error("[BACKUP] No network key set.");
1599
+ }
1600
+
1601
+ /* v8 ignore next */
1602
+ const keyList: LinkKeyBackupData[] = ALLOW_APP_KEY_REQUESTS ? await this.exportLinkKeys() : [];
1603
+
1604
+ let context: SecManContext = initSecurityManagerContext();
1605
+ context.coreKeyType = SecManKeyType.TC_LINK;
1606
+ const [tclkStatus, tcLinkKey] = await this.ezsp.ezspExportKey(context);
1607
+
1608
+ if (tclkStatus !== SLStatus.OK) {
1609
+ throw new Error(`[BACKUP] Failed to export TC Link Key with status=${SLStatus[tclkStatus]}.`);
1610
+ }
1611
+
1612
+ // const [tcKeyStatus, tcKeyInfo] = await this.ezsp.ezspGetApsKeyInfo(context);
1613
+
1614
+ // if (tcKeyStatus !== SLStatus.OK) {
1615
+ // throw new Error(`[BACKUP] Failed to get TC APS key info with status=${SLStatus[tcKeyStatus]}.`);
1616
+ // }
1617
+
1618
+ context = initSecurityManagerContext(); // make sure it's back to zeroes
1619
+ context.coreKeyType = SecManKeyType.NETWORK;
1620
+ context.keyIndex = 0;
1621
+ const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
1622
+
1623
+ if (nkStatus !== SLStatus.OK) {
1624
+ throw new Error(`[BACKUP] Failed to export Network Key with status=${SLStatus[nkStatus]}.`);
1625
+ }
1626
+
1627
+ return {
1628
+ networkOptions: {
1629
+ panId: netParams.panId, // uint16_t
1630
+ extendedPanId: Buffer.from(netParams.extendedPanId),
1631
+ channelList: ZSpec.Utils.uint32MaskToChannels(netParams.channels),
1632
+ networkKey: networkKey.contents,
1633
+ networkKeyDistribute: false,
1634
+ },
1635
+ logicalChannel: netParams.radioChannel,
1636
+ networkKeyInfo: {
1637
+ sequenceNumber: netKeyInfo.networkKeySequenceNumber,
1638
+ frameCounter: netKeyInfo.networkKeyFrameCounter,
1639
+ },
1640
+ // tcLinkKeyInfo: {
1641
+ // incomingFrameCounter: tcKeyInfo.bitmask & EmberKeyStructBitmask.HAS_INCOMING_FRAME_COUNTER ? tcKeyInfo.incomingFrameCounter : 0,
1642
+ // outgoingFrameCounter: tcKeyInfo.bitmask & EmberKeyStructBitmask.HAS_OUTGOING_FRAME_COUNTER ? tcKeyInfo.outgoingFrameCounter : 0,
1643
+ // },
1644
+ securityLevel: SECURITY_LEVEL_Z3,
1645
+ networkUpdateId: netParams.nwkUpdateId,
1646
+ coordinatorIeeeAddress: Buffer.from(this.networkCache.eui64.substring(2) /*take out 0x*/, "hex").reverse(),
1647
+ devices: keyList.map(
1648
+ /* v8 ignore start */
1649
+ (key) => ({
1650
+ networkAddress: null, // not used for restore, no reason to make NCP calls for nothing
1651
+ ieeeAddress: Buffer.from(key.deviceEui64.substring(2) /*take out 0x*/, "hex").reverse(),
1652
+ isDirectChild: false, // not used
1653
+ linkKey: {
1654
+ key: key.key.contents,
1655
+ rxCounter: key.incomingFrameCounter,
1656
+ txCounter: key.outgoingFrameCounter,
1657
+ },
1658
+ }),
1659
+ /* v8 ignore stop */
1660
+ ),
1661
+ ezsp: {
1662
+ version: this.version.ezsp,
1663
+ hashed_tclk: tcLinkKey.contents,
1664
+ // tokens: tokensBuf.toString('hex'),
1665
+ // altNetworkKey: altNetworkKey.contents,
1666
+ },
1667
+ };
1668
+ });
1669
+ }
1670
+
1671
+ // queued, non-InterPAN
1672
+ public async getNetworkParameters(): Promise<TsType.NetworkParameters> {
1673
+ return await this.queue.execute<TsType.NetworkParameters>(async () => {
1674
+ this.checkInterpanLock();
1675
+
1676
+ // first call will cache for the others, but in all likelihood, it will all be from freshly cached after init
1677
+ // since Controller caches this also.
1678
+ const channel = await this.emberGetRadioChannel();
1679
+ const panID = await this.emberGetPanId();
1680
+ const extendedPanID = await this.emberGetExtendedPanId();
1681
+
1682
+ return {
1683
+ panID,
1684
+ extendedPanID: ZSpec.Utils.eui64LEBufferToHex(Buffer.from(extendedPanID)),
1685
+ channel,
1686
+ nwkUpdateID: this.networkCache.parameters.nwkUpdateId,
1687
+ };
1688
+ });
1689
+ }
1690
+
1691
+ // queued
1692
+ public async addInstallCode(ieeeAddress: string, key: Buffer, hashed: boolean): Promise<void> {
1693
+ return await this.queue.execute<void>(async () => {
1694
+ // Add the key to the transient key table.
1695
+ // This will be used while the DUT joins.
1696
+ const impStatus = await this.ezsp.ezspImportTransientKey(ieeeAddress as Eui64, {contents: hashed ? key : ZSpec.Utils.aes128MmoHash(key)});
1697
+
1698
+ if (impStatus === SLStatus.OK) {
1699
+ logger.debug(`[ADD INSTALL CODE] Success for '${ieeeAddress}'.`, NS);
1700
+ } else {
1701
+ throw new Error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${SLStatus[impStatus]}.`);
1702
+ }
1703
+ });
1704
+ }
1705
+
1706
+ /** WARNING: Adapter impl. Starts timer immediately upon returning */
1707
+ public waitFor(
1708
+ networkAddress: number | undefined,
1709
+ endpoint: number,
1710
+ _frameType: Zcl.FrameType,
1711
+ _direction: Zcl.Direction,
1712
+ transactionSequenceNumber: number | undefined,
1713
+ clusterID: number,
1714
+ commandIdentifier: number,
1715
+ timeout: number,
1716
+ ): {promise: Promise<ZclPayload>; cancel: () => void} {
1717
+ const sourceEndpointInfo = FIXED_ENDPOINTS[0];
1718
+ const waiter = this.oneWaitress.waitFor<ZclPayload>(
1719
+ {
1720
+ target: networkAddress,
1721
+ apsFrame: {
1722
+ clusterId: clusterID,
1723
+ profileId: sourceEndpointInfo.profileId, // XXX: only used by OTA upstream
1724
+ sequence: 0, // set by stack
1725
+ sourceEndpoint: sourceEndpointInfo.endpoint,
1726
+ destinationEndpoint: endpoint,
1727
+ groupId: 0,
1728
+ options: EmberApsOption.NONE,
1729
+ },
1730
+ zclSequence: transactionSequenceNumber,
1731
+ commandIdentifier,
1732
+ },
1733
+ timeout,
1734
+ );
1735
+
1736
+ return {
1737
+ cancel: (): void => this.oneWaitress.remove(waiter.id),
1738
+ promise: waiter.start().promise,
1739
+ };
1740
+ }
1741
+
1742
+ //---- ZDO
1743
+
1744
+ // queued, non-InterPAN
1745
+ public async sendZdo(
1746
+ ieeeAddress: string,
1747
+ networkAddress: number,
1748
+ clusterId: Zdo.ClusterId,
1749
+ payload: Buffer,
1750
+ disableResponse: true,
1751
+ ): Promise<void>;
1752
+ public async sendZdo<K extends keyof ZdoTypes.RequestToResponseMap>(
1753
+ ieeeAddress: string,
1754
+ networkAddress: number,
1755
+ clusterId: K,
1756
+ payload: Buffer,
1757
+ disableResponse: false,
1758
+ ): Promise<ZdoTypes.RequestToResponseMap[K]>;
1759
+ public async sendZdo<K extends keyof ZdoTypes.RequestToResponseMap>(
1760
+ ieeeAddress: string,
1761
+ networkAddress: number,
1762
+ clusterId: K,
1763
+ payload: Buffer,
1764
+ disableResponse: boolean,
1765
+ ): Promise<ZdoTypes.RequestToResponseMap[K] | undefined> {
1766
+ return await this.queue.execute(async () => {
1767
+ this.checkInterpanLock();
1768
+
1769
+ const clusterName = Zdo.ClusterId[clusterId];
1770
+ const messageTag = this.nextZDORequestSequence();
1771
+ payload[0] = messageTag;
1772
+ const apsFrame: EmberApsFrame = {
1773
+ profileId: Zdo.ZDO_PROFILE_ID,
1774
+ clusterId,
1775
+ sourceEndpoint: Zdo.ZDO_ENDPOINT,
1776
+ destinationEndpoint: Zdo.ZDO_ENDPOINT,
1777
+ options: DEFAULT_APS_OPTIONS,
1778
+ groupId: 0,
1779
+ sequence: 0, // set by stack
1780
+ };
1781
+ let status: SLStatus | undefined;
1782
+ let apsSequence: number | undefined;
1783
+
1784
+ if (ZSpec.Utils.isBroadcastAddress(networkAddress)) {
1785
+ logger.debug(
1786
+ () => `~~~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag} payload=${payload.toString("hex")}]`,
1787
+ NS,
1788
+ );
1789
+
1790
+ [status, apsSequence] = await this.ezsp.ezspSendBroadcast(
1791
+ ZSpec.NULL_NODE_ID, // alias
1792
+ networkAddress,
1793
+ 0, // nwkSequence
1794
+ apsFrame,
1795
+ ZDO_REQUEST_RADIUS,
1796
+ messageTag,
1797
+ payload,
1798
+ );
1799
+
1800
+ apsFrame.sequence = apsSequence;
1801
+
1802
+ logger.debug(`~~~> [SENT ZDO BROADCAST messageTag=${messageTag} apsSequence=${apsSequence} status=${SLStatus[status]}]`, NS);
1803
+
1804
+ if (status !== SLStatus.OK) {
1805
+ throw new Error(
1806
+ `~x~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag}] Failed to send request with status=${SLStatus[status]}.`,
1807
+ );
1808
+ }
1809
+ } else {
1810
+ logger.debug(
1811
+ () =>
1812
+ `~~~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag} payload=${payload.toString("hex")}]`,
1813
+ NS,
1814
+ );
1815
+
1816
+ [status, apsSequence] = await this.ezsp.ezspSendUnicast(
1817
+ EmberOutgoingMessageType.DIRECT,
1818
+ networkAddress,
1819
+ apsFrame,
1820
+ messageTag,
1821
+ payload,
1822
+ );
1823
+ apsFrame.sequence = apsSequence;
1824
+
1825
+ logger.debug(`~~~> [SENT ZDO UNICAST messageTag=${messageTag} apsSequence=${apsSequence} status=${SLStatus[status]}]`, NS);
1826
+
1827
+ if (status !== SLStatus.OK) {
1828
+ throw new Error(
1829
+ `~x~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag}] Failed to send request with status=${SLStatus[status]}.`,
1830
+ );
1831
+ }
1832
+ }
1833
+
1834
+ if (!disableResponse) {
1835
+ const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
1836
+
1837
+ if (responseClusterId) {
1838
+ return await this.oneWaitress.startWaitingFor(
1839
+ {
1840
+ target: responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? (ieeeAddress as Eui64) : networkAddress,
1841
+ apsFrame,
1842
+ zdoResponseClusterId: responseClusterId,
1843
+ },
1844
+ DEFAULT_REQUEST_TIMEOUT,
1845
+ );
1846
+ }
1847
+ }
1848
+ }, networkAddress);
1849
+ }
1850
+
1851
+ // queued, non-InterPAN
1852
+ public async permitJoin(seconds: number, networkAddress?: number): Promise<void> {
1853
+ const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
1854
+ const preJoining = async (): Promise<void> => {
1855
+ if (seconds) {
1856
+ const plaintextKey: SecManKey = {contents: Buffer.from(ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY)};
1857
+ const impKeyStatus = await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey);
1858
+
1859
+ if (impKeyStatus !== SLStatus.OK) {
1860
+ throw new Error(`[ZDO] Failed import transient key with status=${SLStatus[impKeyStatus]}.`);
1861
+ }
1862
+
1863
+ const setJPstatus = await this.emberSetJoinPolicy(EmberJoinDecision.USE_PRECONFIGURED_KEY);
1864
+
1865
+ if (setJPstatus !== SLStatus.OK) {
1866
+ throw new Error(`[ZDO] Failed set join policy with status=${SLStatus[setJPstatus]}.`);
1867
+ }
1868
+ } else {
1869
+ await this.ezsp.ezspClearTransientLinkKeys();
1870
+
1871
+ const setJPstatus = await this.emberSetJoinPolicy(EmberJoinDecision.ALLOW_REJOINS_ONLY);
1872
+
1873
+ if (setJPstatus !== SLStatus.OK) {
1874
+ throw new Error(`[ZDO] Failed set join policy with status=${SLStatus[setJPstatus]}.`);
1875
+ }
1876
+ }
1877
+ };
1878
+
1879
+ if (networkAddress) {
1880
+ // specific device that is not `Coordinator`
1881
+ await this.queue.execute<void>(async () => {
1882
+ this.checkInterpanLock();
1883
+ await preJoining();
1884
+ });
1885
+
1886
+ // `authentication`: TC significance always 1 (zb specs)
1887
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
1888
+
1889
+ const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
1890
+
1891
+ /* v8 ignore start */
1892
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.PERMIT_JOINING_RESPONSE>(result)) {
1893
+ // TODO: will disappear once moved upstream
1894
+ throw new Zdo.StatusError(result[0]);
1895
+ }
1896
+ /* v8 ignore stop */
1897
+ } else {
1898
+ // coordinator-only (0), or all
1899
+ await this.queue.execute<void>(async () => {
1900
+ this.checkInterpanLock();
1901
+ await preJoining();
1902
+ });
1903
+
1904
+ const status = await this.ezsp.ezspPermitJoining(seconds);
1905
+
1906
+ if (status !== SLStatus.OK) {
1907
+ throw new Error(`[ZDO] Failed coordinator permit joining request with status=${SLStatus[status]}.`);
1908
+ }
1909
+
1910
+ logger.debug(`Permit joining on coordinator for ${seconds} sec.`, NS);
1911
+
1912
+ // broadcast permit joining ZDO
1913
+ if (networkAddress === undefined) {
1914
+ // `authentication`: TC significance always 1 (zb specs)
1915
+ const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
1916
+
1917
+ await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
1918
+ }
1919
+ }
1920
+ }
1921
+
1922
+ //---- ZCL
1923
+
1924
+ // queued, non-InterPAN
1925
+ public async sendZclFrameToEndpoint(
1926
+ ieeeAddr: string,
1927
+ networkAddress: number,
1928
+ endpoint: number,
1929
+ zclFrame: Zcl.Frame,
1930
+ timeout: number,
1931
+ disableResponse: boolean,
1932
+ disableRecovery: boolean,
1933
+ sourceEndpoint?: number,
1934
+ profileId?: number,
1935
+ ): Promise<ZclPayload | undefined> {
1936
+ const command = zclFrame.command;
1937
+ let commandResponseId: number | undefined;
1938
+
1939
+ if (command.response !== undefined && disableResponse === false) {
1940
+ commandResponseId = command.response;
1941
+ } else if (!zclFrame.header.frameControl.disableDefaultResponse) {
1942
+ commandResponseId = Zcl.Foundation.defaultRsp.ID;
1943
+ }
1944
+
1945
+ const apsFrame: EmberApsFrame = {
1946
+ profileId:
1947
+ profileId ?? ((sourceEndpoint && FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || FIXED_ENDPOINTS[0]).profileId,
1948
+ clusterId: zclFrame.cluster.ID,
1949
+ sourceEndpoint: sourceEndpoint || FIXED_ENDPOINTS[0].endpoint,
1950
+ destinationEndpoint: endpoint,
1951
+ options: DEFAULT_APS_OPTIONS,
1952
+ groupId: 0,
1953
+ sequence: 0, // set by stack
1954
+ };
1955
+
1956
+ // don't RETRY if no response expected
1957
+ if (commandResponseId === undefined) {
1958
+ apsFrame.options &= ~EmberApsOption.RETRY;
1959
+ }
1960
+
1961
+ const data = zclFrame.toBuffer();
1962
+
1963
+ return await this.queue.execute<ZclPayload | undefined>(async () => {
1964
+ this.checkInterpanLock();
1965
+
1966
+ logger.debug(
1967
+ () => `~~~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`,
1968
+ NS,
1969
+ );
1970
+
1971
+ for (let i = 1; i <= QUEUE_MAX_SEND_ATTEMPTS; i++) {
1972
+ let status: SLStatus = SLStatus.FAIL;
1973
+
1974
+ try {
1975
+ [status] = await this.ezsp.send(
1976
+ EmberOutgoingMessageType.DIRECT,
1977
+ networkAddress,
1978
+ apsFrame,
1979
+ data,
1980
+ 0, // alias
1981
+ 0, // alias seq
1982
+ );
1983
+ } catch (error) {
1984
+ if (error instanceof EzspError) {
1985
+ switch (error.code) {
1986
+ case EzspStatus.NO_TX_SPACE: {
1987
+ status = SLStatus.BUSY;
1988
+ break;
1989
+ }
1990
+ case EzspStatus.NOT_CONNECTED: {
1991
+ status = SLStatus.NETWORK_DOWN;
1992
+ break;
1993
+ }
1994
+ }
1995
+ }
1996
+ }
1997
+
1998
+ // `else if` order matters
1999
+ if (status === SLStatus.OK) {
2000
+ break;
2001
+ }
2002
+
2003
+ if (disableRecovery || i === QUEUE_MAX_SEND_ATTEMPTS) {
2004
+ throw new Error(
2005
+ `~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${SLStatus[status]}.`,
2006
+ );
2007
+ }
2008
+
2009
+ if (status === SLStatus.ZIGBEE_MAX_MESSAGE_LIMIT_REACHED || status === SLStatus.BUSY) {
2010
+ await wait(QUEUE_BUSY_DEFER_MSEC);
2011
+ } else if (status === SLStatus.NETWORK_DOWN) {
2012
+ await wait(QUEUE_NETWORK_DOWN_DEFER_MSEC);
2013
+ } else {
2014
+ throw new Error(
2015
+ `~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${SLStatus[status]}.`,
2016
+ );
2017
+ }
2018
+
2019
+ logger.debug(
2020
+ `~x~> [ZCL to=${ieeeAddr}:${networkAddress}] Failed to send request attempt ${i}/${QUEUE_MAX_SEND_ATTEMPTS} with status=${SLStatus[status]}.`,
2021
+ NS,
2022
+ );
2023
+ }
2024
+
2025
+ if (commandResponseId !== undefined) {
2026
+ // NOTE: aps sequence number will have been set by send function
2027
+ const result = await this.oneWaitress.startWaitingFor<ZclPayload>(
2028
+ {
2029
+ target: networkAddress,
2030
+ apsFrame,
2031
+ zclSequence: zclFrame.header.transactionSequenceNumber,
2032
+ commandIdentifier: commandResponseId,
2033
+ },
2034
+ timeout,
2035
+ );
2036
+
2037
+ return result;
2038
+ }
2039
+ }, networkAddress);
2040
+ }
2041
+
2042
+ // queued, non-InterPAN
2043
+ public async sendZclFrameToGroup(groupID: number, zclFrame: Zcl.Frame, sourceEndpoint?: number, profileId?: number): Promise<void> {
2044
+ const apsFrame: EmberApsFrame = {
2045
+ profileId:
2046
+ profileId ?? ((sourceEndpoint && FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || FIXED_ENDPOINTS[0]).profileId,
2047
+ clusterId: zclFrame.cluster.ID,
2048
+ sourceEndpoint: sourceEndpoint || FIXED_ENDPOINTS[0].endpoint,
2049
+ destinationEndpoint: 0xff,
2050
+ options: DEFAULT_APS_OPTIONS,
2051
+ groupId: groupID,
2052
+ sequence: 0, // set by stack
2053
+ };
2054
+ const data = zclFrame.toBuffer();
2055
+
2056
+ return await this.queue.execute<void>(async () => {
2057
+ this.checkInterpanLock();
2058
+
2059
+ logger.debug(() => `~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2060
+ const [status] = await this.ezsp.send(
2061
+ EmberOutgoingMessageType.MULTICAST,
2062
+ groupID, // not used with MULTICAST
2063
+ apsFrame,
2064
+ data,
2065
+ 0, // alias
2066
+ 0, // alias seq
2067
+ );
2068
+
2069
+ if (status !== SLStatus.OK) {
2070
+ throw new Error(`~x~> [ZCL GROUP groupId=${groupID}] Failed to send with status=${SLStatus[status]}.`);
2071
+ }
2072
+
2073
+ // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2074
+ await wait(QUEUE_BUSY_DEFER_MSEC);
2075
+ });
2076
+ }
2077
+
2078
+ // queued, non-InterPAN
2079
+ public async sendZclFrameToAll(
2080
+ endpoint: number,
2081
+ zclFrame: Zcl.Frame,
2082
+ sourceEndpoint: number,
2083
+ destination: ZSpec.BroadcastAddress,
2084
+ profileId?: number,
2085
+ ): Promise<void> {
2086
+ const apsFrame: EmberApsFrame = {
2087
+ profileId:
2088
+ profileId ?? ((sourceEndpoint && FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || FIXED_ENDPOINTS[0]).profileId,
2089
+ clusterId: zclFrame.cluster.ID,
2090
+ sourceEndpoint,
2091
+ destinationEndpoint: endpoint,
2092
+ options: DEFAULT_APS_OPTIONS,
2093
+ groupId: destination,
2094
+ sequence: 0, // set by stack
2095
+ };
2096
+ const data = zclFrame.toBuffer();
2097
+
2098
+ return await this.queue.execute<void>(async () => {
2099
+ this.checkInterpanLock();
2100
+
2101
+ logger.debug(() => `~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2102
+ const [status] = await this.ezsp.send(
2103
+ EmberOutgoingMessageType.BROADCAST,
2104
+ destination,
2105
+ apsFrame,
2106
+ data,
2107
+ 0, // alias
2108
+ 0, // alias seq
2109
+ );
2110
+
2111
+ if (status !== SLStatus.OK) {
2112
+ throw new Error(`~x~> [ZCL BROADCAST destination=${destination}] Failed to send with status=${SLStatus[status]}.`);
2113
+ }
2114
+
2115
+ // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2116
+ await wait(QUEUE_BUSY_DEFER_MSEC);
2117
+ });
2118
+ }
2119
+
2120
+ //---- InterPAN for Touchlink
2121
+ // XXX: There might be a better way to handle touchlink with ZLL ezsp functions, but I don't have any device to test so, didn't look into it...
2122
+ // TODO: check all this touchlink/interpan stuff
2123
+
2124
+ // queued
2125
+ public async setChannelInterPAN(channel: number): Promise<void> {
2126
+ return await this.queue.execute<void>(async () => {
2127
+ this.interpanLock = true;
2128
+ const status = await this.ezsp.ezspSetLogicalAndRadioChannel(channel);
2129
+
2130
+ if (status !== SLStatus.OK) {
2131
+ this.interpanLock = false; // XXX: ok?
2132
+ throw new Error(`Failed to set InterPAN channel to '${channel}' with status=${SLStatus[status]}.`);
2133
+ }
2134
+ });
2135
+ }
2136
+
2137
+ // queued
2138
+ public async sendZclFrameInterPANToIeeeAddr(zclFrame: Zcl.Frame, ieeeAddress: string): Promise<void> {
2139
+ return await this.queue.execute<void>(async () => {
2140
+ const msgBuffalo = new EzspBuffalo(Buffer.alloc(MAXIMUM_INTERPAN_LENGTH));
2141
+
2142
+ // cache-enabled getters
2143
+ const sourcePanId = await this.emberGetPanId();
2144
+ const sourceEui64 = await this.emberGetEui64();
2145
+
2146
+ msgBuffalo.writeUInt16(LONG_DEST_FRAME_CONTROL | MAC_ACK_REQUIRED); // macFrameControl
2147
+ msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2148
+ msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2149
+ msgBuffalo.writeIeeeAddr(ieeeAddress); // destAddress (longAddress)
2150
+ msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2151
+ msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2152
+ msgBuffalo.writeUInt16(STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2153
+ msgBuffalo.writeUInt8(EmberInterpanMessageType.UNICAST | INTERPAN_APS_FRAME_TYPE); // apsFrameControl
2154
+ msgBuffalo.writeUInt16(zclFrame.cluster.ID);
2155
+ msgBuffalo.writeUInt16(ZSpec.TOUCHLINK_PROFILE_ID);
2156
+
2157
+ logger.debug(() => `~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.header)}]`, NS);
2158
+ const status = await this.ezsp.ezspSendRawMessage(
2159
+ Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]),
2160
+ EmberTransmitPriority.NORMAL,
2161
+ true,
2162
+ );
2163
+
2164
+ if (status !== SLStatus.OK) {
2165
+ throw new Error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${SLStatus[status]}.`);
2166
+ }
2167
+
2168
+ // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2169
+ });
2170
+ }
2171
+
2172
+ // queued
2173
+ public async sendZclFrameInterPANBroadcast(zclFrame: Zcl.Frame, timeout: number, disableResponse: false): Promise<ZclPayload>;
2174
+ public async sendZclFrameInterPANBroadcast(zclFrame: Zcl.Frame, timeout: number, disableResponse: true): Promise<undefined>;
2175
+ public async sendZclFrameInterPANBroadcast(zclFrame: Zcl.Frame, timeout: number, disableResponse: boolean): Promise<ZclPayload | undefined> {
2176
+ const command = zclFrame.command;
2177
+
2178
+ if (!disableResponse && command.response === undefined) {
2179
+ throw new Error(`Command '${command.name}' has no response, cannot wait for response.`);
2180
+ }
2181
+
2182
+ const endpoint = FIXED_ENDPOINTS[0].endpoint;
2183
+ // just for waitress
2184
+ const apsFrame: EmberApsFrame = {
2185
+ profileId: ZSpec.TOUCHLINK_PROFILE_ID,
2186
+ clusterId: zclFrame.cluster.ID,
2187
+ sourceEndpoint: endpoint, // arbitrary since not sent over-the-air
2188
+ destinationEndpoint: endpoint,
2189
+ options: EmberApsOption.NONE,
2190
+ groupId: ZSpec.BroadcastAddress.SLEEPY,
2191
+ sequence: 0, // set by stack
2192
+ };
2193
+
2194
+ return await this.queue.execute<ZclPayload | undefined>(async () => {
2195
+ const msgBuffalo = new EzspBuffalo(Buffer.alloc(MAXIMUM_INTERPAN_LENGTH));
2196
+
2197
+ // cache-enabled getters
2198
+ const sourcePanId = await this.emberGetPanId();
2199
+ const sourceEui64 = await this.emberGetEui64();
2200
+
2201
+ msgBuffalo.writeUInt16(SHORT_DEST_FRAME_CONTROL); // macFrameControl
2202
+ msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2203
+ msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2204
+ msgBuffalo.writeUInt16(apsFrame.groupId); // destAddress (longAddress)
2205
+ msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2206
+ msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2207
+ msgBuffalo.writeUInt16(STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2208
+ msgBuffalo.writeUInt8(EmberInterpanMessageType.BROADCAST | INTERPAN_APS_FRAME_TYPE); // apsFrameControl
2209
+ msgBuffalo.writeUInt16(apsFrame.clusterId);
2210
+ msgBuffalo.writeUInt16(apsFrame.profileId);
2211
+
2212
+ const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]);
2213
+
2214
+ logger.debug(() => `~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.header)}]`, NS);
2215
+ const status = await this.ezsp.ezspSendRawMessage(data, EmberTransmitPriority.NORMAL, true);
2216
+
2217
+ if (status !== SLStatus.OK) {
2218
+ throw new Error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${SLStatus[status]}.`);
2219
+ }
2220
+
2221
+ // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2222
+
2223
+ if (!disableResponse && command.response !== undefined) {
2224
+ const result = await this.oneWaitress.startWaitingFor<ZclPayload>(
2225
+ {
2226
+ target: undefined,
2227
+ apsFrame: apsFrame,
2228
+ zclSequence: zclFrame.header.transactionSequenceNumber,
2229
+ commandIdentifier: command.response,
2230
+ },
2231
+ timeout,
2232
+ );
2233
+
2234
+ return result;
2235
+ }
2236
+ });
2237
+ }
2238
+
2239
+ // queued
2240
+ public async restoreChannelInterPAN(): Promise<void> {
2241
+ return await this.queue.execute<void>(async () => {
2242
+ const status = await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0]);
2243
+
2244
+ if (status !== SLStatus.OK) {
2245
+ throw new Error(`Failed to restore InterPAN channel to '${this.networkOptions.channelList[0]}' with status=${SLStatus[status]}.`);
2246
+ }
2247
+
2248
+ // let adapter settle down
2249
+ await wait(QUEUE_NETWORK_DOWN_DEFER_MSEC);
2250
+
2251
+ this.interpanLock = false;
2252
+ });
2253
+ }
2254
+
2255
+ //-- END Adapter implementation
2256
+
2257
+ private checkInterpanLock(): void {
2258
+ if (this.interpanLock) {
2259
+ throw new Error("[INTERPAN MODE] Cannot execute non-InterPAN commands.");
2260
+ }
2261
+ }
2262
+ }