@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,1791 @@
1
+ import assert from "node:assert";
2
+ import {Events as AdapterEvents} from '../../adapter';
3
+ import {wait} from "../../utils";
4
+ import {logger} from "../../utils/logger";
5
+ import * as timeService from "../../utils/timeService";
6
+ import * as ZSpec from "../../zspec";
7
+ import {BroadcastAddress} from "../../zspec/enums";
8
+ import type {Eui64} from "../../zspec/tstypes";
9
+ import * as Zcl from "../../zspec/zcl";
10
+ import type {TClusterCommandPayload, TClusterPayload, TPartialClusterAttributes} from "../../zspec/zcl/definition/clusters-types";
11
+ import type {ClusterDefinition, CustomClusters} from "../../zspec/zcl/definition/tstype";
12
+ import type {TZclFrame} from "../../zspec/zcl/zclFrame";
13
+ import * as Zdo from "../../zspec/zdo";
14
+ import type {BindingTableEntry, LQITableEntry, RoutingTableEntry} from "../../zspec/zdo/definition/tstypes";
15
+ import type {ControllerEventMap} from "../controller";
16
+ import {getOtaFirmware, getOtaIndex, OtaSession, parseOtaImage} from "../helpers/ota";
17
+ import zclTransactionSequenceNumber from "../helpers/zclTransactionSequenceNumber";
18
+ import type {
19
+ DatabaseEntry,
20
+ DeviceType,
21
+ KeyValue,
22
+ OtaDataSettings,
23
+ OtaExtraMetas,
24
+ OtaImage,
25
+ OtaSource,
26
+ OtaUpdateAvailableResult,
27
+ ZigbeeOtaImageMeta,
28
+ } from "../tstype";
29
+ import Endpoint, {type BindInternal} from "./endpoint";
30
+ import Entity from "./entity";
31
+
32
+ const NS = "zh:controller:device";
33
+
34
+ const INTERVIEW_GENBASIC_ATTRIBUTES = [
35
+ "modelId",
36
+ "manufacturerName",
37
+ "powerSource",
38
+ "zclVersion",
39
+ "appVersion",
40
+ "stackVersion",
41
+ "hwVersion",
42
+ "dateCode",
43
+ "swBuildId",
44
+ ] as const;
45
+
46
+ type CustomReadResponse = (frame: Zcl.Frame, endpoint: Endpoint) => boolean;
47
+
48
+ export enum InterviewState {
49
+ Pending = "PENDING",
50
+ InProgress = "IN_PROGRESS",
51
+ Successful = "SUCCESSFUL",
52
+ Failed = "FAILED",
53
+ }
54
+
55
+ export class Device extends Entity<ControllerEventMap> {
56
+ private databaseID: number;
57
+ // biome-ignore lint/style/useNamingConvention: cross-repo impact
58
+ private readonly ID: number;
59
+ #genBasic: TPartialClusterAttributes<"genBasic"> = {};
60
+ private _endpoints: Endpoint[];
61
+ private _ieeeAddr: string;
62
+ private _interviewState: InterviewState;
63
+ private _lastSeen?: number;
64
+ private _manufacturerID?: number;
65
+ private _networkAddress: number;
66
+ private _type: DeviceType;
67
+ private _linkquality?: number;
68
+ private _skipDefaultResponse: boolean;
69
+ private _customReadResponse?: CustomReadResponse;
70
+ private _lastDefaultResponseSequenceNumber?: number;
71
+ private _checkinInterval?: number;
72
+ private _pendingRequestTimeout: number;
73
+ private _customClusters: CustomClusters = {};
74
+ private _gpSecurityKey?: number[];
75
+ #scheduledOta: OtaSource | undefined;
76
+ #otaInProgress = false;
77
+
78
+ // Getters/setters
79
+ get ieeeAddr(): string {
80
+ return this._ieeeAddr;
81
+ }
82
+ set ieeeAddr(ieeeAddr: string) {
83
+ this._ieeeAddr = ieeeAddr;
84
+ }
85
+ get applicationVersion(): number | undefined {
86
+ return this.#genBasic.appVersion;
87
+ }
88
+ set applicationVersion(version: number) {
89
+ this.#genBasic.appVersion = version;
90
+ }
91
+ get endpoints(): Endpoint[] {
92
+ return this._endpoints;
93
+ }
94
+ get interviewState(): InterviewState {
95
+ return this._interviewState;
96
+ }
97
+ get lastSeen(): number | undefined {
98
+ return this._lastSeen;
99
+ }
100
+ get manufacturerID(): number | undefined {
101
+ return this._manufacturerID;
102
+ }
103
+ get isDeleted(): boolean {
104
+ return Device.deletedDevices.get(this.databaseID)?.has(this.ieeeAddr) ?? false;
105
+ }
106
+ set type(type: DeviceType) {
107
+ this._type = type;
108
+ }
109
+ get type(): DeviceType {
110
+ return this._type;
111
+ }
112
+ get dateCode(): string | undefined {
113
+ return this.#genBasic.dateCode;
114
+ }
115
+ set dateCode(code: string) {
116
+ this.#genBasic.dateCode = code;
117
+ }
118
+ set hardwareVersion(version: number) {
119
+ this.#genBasic.hwVersion = version;
120
+ }
121
+ get hardwareVersion(): number | undefined {
122
+ return this.#genBasic.hwVersion;
123
+ }
124
+ get manufacturerName(): string | undefined {
125
+ return this.#genBasic.manufacturerName;
126
+ }
127
+ set manufacturerName(name: string | undefined) {
128
+ this.#genBasic.manufacturerName = name;
129
+ }
130
+ set modelID(id: string) {
131
+ this.#genBasic.modelId = id;
132
+ }
133
+ get modelID(): string | undefined {
134
+ return this.#genBasic.modelId;
135
+ }
136
+ get networkAddress(): number {
137
+ return this._networkAddress;
138
+ }
139
+ set networkAddress(networkAddress: number) {
140
+ Device.nwkToIeeeCache.get(this.databaseID)?.delete(this._networkAddress);
141
+
142
+ this._networkAddress = networkAddress;
143
+
144
+ Device.nwkToIeeeCache.get(this.databaseID)?.set(this._networkAddress, this.ieeeAddr);
145
+
146
+ for (const endpoint of this._endpoints) {
147
+ endpoint.deviceNetworkAddress = networkAddress;
148
+ }
149
+ }
150
+ get powerSource(): string | undefined {
151
+ return this.#genBasic.powerSource ? Zcl.POWER_SOURCES[this.#genBasic.powerSource] : undefined;
152
+ }
153
+ set powerSource(source: string | number) {
154
+ if (typeof source === "number") {
155
+ this.#genBasic.powerSource = source & ~(1 << 7);
156
+ } else {
157
+ for (const key in Zcl.POWER_SOURCES) {
158
+ const val = Zcl.POWER_SOURCES[key];
159
+
160
+ if (val === source) {
161
+ this.#genBasic.powerSource = Number(key);
162
+ break;
163
+ }
164
+ }
165
+ }
166
+ }
167
+ get softwareBuildID(): string | undefined {
168
+ return this.#genBasic.swBuildId;
169
+ }
170
+ set softwareBuildID(id: string) {
171
+ this.#genBasic.swBuildId = id;
172
+ }
173
+ get stackVersion(): number | undefined {
174
+ return this.#genBasic.stackVersion;
175
+ }
176
+ set stackVersion(version: number) {
177
+ this.#genBasic.stackVersion = version;
178
+ }
179
+ get zclVersion(): number | undefined {
180
+ return this.#genBasic.zclVersion;
181
+ }
182
+ set zclVersion(version: number) {
183
+ this.#genBasic.zclVersion = version;
184
+ }
185
+ get linkquality(): number | undefined {
186
+ return this._linkquality;
187
+ }
188
+ set linkquality(linkquality: number) {
189
+ this._linkquality = linkquality;
190
+ }
191
+ get skipDefaultResponse(): boolean {
192
+ return this._skipDefaultResponse;
193
+ }
194
+ set skipDefaultResponse(skipDefaultResponse: boolean) {
195
+ this._skipDefaultResponse = skipDefaultResponse;
196
+ }
197
+ get customReadResponse(): CustomReadResponse | undefined {
198
+ return this._customReadResponse;
199
+ }
200
+ set customReadResponse(customReadResponse: CustomReadResponse | undefined) {
201
+ this._customReadResponse = customReadResponse;
202
+ }
203
+ get checkinInterval(): number | undefined {
204
+ return this._checkinInterval;
205
+ }
206
+ set checkinInterval(checkinInterval: number | undefined) {
207
+ this._checkinInterval = checkinInterval;
208
+
209
+ this.resetPendingRequestTimeout();
210
+ }
211
+ get pendingRequestTimeout(): number {
212
+ return this._pendingRequestTimeout;
213
+ }
214
+ set pendingRequestTimeout(pendingRequestTimeout: number) {
215
+ this._pendingRequestTimeout = pendingRequestTimeout;
216
+ }
217
+ get customClusters(): CustomClusters {
218
+ return this._customClusters;
219
+ }
220
+ get gpSecurityKey(): number[] | undefined {
221
+ return this._gpSecurityKey;
222
+ }
223
+ get genBasic(): TPartialClusterAttributes<"genBasic"> {
224
+ return this.#genBasic;
225
+ }
226
+ get scheduledOta(): OtaSource | undefined {
227
+ return this.#scheduledOta;
228
+ }
229
+ get otaInProgress(): boolean {
230
+ return this.#otaInProgress;
231
+ }
232
+
233
+ public meta: KeyValue;
234
+
235
+ // This lookup contains all devices that are queried from the database, this is to ensure that always
236
+ // the same instance is returned.
237
+ private static readonly devices: Map<number, Map<string, Device>> = new Map<number, Map<string, Device>>();
238
+ private static loadedFromDatabase = false;
239
+ private static readonly deletedDevices: Map<number /* databaseID */, Map<string /* IEEE */, Device>> = new Map();
240
+ private static readonly nwkToIeeeCache: Map<number /* databaseID */, Map<number /* nwk addr */, string /* IEEE */>> = new Map();
241
+
242
+ private constructor(
243
+ databaseID: number,
244
+ id: number,
245
+ type: DeviceType,
246
+ ieeeAddr: string,
247
+ networkAddress: number,
248
+ manufacturerID: number | undefined,
249
+ endpoints: Endpoint[],
250
+ manufacturerName: string | undefined,
251
+ powerSource: string | undefined,
252
+ modelID: string | undefined,
253
+ applicationVersion: number | undefined,
254
+ stackVersion: number | undefined,
255
+ zclVersion: number | undefined,
256
+ hardwareVersion: number | undefined,
257
+ dateCode: string | undefined,
258
+ softwareBuildID: string | undefined,
259
+ interviewState: InterviewState,
260
+ meta: KeyValue,
261
+ lastSeen: number | undefined,
262
+ checkinInterval: number | undefined,
263
+ pendingRequestTimeout: number,
264
+ gpSecurityKey: number[] | undefined,
265
+ scheduledOta: OtaSource | undefined,
266
+ ) {
267
+ super();
268
+ this.databaseID = databaseID;
269
+ this.ID = id;
270
+ this._type = type;
271
+ this._ieeeAddr = ieeeAddr;
272
+ this._networkAddress = networkAddress;
273
+ this._manufacturerID = manufacturerID;
274
+ this._endpoints = endpoints;
275
+ this.#genBasic.manufacturerName = manufacturerName;
276
+ this.powerSource = powerSource ?? Zcl.PowerSource.Unknown;
277
+ this.#genBasic.modelId = modelID;
278
+ this.#genBasic.appVersion = applicationVersion;
279
+ this.#genBasic.stackVersion = stackVersion;
280
+ this.#genBasic.zclVersion = zclVersion;
281
+ this.#genBasic.hwVersion = hardwareVersion;
282
+ this.#genBasic.dateCode = dateCode;
283
+ this.#genBasic.swBuildId = softwareBuildID;
284
+ this._interviewState = interviewState;
285
+ this._skipDefaultResponse = false;
286
+ this.meta = meta;
287
+ this._lastSeen = lastSeen;
288
+ this._checkinInterval = checkinInterval;
289
+ this._pendingRequestTimeout = pendingRequestTimeout;
290
+ this._gpSecurityKey = gpSecurityKey;
291
+ this.#scheduledOta = scheduledOta;
292
+ }
293
+
294
+ public createEndpoint(id: number): Endpoint {
295
+ if (this.getEndpoint(id)) {
296
+ throw new Error(`Device '${this.ieeeAddr}' already has an endpoint '${id}'`);
297
+ }
298
+
299
+ const endpoint = Endpoint.create(this.databaseID, id, undefined, undefined, [], [],
300
+ this.networkAddress, this.ieeeAddr
301
+ );
302
+ this.endpoints.push(endpoint);
303
+ this.save();
304
+ return endpoint;
305
+ }
306
+
307
+ public changeIeeeAddress(ieeeAddr: string): void {
308
+ Device.devices.get(this.databaseID)?.delete(this.ieeeAddr);
309
+ this.ieeeAddr = ieeeAddr;
310
+ Device.devices.get(this.databaseID)?.set(this.ieeeAddr, this);
311
+ Device.nwkToIeeeCache.get(this.databaseID)?.set(this.networkAddress, this.ieeeAddr);
312
+ for (const ep of this.endpoints) {
313
+ ep.deviceIeeeAddress = ieeeAddr;
314
+ }
315
+
316
+ this.save();
317
+ }
318
+
319
+ public getEndpoint(id: number): Endpoint | undefined {
320
+ return this.endpoints.find((e): boolean => e.ID === id);
321
+ }
322
+
323
+ // There might be multiple endpoints with same DeviceId but it is not supported and first endpoint is returned
324
+ public getEndpointByDeviceType(deviceType: string): Endpoint | undefined {
325
+ const deviceID = Zcl.ENDPOINT_DEVICE_TYPE[deviceType];
326
+ return this.endpoints.find((d): boolean => d.deviceID === deviceID);
327
+ }
328
+
329
+ public updateGenBasic(data: TPartialClusterAttributes<"genBasic">): void {
330
+ Object.assign(this.#genBasic, data);
331
+ }
332
+
333
+ public implicitCheckin(): void {
334
+ // No need to do anythign in `catch` as `endpoint.sendRequest` already logs failures.
335
+ Promise.allSettled(this.endpoints.map((e) => e.sendPendingRequests(false))).catch(() => {});
336
+ }
337
+
338
+ public updateLastSeen(): void {
339
+ this._lastSeen = Date.now();
340
+ }
341
+
342
+ private resetPendingRequestTimeout(): void {
343
+ // pendingRequestTimeout can be changed dynamically at runtime, and it is not persisted.
344
+ // Default timeout is one checkin interval in milliseconds.
345
+ this._pendingRequestTimeout = (this._checkinInterval ?? 0) * 1000;
346
+ }
347
+
348
+ private hasPendingRequests(): boolean {
349
+ return this.endpoints.find((e) => e.hasPendingRequests()) !== undefined;
350
+ }
351
+
352
+ public async onZclData(dataPayload: AdapterEvents.ZclPayload, frame: Zcl.Frame, endpoint: Endpoint): Promise<void> {
353
+ if (!Device.devices.get(this.databaseID)?.has(this.ieeeAddr)) {
354
+ // prevent race conditions where device gets deleted during processing
355
+ return;
356
+ }
357
+
358
+ if (frame.header.isGlobal) {
359
+ // Response to read requests
360
+ if (frame.command.name === "read" && !this._customReadResponse?.(frame, endpoint)) {
361
+ const attributes: {[s: string]: KeyValue} = {
362
+ ...endpoint.clusters,
363
+ };
364
+
365
+ const isTimeReadRequest = dataPayload.clusterID === Zcl.Clusters.genTime.ID;
366
+ if (isTimeReadRequest) {
367
+ attributes.genTime = {
368
+ attributes: timeService.getTimeClusterAttributes(),
369
+ };
370
+ }
371
+
372
+ if (frame.cluster.name in attributes) {
373
+ const response: KeyValue = {};
374
+
375
+ for (const entry of frame.payload) {
376
+ const name = frame.cluster.getAttribute(entry.attrId)?.name;
377
+
378
+ if (name && name in attributes[frame.cluster.name].attributes) {
379
+ response[name] = attributes[frame.cluster.name].attributes[name];
380
+ }
381
+ }
382
+
383
+ try {
384
+ await endpoint.readResponse(frame.cluster.ID, frame.header.transactionSequenceNumber, response, {
385
+ srcEndpoint: dataPayload.destinationEndpoint,
386
+ });
387
+ } catch (error) {
388
+ logger.error(`Read response to ${this.ieeeAddr} failed (${(error as Error).message})`, NS);
389
+ }
390
+ }
391
+ }
392
+ } else if (frame.header.isSpecific) {
393
+ switch (frame.cluster.name) {
394
+ case "ssIasZone": {
395
+ if (frame.command.name === "enrollReq") {
396
+ // Respond to enroll requests
397
+ logger.debug(`IAS - '${this.ieeeAddr}' responding to enroll response`, NS);
398
+
399
+ await endpoint.command("ssIasZone", "enrollRsp", {enrollrspcode: 0, zoneid: 23}, {disableDefaultResponse: true});
400
+ }
401
+ break;
402
+ }
403
+ case "genPollCtrl": {
404
+ if (frame.command.name === "checkin") {
405
+ // Handle check-in from sleeping end devices
406
+ try {
407
+ if (this.hasPendingRequests() || this._checkinInterval === undefined) {
408
+ logger.debug(`check-in from ${this.ieeeAddr}: accepting fast-poll`, NS);
409
+ await endpoint.command(
410
+ frame.cluster.name as "genPollCtrl",
411
+ "checkinRsp",
412
+ {
413
+ startFastPolling: 1,
414
+ fastPollTimeout: 0,
415
+ },
416
+ {sendPolicy: "immediate"},
417
+ );
418
+
419
+ // This is a good time to read the checkin interval if we haven't stored it previously
420
+ if (this._checkinInterval === undefined) {
421
+ const pollPeriod = await endpoint.read("genPollCtrl", ["checkinInterval"], {sendPolicy: "immediate"});
422
+ this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds
423
+ this.resetPendingRequestTimeout();
424
+ logger.debug(
425
+ `Request Queue (${this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`,
426
+ NS,
427
+ );
428
+ }
429
+
430
+ await Promise.all(this.endpoints.map(async (e) => await e.sendPendingRequests(true)));
431
+ // We *must* end fast-poll when we're done sending things. Otherwise
432
+ // we cause undue power-drain.
433
+ logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS);
434
+ await endpoint.command(frame.cluster.name as "genPollCtrl", "fastPollStop", {}, {sendPolicy: "immediate"});
435
+ } else {
436
+ logger.debug(`check-in from ${this.ieeeAddr}: declining fast-poll`, NS);
437
+ await endpoint.command(
438
+ frame.cluster.name as "genPollCtrl",
439
+ "checkinRsp",
440
+ {
441
+ startFastPolling: 0,
442
+ fastPollTimeout: 0,
443
+ },
444
+ {sendPolicy: "immediate"},
445
+ );
446
+ }
447
+ } catch (error) {
448
+ logger.error(`Handling of poll check-in from ${this.ieeeAddr} failed (${(error as Error).message})`, NS);
449
+ }
450
+ }
451
+ break;
452
+ }
453
+ }
454
+ }
455
+
456
+ // Send a default response if necessary.
457
+ const isDefaultResponse = frame.header.isGlobal && frame.command.name === "defaultRsp";
458
+ const commandHasResponse = frame.command.response !== undefined;
459
+ const disableDefaultResponse = frame.header.frameControl.disableDefaultResponse;
460
+ /* v8 ignore next */
461
+ const disableTuyaDefaultResponse = this.manufacturerName?.startsWith("_TZ") && process.env.DISABLE_TUYA_DEFAULT_RESPONSE;
462
+ // Sometimes messages are received twice, prevent responding twice
463
+ const alreadyResponded = this._lastDefaultResponseSequenceNumber === frame.header.transactionSequenceNumber;
464
+
465
+ if (
466
+ this.type !== "GreenPower" &&
467
+ !dataPayload.wasBroadcast &&
468
+ !disableDefaultResponse &&
469
+ !isDefaultResponse &&
470
+ !commandHasResponse &&
471
+ !this._skipDefaultResponse &&
472
+ !alreadyResponded &&
473
+ !disableTuyaDefaultResponse
474
+ ) {
475
+ try {
476
+ this._lastDefaultResponseSequenceNumber = frame.header.transactionSequenceNumber;
477
+ // In the ZCL it is not documented what the direction of the default response should be
478
+ // In https://github.com/Koenkk/zigbee2mqtt/issues/18096 a commandResponse (SERVER_TO_CLIENT)
479
+ // is send and the device expects a CLIENT_TO_SERVER back.
480
+ // Previously SERVER_TO_CLIENT was always used.
481
+ // Therefore for non-global commands we inverse the direction.
482
+ const direction = frame.header.isGlobal
483
+ ? Zcl.Direction.SERVER_TO_CLIENT
484
+ : frame.header.frameControl.direction === Zcl.Direction.CLIENT_TO_SERVER
485
+ ? Zcl.Direction.SERVER_TO_CLIENT
486
+ : Zcl.Direction.CLIENT_TO_SERVER;
487
+
488
+ await endpoint.defaultResponse(frame.command.ID, 0, frame.cluster.ID, frame.header.transactionSequenceNumber, {direction});
489
+ } catch (error) {
490
+ logger.debug(`Default response to ${this.ieeeAddr} failed (${error})`, NS);
491
+ }
492
+ }
493
+ }
494
+
495
+ /*
496
+ * CRUD
497
+ */
498
+
499
+ /**
500
+ * Reset runtime lookups.
501
+ */
502
+ public static resetCache(): void {
503
+ Device.devices.clear();
504
+ Device.loadedFromDatabase = false;
505
+ Device.deletedDevices.clear();
506
+ Device.nwkToIeeeCache.clear();
507
+ }
508
+
509
+ private static fromDatabaseEntry(entry: DatabaseEntry, databaseID: number): Device {
510
+ const networkAddress = entry.nwkAddr;
511
+ const ieeeAddr = entry.ieeeAddr;
512
+ const endpoints: Endpoint[] = [];
513
+
514
+ for (const id in entry.endpoints) {
515
+ endpoints.push(Endpoint.fromDatabaseRecord(entry.endpoints[id], networkAddress, ieeeAddr, databaseID));
516
+ }
517
+
518
+ const meta = entry.meta ?? {};
519
+
520
+ if (entry.type === "Group") {
521
+ throw new Error("Cannot load device from group");
522
+ }
523
+
524
+ // default: no timeout (messages expire immediately after first send attempt)
525
+ let pendingRequestTimeout = 0;
526
+ if (endpoints.filter((e): boolean => e.inputClusters.includes(Zcl.Clusters.genPollCtrl.ID)).length > 0) {
527
+ // default for devices that support genPollCtrl cluster (RX off when idle): 1 day
528
+ pendingRequestTimeout = 86400000;
529
+ }
530
+ // always load value from database available (modernExtend.quirkCheckinInterval() exists for devices without genPollCtl)
531
+ if (entry.checkinInterval !== undefined) {
532
+ // if the checkin interval is known, messages expire by default after one checkin interval
533
+ pendingRequestTimeout = entry.checkinInterval * 1000; // milliseconds
534
+ }
535
+ logger.debug(`Request Queue (${ieeeAddr}): default expiration timeout set to ${pendingRequestTimeout}`, NS);
536
+
537
+ // Migrate interviewCompleted to interviewState
538
+ if (!entry.interviewState) {
539
+ entry.interviewState = entry.interviewCompleted ? InterviewState.Successful : InterviewState.Failed;
540
+ logger.debug(`Migrated interviewState for '${ieeeAddr}': ${entry.interviewCompleted} -> ${entry.interviewState}`, NS);
541
+ }
542
+
543
+ return new Device(
544
+ databaseID,
545
+ entry.id,
546
+ entry.type,
547
+ ieeeAddr,
548
+ networkAddress,
549
+ entry.manufId,
550
+ endpoints,
551
+ entry.manufName,
552
+ entry.powerSource,
553
+ entry.modelId,
554
+ entry.appVersion,
555
+ entry.stackVersion,
556
+ entry.zclVersion,
557
+ entry.hwVersion,
558
+ entry.dateCode,
559
+ entry.swBuildId,
560
+ entry.interviewState,
561
+ meta,
562
+ entry.lastSeen,
563
+ entry.checkinInterval,
564
+ pendingRequestTimeout,
565
+ entry.gpSecurityKey,
566
+ entry.scheduledOta,
567
+ );
568
+ }
569
+
570
+ private toDatabaseEntry(): DatabaseEntry {
571
+ const epList = this.endpoints.map((e): number => e.ID);
572
+ const endpoints: KeyValue = {};
573
+
574
+ for (const endpoint of this.endpoints) {
575
+ endpoints[endpoint.ID] = endpoint.toDatabaseRecord();
576
+ }
577
+
578
+ return {
579
+ id: this.ID,
580
+ type: this.type,
581
+ ieeeAddr: this.ieeeAddr,
582
+ nwkAddr: this.networkAddress,
583
+ manufId: this.manufacturerID,
584
+ manufName: this.manufacturerName,
585
+ powerSource: this.powerSource,
586
+ modelId: this.modelID,
587
+ epList,
588
+ endpoints,
589
+ appVersion: this.applicationVersion,
590
+ stackVersion: this.stackVersion,
591
+ hwVersion: this.hardwareVersion,
592
+ dateCode: this.dateCode,
593
+ swBuildId: this.softwareBuildID,
594
+ zclVersion: this.zclVersion,
595
+ /** @deprecated Keep interviewCompleted for backwards compatibility (in case zh gets downgraded) */
596
+ interviewCompleted: this.interviewState === InterviewState.Successful,
597
+ interviewState: this.interviewState === InterviewState.InProgress ? InterviewState.Pending : this.interviewState,
598
+ meta: this.meta,
599
+ lastSeen: this.lastSeen,
600
+ checkinInterval: this.checkinInterval,
601
+ gpSecurityKey: this.gpSecurityKey,
602
+ scheduledOta: this.scheduledOta,
603
+ };
604
+ }
605
+
606
+ public save(writeDatabase = true): void {
607
+ Entity.getDatabaseByID(this.databaseID)?.update(this.toDatabaseEntry(), writeDatabase);
608
+ }
609
+
610
+ private static loadFromDatabaseIfNecessary(): void {
611
+ if (!Device.loadedFromDatabase) {
612
+ Entity.databases.forEach(database => {
613
+ if (!Device.devices.has(database.id)) {
614
+ Device.devices.set(database.id, new Map<string, Device>());
615
+ Device.deletedDevices.set(database.id, new Map<string, Device>());
616
+ Device.nwkToIeeeCache.set(database.id, new Map<number, string>());
617
+ const entries = database.getEntriesIterator(['Coordinator', 'EndDevice', 'Router', 'GreenPower', 'Unknown']);
618
+ for (const entry of entries) {
619
+ const device = Device.fromDatabaseEntry(entry, database.id);
620
+ Device.devices.get(database.id)!.set(device.ieeeAddr, device);
621
+ Device.nwkToIeeeCache.get(database.id)!.set(device.networkAddress, device.ieeeAddr);
622
+ }
623
+ }
624
+ });
625
+
626
+ Device.loadedFromDatabase = true;
627
+ }
628
+ }
629
+
630
+ public static find(databaseID: number, ieeeOrNwkAddress: string | number, includeDeleted = false): Device | undefined {
631
+ return typeof ieeeOrNwkAddress === "string"
632
+ ? Device.byIeeeAddr(databaseID, ieeeOrNwkAddress, includeDeleted)
633
+ : Device.byNetworkAddress(databaseID, ieeeOrNwkAddress, includeDeleted);
634
+ }
635
+
636
+ public static byIeeeAddr(databaseID: number, ieeeAddr: string, includeDeleted = false): Device | undefined {
637
+ Device.loadFromDatabaseIfNecessary();
638
+ const device = Device.devices.get(databaseID)?.get(ieeeAddr);
639
+ return includeDeleted ? (Device.deletedDevices.get(databaseID)?.get(ieeeAddr) ?? device) : device;
640
+ }
641
+
642
+ public static byNetworkAddress(databaseID: number, networkAddress: number, includeDeleted = false): Device | undefined {
643
+ Device.loadFromDatabaseIfNecessary();
644
+
645
+ const ieeeAddr = Device.nwkToIeeeCache.get(databaseID)?.get(networkAddress);
646
+
647
+ return ieeeAddr ? Device.byIeeeAddr(databaseID, ieeeAddr, includeDeleted) : undefined;
648
+ }
649
+
650
+ public static byType(databaseID: number, type: DeviceType): Device[] {
651
+ return Device.allByDatabaseID(databaseID).filter(d => d.type === type);
652
+ }
653
+
654
+ public static allByDatabaseID(databaseID: number): Device[] {
655
+ Device.loadFromDatabaseIfNecessary();
656
+ return Array.from(Device.devices.get(databaseID)?.values() ?? []);
657
+ }
658
+
659
+ /** Check if a device is explicitly deleted */
660
+ public static isDeletedByIeeeAddr(databaseID: number, ieeeAddr: string): boolean {
661
+ Device.loadFromDatabaseIfNecessary();
662
+
663
+ return Device.deletedDevices.get(databaseID)?.has(ieeeAddr) ?? false;
664
+ }
665
+
666
+ /** Check if a device is explicitly deleted */
667
+ public static isDeletedByNetworkAddress(databaseID: number, networkAddress: number): boolean {
668
+ Device.loadFromDatabaseIfNecessary();
669
+
670
+ const ieeeAddr = Device.nwkToIeeeCache.get(databaseID)?.get(networkAddress);
671
+
672
+ return ieeeAddr ? Device.deletedDevices.get(databaseID)?.has(ieeeAddr) ?? false : false;
673
+ }
674
+
675
+ // public static all(): Device[] {
676
+ // Device.loadFromDatabaseIfNecessary();
677
+ // return Array.from(Device.devices.values());
678
+ // }
679
+
680
+ public static *allIterator(databaseID: number, predicate?: (value: Device) => boolean): Generator<Device> {
681
+ Device.loadFromDatabaseIfNecessary();
682
+
683
+ for (const device of Device.allByDatabaseID(databaseID)) {
684
+ if (!predicate || predicate(device)) {
685
+ yield device;
686
+ }
687
+ }
688
+ }
689
+
690
+ public undelete(): void {
691
+ if (Device.deletedDevices.get(this.databaseID)?.delete(this.ieeeAddr)) {
692
+ Device.devices.get(this.databaseID)?.set(this.ieeeAddr, this);
693
+
694
+ Entity.getDatabaseByID(this.databaseID)?.insert(this.toDatabaseEntry());
695
+ } else {
696
+ throw new Error(`Device '${this.ieeeAddr}' is not deleted`);
697
+ }
698
+ }
699
+
700
+ public static create(
701
+ type: DeviceType,
702
+ ieeeAddr: string,
703
+ networkAddress: number,
704
+ manufacturerID: number | undefined,
705
+ manufacturerName: string | undefined,
706
+ powerSource: string | undefined,
707
+ modelID: string | undefined,
708
+ interviewState: InterviewState,
709
+ gpSecurityKey: number[] | undefined,
710
+ databaseID: number,
711
+ ): Device {
712
+ Device.loadFromDatabaseIfNecessary();
713
+
714
+ if (Device.devices.get(databaseID)?.has(ieeeAddr)) {
715
+ throw new Error(`Device with IEEE address '${ieeeAddr}' already exists`);
716
+ }
717
+ const database = Entity.getDatabaseByID(databaseID);
718
+ if (!database) {
719
+ throw new Error(`Database with ID '${databaseID}' not found`);
720
+ }
721
+
722
+ const ID = database.newID();
723
+ const device = new Device(
724
+ databaseID,
725
+ ID,
726
+ type,
727
+ ieeeAddr,
728
+ networkAddress,
729
+ manufacturerID,
730
+ [],
731
+ manufacturerName,
732
+ powerSource,
733
+ modelID,
734
+ undefined,
735
+ undefined,
736
+ undefined,
737
+ undefined,
738
+ undefined,
739
+ undefined,
740
+ interviewState,
741
+ {},
742
+ undefined,
743
+ undefined,
744
+ 0,
745
+ gpSecurityKey,
746
+ undefined,
747
+ );
748
+
749
+ database.insert(device.toDatabaseEntry());
750
+ Device.devices.get(databaseID)?.set(device.ieeeAddr, device);
751
+ Device.nwkToIeeeCache.get(databaseID)?.set(device.networkAddress, device.ieeeAddr);
752
+ return device;
753
+ }
754
+
755
+ /*
756
+ * Zigbee functions
757
+ */
758
+
759
+ public async interview(ignoreCache = false): Promise<void> {
760
+ if (this.interviewState === InterviewState.InProgress) {
761
+ const message = `Interview - interview already in progress for '${this.ieeeAddr}'`;
762
+ logger.debug(message, NS);
763
+ throw new Error(message);
764
+ }
765
+
766
+ let err: unknown;
767
+ this._interviewState = InterviewState.InProgress;
768
+ logger.debug(`Interview - start device '${this.ieeeAddr}'`, NS);
769
+
770
+ try {
771
+ await this.interviewInternal(ignoreCache);
772
+ logger.debug(`Interview - completed for device '${this.ieeeAddr}'`, NS);
773
+ this._interviewState = InterviewState.Successful;
774
+ } catch (error) {
775
+ if (this.interviewQuirks()) {
776
+ this._interviewState = InterviewState.Successful;
777
+ logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`, NS);
778
+ } else {
779
+ this._interviewState = InterviewState.Failed;
780
+ logger.debug(`Interview - failed for device '${this.ieeeAddr}' with error '${error}'`, NS);
781
+ err = error;
782
+ }
783
+ } finally {
784
+ this.save();
785
+ }
786
+
787
+ if (err) {
788
+ throw err;
789
+ }
790
+ }
791
+
792
+ private interviewQuirks(): boolean {
793
+ logger.debug(`Interview - quirks check for '${this.modelID}'-'${this.manufacturerName}'-'${this.type}'`, NS);
794
+
795
+ // Tuya devices are typically hard to interview. They also don't require a full interview to work correctly
796
+ // e.g. no ias enrolling is required for the devices to work.
797
+ // Assume that in case we got both the manufacturerName and modelID the device works correctly.
798
+ // https://github.com/Koenkk/zigbee2mqtt/issues/7564:
799
+ // Fails during ias enroll due to UNSUPPORTED_ATTRIBUTE
800
+ // https://github.com/Koenkk/zigbee2mqtt/issues/4655
801
+ // Device does not change zoneState after enroll (event with original gateway)
802
+ // modelID is mostly in the form of e.g. TS0202 and manufacturerName like e.g. _TYZB01_xph99wvr
803
+ if (
804
+ this.manufacturerName === "HOBEIAN" ||
805
+ (this.modelID?.match("^TS\\d*$") && (this.manufacturerName?.match("^_TZ.*_.*$") || this.manufacturerName?.match("^_TYZB01_.*$")))
806
+ ) {
807
+ this.#genBasic.powerSource = this.#genBasic.powerSource || Zcl.PowerSource.Battery;
808
+ logger.debug("Interview - quirks matched for Tuya end device", NS);
809
+ return true;
810
+ }
811
+
812
+ // Some devices, e.g. Xiaomi end devices have a different interview procedure, after pairing they
813
+ // report it's modelID trough a readResponse. The readResponse is received by the controller and set
814
+ // on the device.
815
+ const lookup: {
816
+ [s: string]: {
817
+ type?: DeviceType;
818
+ manufacturerID?: number;
819
+ manufacturerName?: string;
820
+ powerSource?: Zcl.PowerSource;
821
+ };
822
+ } = {
823
+ "^3R.*?Z": {
824
+ type: "EndDevice",
825
+ powerSource: Zcl.PowerSource.Battery,
826
+ },
827
+ "lumi..*": {
828
+ type: "EndDevice",
829
+ manufacturerID: 4151,
830
+ manufacturerName: "LUMI",
831
+ powerSource: Zcl.PowerSource.Battery,
832
+ },
833
+ "TERNCY-PP01": {
834
+ type: "EndDevice",
835
+ manufacturerID: 4648,
836
+ manufacturerName: "TERNCY",
837
+ powerSource: Zcl.PowerSource.Battery,
838
+ },
839
+ "3RWS18BZ": {}, // https://github.com/Koenkk/zigbee-herdsman-converters/pull/2710
840
+ "MULTI-MECI--EA01": {},
841
+ MOT003: {}, // https://github.com/Koenkk/zigbee2mqtt/issues/12471
842
+ "C-ZB-SEDC": {}, //candeo device that doesn't follow IAS enrollment process correctly and therefore fails to complete interview
843
+ "C-ZB-SEMO": {}, //candeo device that doesn't follow IAS enrollment process correctly and therefore fails to complete interview
844
+ "CS-T9C-A0-BG": {}, // iAS enroll fails: https://github.com/Koenkk/zigbee2mqtt/issues/27822
845
+ "SNZB-01": {}, // iAS enroll fails: https://github.com/Koenkk/zigbee2mqtt/issues/29474
846
+ };
847
+
848
+ let match: string | undefined;
849
+
850
+ for (const key in lookup) {
851
+ if (this.modelID?.match(key)) {
852
+ match = key;
853
+ break;
854
+ }
855
+ }
856
+
857
+ if (match) {
858
+ const info = lookup[match];
859
+ logger.debug(`Interview procedure failed but got modelID matching '${match}', assuming interview succeeded`, NS);
860
+ this._type = this._type === "Unknown" && info.type ? info.type : this._type;
861
+ this._manufacturerID = this._manufacturerID || info.manufacturerID;
862
+ this.#genBasic.manufacturerName = this.#genBasic.manufacturerName || info.manufacturerName;
863
+ this.#genBasic.powerSource = (this.#genBasic.powerSource || info.powerSource) /* v8 ignore next */ ?? Zcl.PowerSource.Unknown;
864
+ logger.debug(`Interview - quirks matched on '${match}'`, NS);
865
+ return true;
866
+ }
867
+
868
+ logger.debug("Interview - quirks did not match", NS);
869
+ return false;
870
+ }
871
+
872
+ private async interviewInternal(ignoreCache: boolean): Promise<void> {
873
+ const hasNodeDescriptor = (): boolean => this._manufacturerID !== undefined && this._type !== "Unknown";
874
+
875
+ if (ignoreCache || !hasNodeDescriptor()) {
876
+ for (let attempt = 0; attempt < 6; attempt++) {
877
+ try {
878
+ await this.updateNodeDescriptor();
879
+ break;
880
+ } catch (error) {
881
+ if (this.interviewQuirks()) {
882
+ logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`, NS);
883
+ return;
884
+ }
885
+
886
+ // Most of the times the first node descriptor query fails and the seconds one succeeds.
887
+ logger.debug(`Interview - node descriptor request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS);
888
+ }
889
+ }
890
+ } else {
891
+ logger.debug(`Interview - skip node descriptor request for '${this.ieeeAddr}', already got it`, NS);
892
+ }
893
+
894
+ if (!hasNodeDescriptor()) {
895
+ throw new Error(`Interview failed because can not get node descriptor ('${this.ieeeAddr}')`);
896
+ }
897
+
898
+ if (this.manufacturerID === 4619 && this._type === "EndDevice") {
899
+ // Give Tuya end device some time to pair. Otherwise they leave immediately.
900
+ // https://github.com/Koenkk/zigbee2mqtt/issues/5814
901
+ logger.debug("Interview - Detected Tuya end device, waiting 10 seconds...", NS);
902
+ await wait(10000);
903
+ } else if (this.manufacturerID === 0 || this.manufacturerID === 4098) {
904
+ // Potentially a Tuya device, some sleep fast so make sure to read the modelId and manufacturerName quickly.
905
+ // In case the device responds, the endoint and modelID/manufacturerName are set
906
+ // in controller.onZclOrRawData()
907
+ // https://github.com/Koenkk/zigbee2mqtt/issues/7553
908
+ logger.debug("Interview - Detected potential Tuya end device, reading modelID and manufacturerName...", NS);
909
+ try {
910
+ const endpoint = Endpoint.create(this.databaseID, 1, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr);
911
+ const result = await endpoint.read("genBasic", ["modelId", "manufacturerName"], {sendPolicy: "immediate"});
912
+
913
+ this.updateGenBasic(result);
914
+ } catch (error) {
915
+ logger.debug(`Interview - Tuya read modelID and manufacturerName failed (${error})`, NS);
916
+ }
917
+ }
918
+
919
+ // e.g. Xiaomi Aqara Opple devices fail to respond to the first active endpoints request, therefore try 2 times
920
+ // https://github.com/Koenkk/zigbee-herdsman/pull/103
921
+ let gotActiveEndpoints = false;
922
+
923
+ for (let attempt = 0; attempt < 2; attempt++) {
924
+ try {
925
+ await this.updateActiveEndpoints();
926
+ gotActiveEndpoints = true;
927
+ break;
928
+ } catch (error) {
929
+ logger.debug(`Interview - active endpoints request failed for '${this.ieeeAddr}', attempt ${attempt + 1} (${error})`, NS);
930
+ }
931
+ }
932
+
933
+ if (!gotActiveEndpoints) {
934
+ throw new Error(`Interview failed because can not get active endpoints ('${this.ieeeAddr}')`);
935
+ }
936
+
937
+ logger.debug(`Interview - got active endpoints for device '${this.ieeeAddr}'`, NS);
938
+
939
+ const coordinator = Device.byType(this.databaseID, "Coordinator")[0];
940
+
941
+ for (const endpoint of this._endpoints) {
942
+ await endpoint.updateSimpleDescriptor();
943
+ logger.debug(`Interview - got simple descriptor for endpoint '${endpoint.ID}' device '${this.ieeeAddr}'`, NS);
944
+
945
+ // Read attributes
946
+ // nice to have but not required for successful pairing as most of the attributes are not mandatory in ZCL specification
947
+ if (endpoint.supportsInputCluster("genBasic")) {
948
+ for (const key of INTERVIEW_GENBASIC_ATTRIBUTES) {
949
+ if (ignoreCache || !this.#genBasic[key]) {
950
+ try {
951
+ let result: TPartialClusterAttributes<"genBasic">;
952
+
953
+ try {
954
+ result = await endpoint.read("genBasic", [key], {sendPolicy: "immediate"});
955
+ } catch (error) {
956
+ // Reading attributes can fail for many reason, e.g. it could be that device rejoins
957
+ // while joining like in:
958
+ // https://github.com/Koenkk/zigbee-herdsman-converters/issues/2485.
959
+ // The modelID and manufacturerName are crucial for device identification, so retry.
960
+ if (key === "modelId" || key === "manufacturerName") {
961
+ logger.debug(`Interview - first ${key} retrieval attempt failed, retrying after 10 seconds...`, NS);
962
+ await wait(10000);
963
+ result = await endpoint.read("genBasic", [key], {sendPolicy: "immediate"});
964
+ } else {
965
+ throw error;
966
+ }
967
+ }
968
+
969
+ this.updateGenBasic(result);
970
+ logger.debug(`Interview - got '${key}' for device '${this.ieeeAddr}'`, NS);
971
+ } catch (error) {
972
+ logger.debug(`Interview - failed to read attribute '${key}' from endpoint '${endpoint.ID}' (${error})`, NS);
973
+ }
974
+ }
975
+ }
976
+ }
977
+
978
+ // Enroll IAS device
979
+ if (endpoint.supportsInputCluster("ssIasZone")) {
980
+ logger.debug(`Interview - IAS - enrolling '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
981
+
982
+ const stateBefore = await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState"], {sendPolicy: "immediate"});
983
+ logger.debug(() => `Interview - IAS - before enrolling state: '${JSON.stringify(stateBefore)}'`, NS);
984
+
985
+ // Do not enroll when device has already been enrolled
986
+ if (stateBefore.zoneState !== 1 || stateBefore.iasCieAddr !== coordinator.ieeeAddr) {
987
+ logger.debug("Interview - IAS - not enrolled, enrolling", NS);
988
+
989
+ await endpoint.write("ssIasZone", {iasCieAddr: coordinator.ieeeAddr}, {disableDefaultResponse: true, sendPolicy: "immediate"});
990
+ logger.debug("Interview - IAS - wrote iasCieAddr", NS);
991
+
992
+ // There are 2 enrollment procedures:
993
+ // - Auto enroll: coordinator has to send enrollResponse without receiving an enroll request
994
+ // this case is handled below.
995
+ // - Manual enroll: coordinator replies to enroll request with an enroll response.
996
+ // this case in hanled in onZclData().
997
+ // https://github.com/Koenkk/zigbee2mqtt/issues/4569#issuecomment-706075676
998
+ await wait(500);
999
+ logger.debug(`IAS - '${this.ieeeAddr}' sending enroll response (auto enroll)`, NS);
1000
+ const payload = {enrollrspcode: 0, zoneid: 23};
1001
+ await endpoint.command("ssIasZone", "enrollRsp", payload, {disableDefaultResponse: true, sendPolicy: "immediate"});
1002
+
1003
+ let enrolled = false;
1004
+ for (let attempt = 0; attempt < 20; attempt++) {
1005
+ await wait(500);
1006
+ const stateAfter = await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState"], {sendPolicy: "immediate"});
1007
+ logger.debug(() => `Interview - IAS - after enrolling state (${attempt}): '${JSON.stringify(stateAfter)}'`, NS);
1008
+ if (stateAfter.zoneState === 1) {
1009
+ enrolled = true;
1010
+ break;
1011
+ }
1012
+ }
1013
+
1014
+ if (enrolled) {
1015
+ logger.debug(`Interview - IAS successfully enrolled '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
1016
+ } else {
1017
+ throw new Error(`Interview failed because of failed IAS enroll (zoneState didn't change ('${this.ieeeAddr}')`);
1018
+ }
1019
+ } else {
1020
+ logger.debug("Interview - IAS - already enrolled, skipping enroll", NS);
1021
+ }
1022
+ }
1023
+ }
1024
+
1025
+ // Bind poll control
1026
+ try {
1027
+ for (const endpoint of this.endpoints.filter((e): boolean => e.supportsInputCluster("genPollCtrl"))) {
1028
+ logger.debug(`Interview - Poll control - binding '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
1029
+ await endpoint.bind("genPollCtrl", coordinator.endpoints[0]);
1030
+ const pollPeriod = await endpoint.read("genPollCtrl", ["checkinInterval"], {sendPolicy: "immediate"});
1031
+ this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds
1032
+ this.resetPendingRequestTimeout();
1033
+ }
1034
+ /* v8 ignore start */
1035
+ } catch (error) {
1036
+ logger.debug(`Interview - failed to bind genPollCtrl (${error})`, NS);
1037
+ }
1038
+ /* v8 ignore stop */
1039
+ }
1040
+
1041
+ public async updateNodeDescriptor(): Promise<void> {
1042
+ const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
1043
+ const adapter = Entity.getAdapterByID(this.databaseID);
1044
+ if (!adapter) {
1045
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1046
+ }
1047
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.networkAddress);
1048
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1049
+
1050
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.NODE_DESCRIPTOR_RESPONSE>(response)) {
1051
+ throw new Zdo.StatusError(response[0]);
1052
+ }
1053
+
1054
+ // TODO: make use of: capabilities.rxOnWhenIdle, maxIncTxSize, maxOutTxSize, serverMask.stackComplianceRevision
1055
+ const nodeDescriptor = response[1];
1056
+ this._manufacturerID = nodeDescriptor.manufacturerCode;
1057
+
1058
+ switch (nodeDescriptor.logicalType) {
1059
+ case 0x0:
1060
+ this._type = "Coordinator";
1061
+ break;
1062
+ case 0x1:
1063
+ this._type = "Router";
1064
+ break;
1065
+ case 0x2:
1066
+ this._type = "EndDevice";
1067
+ break;
1068
+ }
1069
+
1070
+ logger.debug(`Interview - got node descriptor for device '${this.ieeeAddr}'`, NS);
1071
+
1072
+ // TODO: define a property on Device for this value (would be good to have it displayed)
1073
+ // log for devices older than 1 from current revision
1074
+ if (nodeDescriptor.serverMask.stackComplianceRevision < ZSpec.ZIGBEE_REVISION - 1) {
1075
+ // always 0 before revision 21 where field was added
1076
+ const rev = nodeDescriptor.serverMask.stackComplianceRevision < 21 ? "pre-21" : nodeDescriptor.serverMask.stackComplianceRevision;
1077
+
1078
+ logger.info(
1079
+ `Device '${this.ieeeAddr}' is only compliant to revision '${rev}' of the Zigbee specification (current revision: ${ZSpec.ZIGBEE_REVISION}).`,
1080
+ NS,
1081
+ );
1082
+ }
1083
+ }
1084
+
1085
+ public async updateActiveEndpoints(): Promise<void> {
1086
+ const adapter = Entity.getAdapterByID(this.databaseID);
1087
+ if (!adapter) {
1088
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1089
+ }
1090
+ const clusterId = Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST;
1091
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.networkAddress);
1092
+
1093
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1094
+
1095
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.ACTIVE_ENDPOINTS_RESPONSE>(response)) {
1096
+ throw new Zdo.StatusError(response[0]);
1097
+ }
1098
+
1099
+ const activeEndpoints = response[1];
1100
+
1101
+ // Make sure that the endpoint are sorted.
1102
+ activeEndpoints.endpointList.sort((a, b) => a - b);
1103
+ for (const endpoint of activeEndpoints.endpointList) {
1104
+ // Some devices, e.g. TERNCY return endpoint 0 in the active endpoints request.
1105
+ // This is not a valid endpoint number according to the ZCL, requesting a simple descriptor will result
1106
+ // into an error. Therefore we filter it, more info: https://github.com/Koenkk/zigbee-herdsman/issues/82
1107
+ if (endpoint !== 0 && !this.getEndpoint(endpoint)) {
1108
+ this._endpoints.push(Endpoint.create(this.databaseID, endpoint, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr));
1109
+ }
1110
+ }
1111
+
1112
+ // Remove disappeared endpoints (can happen with e.g. custom devices).
1113
+ this._endpoints = this._endpoints.filter((e) => activeEndpoints.endpointList.includes(e.ID));
1114
+ }
1115
+
1116
+ /**
1117
+ * Request device to advertise its network address.
1118
+ * Note: This does not actually update the device property (if needed), as this is already done with `zdoResponse` event in Controller.
1119
+ */
1120
+ public async requestNetworkAddress(): Promise<void> {
1121
+ const clusterId = Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
1122
+ const adapter = Entity.getAdapterByID(this.databaseID);
1123
+ if (!adapter) {
1124
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1125
+ }
1126
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.ieeeAddr as Eui64, false, 0);
1127
+
1128
+ await adapter.sendZdo(this.ieeeAddr, ZSpec.BroadcastAddress.RX_ON_WHEN_IDLE, clusterId, zdoPayload, true);
1129
+ }
1130
+
1131
+ public async removeFromNetwork(): Promise<void> {
1132
+ const adapter = Entity.getAdapterByID(this.databaseID);
1133
+ if (!adapter) {
1134
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1135
+ }
1136
+ if (this._type === "GreenPower") {
1137
+ const payload = {
1138
+ options: 0x002550,
1139
+ srcID: Number(this.ieeeAddr),
1140
+ };
1141
+ const frame = Zcl.Frame.create(
1142
+ Zcl.FrameType.SPECIFIC,
1143
+ Zcl.Direction.SERVER_TO_CLIENT,
1144
+ true,
1145
+ undefined,
1146
+ zclTransactionSequenceNumber.next(),
1147
+ "pairing",
1148
+ 33,
1149
+ payload,
1150
+ this.customClusters,
1151
+ );
1152
+
1153
+ await adapter.sendZclFrameToAll(242, frame, 242, BroadcastAddress.RX_ON_WHEN_IDLE);
1154
+ } else {
1155
+ const clusterId = Zdo.ClusterId.LEAVE_REQUEST;
1156
+ const zdoPayload = Zdo.Buffalo.buildRequest(
1157
+ adapter.hasZdoMessageOverhead,
1158
+ clusterId,
1159
+ this.ieeeAddr as Eui64,
1160
+ Zdo.LeaveRequestFlags.WITHOUT_REJOIN,
1161
+ );
1162
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1163
+
1164
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.LEAVE_RESPONSE>(response)) {
1165
+ throw new Zdo.StatusError(response[0]);
1166
+ }
1167
+ }
1168
+
1169
+ this.removeFromDatabase();
1170
+ }
1171
+
1172
+ public removeFromDatabase(): void {
1173
+ Device.loadFromDatabaseIfNecessary();
1174
+
1175
+ for (const endpoint of this.endpoints) {
1176
+ endpoint.removeFromAllGroupsDatabase();
1177
+ }
1178
+ const database = Entity.getDatabaseByID(this.databaseID);
1179
+ if (database?.has(this.ID)) {
1180
+ database.remove(this.ID);
1181
+ }
1182
+
1183
+ Device.deletedDevices.get(this.databaseID)?.set(this.ieeeAddr, this);
1184
+ Device.devices.get(this.databaseID)?.delete(this.ieeeAddr);
1185
+
1186
+ // Clear all data in case device joins again
1187
+ // Green power devices are never interviewed, keep existing interview state.
1188
+ this._interviewState = this.type === "GreenPower" ? this._interviewState : InterviewState.Pending;
1189
+ this.meta = {};
1190
+ const newEndpoints: Endpoint[] = [];
1191
+ for (const endpoint of this.endpoints) {
1192
+ newEndpoints.push(
1193
+ Endpoint.create(
1194
+ this.databaseID,
1195
+ endpoint.ID,
1196
+ endpoint.profileID,
1197
+ endpoint.deviceID,
1198
+ endpoint.inputClusters,
1199
+ endpoint.outputClusters,
1200
+ this.networkAddress,
1201
+ this.ieeeAddr,
1202
+ ),
1203
+ );
1204
+ }
1205
+ this._endpoints = newEndpoints;
1206
+ }
1207
+
1208
+ public async lqi(): Promise<LQITableEntry[]> {
1209
+ const adapter = Entity.getAdapterByID(this.databaseID);
1210
+ if (!adapter) {
1211
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1212
+ }
1213
+ const clusterId = Zdo.ClusterId.LQI_TABLE_REQUEST;
1214
+ const table: LQITableEntry[] = [];
1215
+ const request = async (startIndex: number): Promise<[tableEntries: number, entryCount: number]> => {
1216
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
1217
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1218
+
1219
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.LQI_TABLE_RESPONSE>(response)) {
1220
+ throw new Zdo.StatusError(response[0]);
1221
+ }
1222
+
1223
+ const result = response[1];
1224
+
1225
+ table.push(...result.entryList);
1226
+
1227
+ return [result.neighborTableEntries, result.entryList.length];
1228
+ };
1229
+
1230
+ let [tableEntries, entryCount] = await request(0);
1231
+
1232
+ const size = tableEntries;
1233
+ let nextStartIndex = entryCount;
1234
+
1235
+ while (table.length < size) {
1236
+ [tableEntries, entryCount] = await request(nextStartIndex);
1237
+
1238
+ nextStartIndex += entryCount;
1239
+ }
1240
+
1241
+ return table;
1242
+ }
1243
+
1244
+ public async routingTable(): Promise<RoutingTableEntry[]> {
1245
+ const adapter = Entity.getAdapterByID(this.databaseID);
1246
+ if (!adapter) {
1247
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1248
+ }
1249
+ const clusterId = Zdo.ClusterId.ROUTING_TABLE_REQUEST;
1250
+ const table: RoutingTableEntry[] = [];
1251
+ const request = async (startIndex: number): Promise<[tableEntries: number, entryCount: number]> => {
1252
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
1253
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1254
+
1255
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.ROUTING_TABLE_RESPONSE>(response)) {
1256
+ throw new Zdo.StatusError(response[0]);
1257
+ }
1258
+
1259
+ const result = response[1];
1260
+
1261
+ table.push(...result.entryList);
1262
+
1263
+ return [result.routingTableEntries, result.entryList.length];
1264
+ };
1265
+
1266
+ let [tableEntries, entryCount] = await request(0);
1267
+
1268
+ const size = tableEntries;
1269
+ let nextStartIndex = entryCount;
1270
+
1271
+ while (table.length < size) {
1272
+ [tableEntries, entryCount] = await request(nextStartIndex);
1273
+
1274
+ nextStartIndex += entryCount;
1275
+ }
1276
+
1277
+ return table;
1278
+ }
1279
+
1280
+ public async bindingTable(): Promise<BindingTableEntry[]> {
1281
+ const adapter = Entity.getAdapterByID(this.databaseID);
1282
+ if (!adapter) {
1283
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1284
+ }
1285
+ const clusterId = Zdo.ClusterId.BINDING_TABLE_REQUEST;
1286
+ const table: BindingTableEntry[] = [];
1287
+ const request = async (startIndex: number): Promise<[tableEntries: number, entryCount: number]> => {
1288
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
1289
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1290
+
1291
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.BINDING_TABLE_RESPONSE>(response)) {
1292
+ throw new Zdo.StatusError(response[0]);
1293
+ }
1294
+
1295
+ const result = response[1];
1296
+
1297
+ table.push(...result.entryList);
1298
+
1299
+ return [result.bindingTableEntries, result.entryList.length];
1300
+ };
1301
+
1302
+ let [tableEntries, entryCount] = await request(0);
1303
+
1304
+ const size = tableEntries;
1305
+ let nextStartIndex = entryCount;
1306
+
1307
+ while (table.length < size) {
1308
+ [tableEntries, entryCount] = await request(nextStartIndex);
1309
+ nextStartIndex += entryCount;
1310
+ }
1311
+
1312
+ for (const ep of this._endpoints) {
1313
+ const newBinds: BindInternal[] = [];
1314
+
1315
+ for (const entry of table) {
1316
+ if (entry.sourceEui64 !== this.ieeeAddr || entry.sourceEndpoint !== ep.ID) {
1317
+ continue;
1318
+ }
1319
+
1320
+ if (entry.destAddrMode === 0x01) {
1321
+ newBinds.push({type: "group", cluster: entry.clusterId, groupID: entry.dest as number});
1322
+ } else {
1323
+ newBinds.push({
1324
+ type: "endpoint",
1325
+ cluster: entry.clusterId,
1326
+ deviceIeeeAddress: entry.dest as Eui64,
1327
+ endpointID: entry.destEndpoint as number,
1328
+ });
1329
+ }
1330
+ }
1331
+
1332
+ ep.saveBindings(newBinds);
1333
+ }
1334
+
1335
+ return table;
1336
+ }
1337
+
1338
+ /**
1339
+ * Clear all the bindings of a device.
1340
+ * Support of this command is optional (only mandatory if device has a binding table).
1341
+ * @param eui64List list of bind entries to match and clear. Send `["0xffffffffffffffff"]` to clear all.
1342
+ */
1343
+ public async clearAllBindings(eui64List: Eui64[]): Promise<void> {
1344
+ const adapter = Entity.getAdapterByID(this.databaseID);
1345
+ if (!adapter) {
1346
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1347
+ }
1348
+ const clusterId = Zdo.ClusterId.CLEAR_ALL_BINDINGS_REQUEST;
1349
+ const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, {eui64List});
1350
+ const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
1351
+
1352
+ if (!Zdo.Buffalo.checkStatus<Zdo.ClusterId.CLEAR_ALL_BINDINGS_RESPONSE>(response)) {
1353
+ throw new Zdo.StatusError(response[0]);
1354
+ }
1355
+
1356
+ if (
1357
+ (eui64List.length === 1 && eui64List[0].toLowerCase() === ZSpec.BLANK_EUI64) ||
1358
+ eui64List.some((eui64) => eui64.toLowerCase() === this.ieeeAddr)
1359
+ ) {
1360
+ for (const ep of this._endpoints) {
1361
+ ep.clearBindings();
1362
+ }
1363
+ }
1364
+ }
1365
+
1366
+ public async ping(disableRecovery = true): Promise<void> {
1367
+ // Zigbee does not have an official pinging mechanism. Use a read request
1368
+ // of a mandatory basic cluster attribute to keep it as lightweight as
1369
+ // possible.
1370
+ const endpoint = this.endpoints.find((ep) => ep.inputClusters.includes(0)) ?? this.endpoints[0];
1371
+ await endpoint.read("genBasic", ["zclVersion"], {disableRecovery, sendPolicy: "immediate"});
1372
+ }
1373
+
1374
+ public addCustomCluster(name: string, cluster: ClusterDefinition): void {
1375
+ assert(
1376
+ ![Zcl.Clusters.touchlink.ID, Zcl.Clusters.greenPower.ID].includes(cluster.ID),
1377
+ "Overriding of greenPower or touchlink cluster is not supported",
1378
+ );
1379
+ if (Zcl.Utils.isClusterName(name)) {
1380
+ const existingCluster = this._customClusters[name] ?? Zcl.Clusters[name];
1381
+
1382
+ // Extend existing cluster
1383
+ assert(existingCluster.ID === cluster.ID, `Custom cluster ID (${cluster.ID}) should match existing cluster ID (${existingCluster.ID})`);
1384
+ cluster = {
1385
+ ID: cluster.ID,
1386
+ manufacturerCode: cluster.manufacturerCode,
1387
+ attributes: {...existingCluster.attributes, ...cluster.attributes},
1388
+ commands: {...existingCluster.commands, ...cluster.commands},
1389
+ commandsResponse: {...existingCluster.commandsResponse, ...cluster.commandsResponse},
1390
+ };
1391
+ }
1392
+ this._customClusters[name] = cluster;
1393
+ }
1394
+
1395
+ #waitForOtaCommand<Co extends string>(
1396
+ endpointId: number,
1397
+ commandId: number,
1398
+ transactionSequenceNumber: number | undefined,
1399
+ timeout: number,
1400
+ ): {promise: Promise<TZclFrame<"genOta", Co>>; cancel: () => void} {
1401
+ const adapter = Entity.getAdapterByID(this.databaseID);
1402
+ if (!adapter) {
1403
+ throw new Error(`No adapter found for database ID ${this.databaseID}`);
1404
+ }
1405
+ const waiter = adapter.waitFor(
1406
+ this.networkAddress,
1407
+ endpointId,
1408
+ Zcl.FrameType.SPECIFIC,
1409
+ Zcl.Direction.CLIENT_TO_SERVER,
1410
+ transactionSequenceNumber,
1411
+ Zcl.Clusters.genOta.ID,
1412
+ commandId,
1413
+ timeout,
1414
+ );
1415
+ const promise = new Promise<Zcl.Frame & {payload: TClusterPayload<"genOta", Co>}>((resolve, reject) => {
1416
+ waiter.promise.then(
1417
+ (payload) => {
1418
+ try {
1419
+ const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, this.customClusters);
1420
+
1421
+ resolve(frame);
1422
+ } catch (error) {
1423
+ reject(error);
1424
+ }
1425
+ },
1426
+ (error) => reject(error),
1427
+ );
1428
+ });
1429
+
1430
+ return {promise, cancel: waiter.cancel};
1431
+ }
1432
+
1433
+ async findMatchingOtaImage(
1434
+ source: OtaSource,
1435
+ current: TClusterCommandPayload<"genOta", "queryNextImageRequest">,
1436
+ extraMetas: OtaExtraMetas,
1437
+ ): Promise<ZigbeeOtaImageMeta | undefined> {
1438
+ logger.debug(() => `Getting image metadata for ${this.ieeeAddr}...`, NS);
1439
+
1440
+ const images = await getOtaIndex(source);
1441
+ // NOTE: Officially an image can be determined with a combination of manufacturerCode and imageType.
1442
+ // However several manufacturers do not follow the spec properly.
1443
+ // The index provides the needed extra metadata to prevent mismatches.
1444
+ // e.g. Tuya must match on manufacturerName, Gledopto on modelId...
1445
+ return images.find(
1446
+ (i) =>
1447
+ i.imageType === current.imageType &&
1448
+ i.manufacturerCode === current.manufacturerCode &&
1449
+ (i.minFileVersion === undefined || current.fileVersion >= i.minFileVersion) &&
1450
+ (i.maxFileVersion === undefined || current.fileVersion <= i.maxFileVersion) &&
1451
+ // let extra metas override the match from this.modelID, same for manufacturerName
1452
+ (!i.modelId || i.modelId === this.modelID || i.modelId === extraMetas.modelId) &&
1453
+ (!i.manufacturerName ||
1454
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
1455
+ i.manufacturerName.includes(this.manufacturerName!) ||
1456
+ // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
1457
+ i.manufacturerName.includes(extraMetas.manufacturerName!)) &&
1458
+ (!extraMetas.otaHeaderString || i.otaHeaderString === extraMetas.otaHeaderString) &&
1459
+ (i.hardwareVersionMin === undefined ||
1460
+ (current.hardwareVersion !== undefined && current.hardwareVersion >= i.hardwareVersionMin) ||
1461
+ (extraMetas.hardwareVersionMin !== undefined && extraMetas.hardwareVersionMin >= i.hardwareVersionMin)) &&
1462
+ (i.hardwareVersionMax === undefined ||
1463
+ (current.hardwareVersion !== undefined && current.hardwareVersion <= i.hardwareVersionMax) ||
1464
+ (extraMetas.hardwareVersionMax !== undefined && extraMetas.hardwareVersionMax <= i.hardwareVersionMax)),
1465
+ );
1466
+ }
1467
+
1468
+ async #notifyOta(endpoint: Endpoint): Promise<[payload: TClusterCommandPayload<"genOta", "queryNextImageRequest">, tsn: number]> {
1469
+ // Some devices (e.g. Insta) take a very long trying to discover the correct coordinator EP for OTA
1470
+ const queryNextImageRequest = this.#waitForOtaCommand<"queryNextImageRequest">(
1471
+ endpoint.ID,
1472
+ Zcl.Clusters.genOta.commands.queryNextImageRequest.ID,
1473
+ undefined,
1474
+ 60000,
1475
+ );
1476
+
1477
+ try {
1478
+ await endpoint.commandResponse("genOta", "imageNotify", {payloadType: 0, queryJitter: 100}, {sendPolicy: "immediate"});
1479
+
1480
+ const response = await queryNextImageRequest.promise;
1481
+
1482
+ return [response.payload, response.header.transactionSequenceNumber];
1483
+ } catch {
1484
+ queryNextImageRequest.cancel();
1485
+
1486
+ throw new Error(`Device didn't respond to OTA request`);
1487
+ }
1488
+ }
1489
+
1490
+ /**
1491
+ * If `current` is undefined, will automatically notify and reply to query with `NO_IMAGE_AVAILABLE` (stops device from doing further requests).
1492
+ */
1493
+ async checkOta(
1494
+ source: OtaSource,
1495
+ current: TClusterCommandPayload<"genOta", "queryNextImageRequest"> | undefined,
1496
+ extraMetas: OtaExtraMetas,
1497
+ endpoint = this.endpoints.find((e) => e.supportsOutputCluster("genOta")),
1498
+ ): Promise<OtaUpdateAvailableResult> {
1499
+ assert(endpoint !== undefined, `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
1500
+
1501
+ if (this.modelID === "PP-WHT-US") {
1502
+ // see https://github.com/Koenkk/zigbee-OTA/pull/14
1503
+ const scenesEndpoint = this.endpoints.find((e) => e.supportsOutputCluster("genScenes"));
1504
+
1505
+ if (scenesEndpoint !== undefined) {
1506
+ await scenesEndpoint.write("genScenes", {currentGroup: 49502}, {disableDefaultResponse: true, sendPolicy: "immediate"});
1507
+ }
1508
+ }
1509
+
1510
+ if (current === undefined) {
1511
+ let queryTsn: number;
1512
+ [current, queryTsn] = await this.#notifyOta(endpoint);
1513
+
1514
+ await endpoint.commandResponse("genOta", "queryNextImageResponse", {status: Zcl.Status.NO_IMAGE_AVAILABLE}, undefined, queryTsn);
1515
+ }
1516
+
1517
+ logger.debug(
1518
+ () =>
1519
+ `Checking OTA ${this.ieeeAddr} ${source.downgrade ? "downgrade" : "upgrade"} image availability, current=${JSON.stringify(current)}`,
1520
+ NS,
1521
+ );
1522
+
1523
+ if (
1524
+ this.meta.lumiFileVersion &&
1525
+ (this.modelID === "lumi.airrtc.agl001" || this.modelID === "lumi.curtain.acn003" || this.modelID === "lumi.curtain.agl001")
1526
+ ) {
1527
+ // The current.fileVersion which comes from the device is wrong.
1528
+ // Use the `lumiFileVersion` which comes from the manuSpecificLumi.attributeReport instead.
1529
+ // https://github.com/Koenkk/zigbee2mqtt/issues/16345#issuecomment-1454835056
1530
+ // https://github.com/Koenkk/zigbee2mqtt/issues/16345 doesn't seem to be needed for all
1531
+ // https://github.com/Koenkk/zigbee2mqtt/issues/15745
1532
+ current = {...current, fileVersion: this.meta.lumiFileVersion};
1533
+ }
1534
+
1535
+ const meta = await this.findMatchingOtaImage(source, current, extraMetas);
1536
+
1537
+ if (!meta) {
1538
+ // no image in repo/URL for specified device
1539
+ return {
1540
+ available: false,
1541
+ current,
1542
+ };
1543
+ }
1544
+
1545
+ logger.debug(
1546
+ () => `OTA ${source.downgrade ? "downgrade" : "upgrade"} image availability for ${this.ieeeAddr}, available=${JSON.stringify(meta)}`,
1547
+ NS,
1548
+ );
1549
+
1550
+ return {
1551
+ available: meta.force ? true : source.downgrade ? current.fileVersion > meta.fileVersion : current.fileVersion < meta.fileVersion,
1552
+ current,
1553
+ availableMeta: meta,
1554
+ };
1555
+ }
1556
+
1557
+ async updateOta(
1558
+ source: Readonly<OtaSource> | undefined,
1559
+ requestPayload: TClusterCommandPayload<"genOta", "queryNextImageRequest"> | undefined,
1560
+ requestTsn: number | undefined,
1561
+ extraMetas: Readonly<OtaExtraMetas>,
1562
+ onProgress: (progress: number, remaining: number) => void,
1563
+ dataSettings: OtaDataSettings,
1564
+ endpoint = this.endpoints.find((e) => e.supportsOutputCluster("genOta")),
1565
+ ): Promise<[from: OtaUpdateAvailableResult["current"], to: OtaUpdateAvailableResult["current"] | undefined]> {
1566
+ assert(this.#otaInProgress === false, `OTA already in progress for ${this.ieeeAddr}`);
1567
+ assert(endpoint !== undefined, `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
1568
+
1569
+ if (source === undefined) {
1570
+ assert(this.#scheduledOta !== undefined, `No currently scheduled OTA for ${this.ieeeAddr}`);
1571
+
1572
+ source = this.#scheduledOta;
1573
+ }
1574
+
1575
+ this.#otaInProgress = true;
1576
+
1577
+ // always expected both undefined if one is, but just in case
1578
+ if (requestPayload === undefined || requestTsn === undefined) {
1579
+ try {
1580
+ [requestPayload, requestTsn] = await this.#notifyOta(endpoint);
1581
+ } finally {
1582
+ this.#otaInProgress = false;
1583
+ }
1584
+ }
1585
+
1586
+ let available: OtaUpdateAvailableResult["available"] = false;
1587
+ let image: OtaImage | undefined;
1588
+
1589
+ if (source.url && !source.url.endsWith(".json")) {
1590
+ // firmware file at `source.url`
1591
+ try {
1592
+ const downloadedFile = await getOtaFirmware(source.url, undefined);
1593
+ image = parseOtaImage(downloadedFile);
1594
+ available = source.downgrade
1595
+ ? requestPayload.fileVersion > image.header.fileVersion
1596
+ : requestPayload.fileVersion < image.header.fileVersion;
1597
+
1598
+ logger.debug(
1599
+ () =>
1600
+ // biome-ignore lint/style/noNonNullAssertion: valid from above, won't change after assignment
1601
+ `Parsed image from '${source.url}' for ${this.ieeeAddr}, header=${JSON.stringify(image!.header)}`,
1602
+ NS,
1603
+ );
1604
+ } catch (error) {
1605
+ logger.error(`Failed to parse OTA image from '${source.url}' for ${this.ieeeAddr}, aborting (${(error as Error).message})`, NS);
1606
+ // biome-ignore lint/style/noNonNullAssertion: expected valid
1607
+ logger.debug((error as Error).stack!, NS);
1608
+ }
1609
+ } else {
1610
+ let availableMeta: OtaUpdateAvailableResult["availableMeta"];
1611
+
1612
+ try {
1613
+ // index file at `source.url` (or undefined to use defaults)
1614
+ ({available, availableMeta} = await this.checkOta(source, requestPayload, extraMetas, endpoint));
1615
+ } finally {
1616
+ this.#otaInProgress = false;
1617
+ }
1618
+
1619
+ if (available && availableMeta) {
1620
+ try {
1621
+ const downloadedFile = await getOtaFirmware(availableMeta.url, availableMeta.sha512);
1622
+ image = parseOtaImage(downloadedFile);
1623
+
1624
+ logger.debug(
1625
+ () =>
1626
+ // biome-ignore lint/style/noNonNullAssertion: valid from above, won't change after assignment
1627
+ `Parsed image from '${availableMeta.url}' for ${this.ieeeAddr}, header=${JSON.stringify(image!.header)}`,
1628
+ NS,
1629
+ );
1630
+ } catch (error) {
1631
+ logger.error(`Failed to parse OTA image for ${this.ieeeAddr}, aborting (${(error as Error).message})`, NS);
1632
+ // biome-ignore lint/style/noNonNullAssertion: expected valid
1633
+ logger.debug((error as Error).stack!, NS);
1634
+ }
1635
+ } else {
1636
+ logger.info(() => `No OTA ${source.downgrade ? "downgrade" : "upgrade"} image currently available for ${this.ieeeAddr}`, NS);
1637
+ }
1638
+ }
1639
+
1640
+ // reply to `queryNextImageRequest` now that we have the data for it, should trigger image block/page request from device
1641
+ // NOTE: previous code had try/catch wrapping with ignored error, but that doesn't look good (would fail to start OTA from device side)
1642
+ try {
1643
+ await endpoint.commandResponse(
1644
+ "genOta",
1645
+ "queryNextImageResponse",
1646
+ image && available
1647
+ ? {
1648
+ status: Zcl.Status.SUCCESS,
1649
+ manufacturerCode: image.header.manufacturerCode,
1650
+ imageType: image.header.imageType,
1651
+ fileVersion: image.header.fileVersion,
1652
+ imageSize: image.header.totalImageSize,
1653
+ }
1654
+ : {status: Zcl.Status.NO_IMAGE_AVAILABLE},
1655
+ undefined,
1656
+ requestTsn,
1657
+ );
1658
+ } finally {
1659
+ this.#otaInProgress = false;
1660
+ }
1661
+
1662
+ if (!image || !available) {
1663
+ this.#otaInProgress = false;
1664
+
1665
+ return [requestPayload, undefined];
1666
+ }
1667
+
1668
+ logger.debug(() => `Starting OTA update for ${this.ieeeAddr}`, NS);
1669
+
1670
+ const session = new OtaSession(this.ieeeAddr, endpoint, image, onProgress, dataSettings, this.#waitForOtaCommand.bind(this));
1671
+
1672
+ let endResult: TZclFrame<"genOta", "upgradeEndRequest">;
1673
+
1674
+ try {
1675
+ endResult = await session.run();
1676
+ } finally {
1677
+ this.#otaInProgress = false;
1678
+ }
1679
+
1680
+ logger.debug(() => `Received upgrade end request for ${this.ieeeAddr}: ${JSON.stringify(endResult.payload)}`, NS);
1681
+
1682
+ if (endResult.payload.status === Zcl.Status.SUCCESS) {
1683
+ try {
1684
+ const currentTime = timeService.timestampToZigbeeUtcTime(Date.now());
1685
+
1686
+ await endpoint.commandResponse(
1687
+ "genOta",
1688
+ "upgradeEndResponse",
1689
+ {
1690
+ manufacturerCode: image.header.manufacturerCode,
1691
+ imageType: image.header.imageType,
1692
+ fileVersion: image.header.fileVersion,
1693
+ currentTime,
1694
+ upgradeTime: currentTime + 1, // TODO: could this tiny offset be a problem for some stacks?
1695
+ },
1696
+ undefined,
1697
+ endResult.header.transactionSequenceNumber,
1698
+ );
1699
+
1700
+ onProgress(100, 0);
1701
+ logger.info(
1702
+ () =>
1703
+ `Update of ${this.ieeeAddr} successful (${Math.round((performance.now() - session.startTime) / 1000)} seconds). Waiting for device announce...`,
1704
+ NS,
1705
+ );
1706
+
1707
+ let timer: NodeJS.Timeout;
1708
+
1709
+ await new Promise<void>((resolve) => {
1710
+ const onDeviceAnnounce = () => {
1711
+ clearTimeout(timer);
1712
+ logger.debug(() => `Received device announce for ${this.ieeeAddr}, OTA update finished.`, NS);
1713
+ resolve();
1714
+ };
1715
+
1716
+ // force "finished" after given time
1717
+ timer = setTimeout(() => {
1718
+ this.removeListener("deviceAnnounce", onDeviceAnnounce);
1719
+ logger.debug(() => `Timed out waiting for device announce for ${this.ieeeAddr}, OTA update considered finished.`, NS);
1720
+ resolve();
1721
+ }, 120000 /** consider "done" after timeout even if no announce seen */);
1722
+
1723
+ this.once("deviceAnnounce", onDeviceAnnounce);
1724
+ });
1725
+
1726
+ // only "cancel" possible scheduled OTA when successful
1727
+ this.#scheduledOta = undefined;
1728
+ this.#otaInProgress = false;
1729
+
1730
+ return [
1731
+ requestPayload,
1732
+ {
1733
+ fieldControl: 0,
1734
+ manufacturerCode: image.header.manufacturerCode,
1735
+ imageType: image.header.imageType,
1736
+ fileVersion: image.header.fileVersion,
1737
+ },
1738
+ ];
1739
+ } catch (error) {
1740
+ this.#otaInProgress = false;
1741
+
1742
+ throw new Error(`OTA upgrade end response failed: ${(error as Error).message}`);
1743
+ }
1744
+ } else {
1745
+ /**
1746
+ * For other status value received such as INVALID_IMAGE, REQUIRE_MORE_IMAGE, or ABORT,
1747
+ * the upgrade server SHALL not send Upgrade End Response command but it SHALL send default
1748
+ * response command with status of success and it SHALL wait for the client to reinitiate the upgrade process.
1749
+ */
1750
+ try {
1751
+ await endpoint.defaultResponse(
1752
+ Zcl.Clusters.genOta.commands.upgradeEndRequest.ID,
1753
+ Zcl.Status.SUCCESS,
1754
+ Zcl.Clusters.genOta.ID,
1755
+ endResult.header.transactionSequenceNumber,
1756
+ );
1757
+ } catch (error) {
1758
+ logger.debug(() => `OTA upgrade end request default response for ${this.ieeeAddr} failed: ${(error as Error).message}`, NS);
1759
+ }
1760
+
1761
+ this.#otaInProgress = false;
1762
+
1763
+ throw new Error(`OTA update of ${this.ieeeAddr} failed with reason: ${Zcl.Status[endResult.payload.status]}`);
1764
+ }
1765
+ }
1766
+
1767
+ scheduleOta(source: OtaSource): void {
1768
+ assert(
1769
+ this.endpoints.some((e) => e.supportsOutputCluster("genOta")),
1770
+ `No endpoint found with OTA cluster support for ${this.ieeeAddr}`,
1771
+ );
1772
+
1773
+ if (this.#scheduledOta) {
1774
+ logger.info(`Previously scheduled OTA update for '${this.ieeeAddr}' was cancelled in favor of new schedule request`, NS);
1775
+ }
1776
+
1777
+ this.#scheduledOta = source;
1778
+
1779
+ logger.info(`Scheduled OTA update for '${this.ieeeAddr}' on next request from device`, NS);
1780
+ }
1781
+
1782
+ unscheduleOta(): void {
1783
+ if (this.#scheduledOta !== undefined) {
1784
+ this.#scheduledOta = undefined;
1785
+
1786
+ logger.info(`Previously scheduled OTA update for '${this.ieeeAddr}' was cancelled`, NS);
1787
+ }
1788
+ }
1789
+ }
1790
+
1791
+ export default Device;