zigbee-herdsman 0.50.1 → 0.52.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 (508) hide show
  1. package/.github/workflows/ci.yml +4 -2
  2. package/.prettierrc +9 -0
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +20 -0
  5. package/dist/adapter/adapter.d.ts +4 -4
  6. package/dist/adapter/adapter.d.ts.map +1 -1
  7. package/dist/adapter/adapter.js +8 -13
  8. package/dist/adapter/adapter.js.map +1 -1
  9. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +1 -1
  10. package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
  11. package/dist/adapter/deconz/adapter/deconzAdapter.js +249 -155
  12. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
  13. package/dist/adapter/deconz/adapter/index.d.ts +1 -1
  14. package/dist/adapter/deconz/adapter/index.d.ts.map +1 -1
  15. package/dist/adapter/deconz/adapter/index.js.map +1 -1
  16. package/dist/adapter/deconz/driver/constants.d.ts +1 -1
  17. package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
  18. package/dist/adapter/deconz/driver/constants.js +7 -7
  19. package/dist/adapter/deconz/driver/constants.js.map +1 -1
  20. package/dist/adapter/deconz/driver/driver.d.ts.map +1 -1
  21. package/dist/adapter/deconz/driver/driver.js +92 -60
  22. package/dist/adapter/deconz/driver/driver.js.map +1 -1
  23. package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -1
  24. package/dist/adapter/deconz/driver/frameParser.js +55 -46
  25. package/dist/adapter/deconz/driver/frameParser.js.map +1 -1
  26. package/dist/adapter/deconz/driver/parser.js +1 -1
  27. package/dist/adapter/ember/adapter/emberAdapter.d.ts +27 -445
  28. package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
  29. package/dist/adapter/ember/adapter/emberAdapter.js +888 -1681
  30. package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
  31. package/dist/adapter/ember/adapter/endpoints.d.ts.map +1 -1
  32. package/dist/adapter/ember/adapter/endpoints.js +4 -2
  33. package/dist/adapter/ember/adapter/endpoints.js.map +1 -1
  34. package/dist/adapter/ember/adapter/oneWaitress.d.ts +5 -4
  35. package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
  36. package/dist/adapter/ember/adapter/oneWaitress.js +44 -30
  37. package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
  38. package/dist/adapter/ember/adapter/tokensManager.d.ts +11 -10
  39. package/dist/adapter/ember/adapter/tokensManager.d.ts.map +1 -1
  40. package/dist/adapter/ember/adapter/tokensManager.js +118 -117
  41. package/dist/adapter/ember/adapter/tokensManager.js.map +1 -1
  42. package/dist/adapter/ember/consts.d.ts +1 -0
  43. package/dist/adapter/ember/consts.d.ts.map +1 -1
  44. package/dist/adapter/ember/consts.js +29 -27
  45. package/dist/adapter/ember/consts.js.map +1 -1
  46. package/dist/adapter/ember/enums.d.ts +130 -409
  47. package/dist/adapter/ember/enums.d.ts.map +1 -1
  48. package/dist/adapter/ember/enums.js +146 -484
  49. package/dist/adapter/ember/enums.js.map +1 -1
  50. package/dist/adapter/ember/ezsp/buffalo.d.ts +15 -4
  51. package/dist/adapter/ember/ezsp/buffalo.d.ts.map +1 -1
  52. package/dist/adapter/ember/ezsp/buffalo.js +148 -38
  53. package/dist/adapter/ember/ezsp/buffalo.js.map +1 -1
  54. package/dist/adapter/ember/ezsp/consts.d.ts +2 -1
  55. package/dist/adapter/ember/ezsp/consts.d.ts.map +1 -1
  56. package/dist/adapter/ember/ezsp/consts.js +6 -5
  57. package/dist/adapter/ember/ezsp/consts.js.map +1 -1
  58. package/dist/adapter/ember/ezsp/enums.d.ts +160 -49
  59. package/dist/adapter/ember/ezsp/enums.d.ts.map +1 -1
  60. package/dist/adapter/ember/ezsp/enums.js +177 -49
  61. package/dist/adapter/ember/ezsp/enums.js.map +1 -1
  62. package/dist/adapter/ember/ezsp/ezsp.d.ts +991 -729
  63. package/dist/adapter/ember/ezsp/ezsp.d.ts.map +1 -1
  64. package/dist/adapter/ember/ezsp/ezsp.js +3219 -2683
  65. package/dist/adapter/ember/ezsp/ezsp.js.map +1 -1
  66. package/dist/adapter/ember/ezspError.d.ts +6 -0
  67. package/dist/adapter/ember/ezspError.d.ts.map +1 -0
  68. package/dist/adapter/ember/ezspError.js +13 -0
  69. package/dist/adapter/ember/ezspError.js.map +1 -0
  70. package/dist/adapter/ember/types.d.ts +91 -43
  71. package/dist/adapter/ember/types.d.ts.map +1 -1
  72. package/dist/adapter/ember/uart/ash.d.ts +16 -12
  73. package/dist/adapter/ember/uart/ash.d.ts.map +1 -1
  74. package/dist/adapter/ember/uart/ash.js +81 -82
  75. package/dist/adapter/ember/uart/ash.js.map +1 -1
  76. package/dist/adapter/ember/uart/consts.d.ts.map +1 -1
  77. package/dist/adapter/ember/uart/consts.js +9 -9
  78. package/dist/adapter/ember/uart/consts.js.map +1 -1
  79. package/dist/adapter/ember/uart/enums.d.ts.map +1 -1
  80. package/dist/adapter/ember/uart/parser.d.ts +1 -1
  81. package/dist/adapter/ember/uart/parser.d.ts.map +1 -1
  82. package/dist/adapter/ember/uart/parser.js +1 -1
  83. package/dist/adapter/ember/uart/parser.js.map +1 -1
  84. package/dist/adapter/ember/uart/queues.d.ts.map +1 -1
  85. package/dist/adapter/ember/uart/queues.js +1 -1
  86. package/dist/adapter/ember/uart/queues.js.map +1 -1
  87. package/dist/adapter/ember/uart/writer.d.ts +1 -1
  88. package/dist/adapter/ember/uart/writer.d.ts.map +1 -1
  89. package/dist/adapter/ember/uart/writer.js +2 -3
  90. package/dist/adapter/ember/uart/writer.js.map +1 -1
  91. package/dist/adapter/ember/utils/initters.d.ts +2 -2
  92. package/dist/adapter/ember/utils/initters.d.ts.map +1 -1
  93. package/dist/adapter/ember/utils/initters.js +1 -0
  94. package/dist/adapter/ember/utils/initters.js.map +1 -1
  95. package/dist/adapter/ember/utils/math.d.ts +0 -8
  96. package/dist/adapter/ember/utils/math.d.ts.map +1 -1
  97. package/dist/adapter/ember/utils/math.js +12 -31
  98. package/dist/adapter/ember/utils/math.js.map +1 -1
  99. package/dist/adapter/events.d.ts +1 -1
  100. package/dist/adapter/events.d.ts.map +1 -1
  101. package/dist/adapter/ezsp/adapter/backup.d.ts +1 -1
  102. package/dist/adapter/ezsp/adapter/backup.d.ts.map +1 -1
  103. package/dist/adapter/ezsp/adapter/backup.js +11 -10
  104. package/dist/adapter/ezsp/adapter/backup.js.map +1 -1
  105. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +4 -4
  106. package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
  107. package/dist/adapter/ezsp/adapter/ezspAdapter.js +74 -41
  108. package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
  109. package/dist/adapter/ezsp/adapter/index.d.ts +1 -1
  110. package/dist/adapter/ezsp/adapter/index.d.ts.map +1 -1
  111. package/dist/adapter/ezsp/adapter/index.js.map +1 -1
  112. package/dist/adapter/ezsp/driver/commands.d.ts.map +1 -1
  113. package/dist/adapter/ezsp/driver/commands.js +452 -452
  114. package/dist/adapter/ezsp/driver/commands.js.map +1 -1
  115. package/dist/adapter/ezsp/driver/consts.js +4 -4
  116. package/dist/adapter/ezsp/driver/consts.js.map +1 -1
  117. package/dist/adapter/ezsp/driver/driver.d.ts +5 -5
  118. package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
  119. package/dist/adapter/ezsp/driver/driver.js +82 -82
  120. package/dist/adapter/ezsp/driver/driver.js.map +1 -1
  121. package/dist/adapter/ezsp/driver/ezsp.d.ts +3 -3
  122. package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -1
  123. package/dist/adapter/ezsp/driver/ezsp.js +58 -58
  124. package/dist/adapter/ezsp/driver/ezsp.js.map +1 -1
  125. package/dist/adapter/ezsp/driver/frame.js +9 -9
  126. package/dist/adapter/ezsp/driver/frame.js.map +1 -1
  127. package/dist/adapter/ezsp/driver/index.d.ts +1 -1
  128. package/dist/adapter/ezsp/driver/index.d.ts.map +1 -1
  129. package/dist/adapter/ezsp/driver/index.js +2 -2
  130. package/dist/adapter/ezsp/driver/index.js.map +1 -1
  131. package/dist/adapter/ezsp/driver/multicast.d.ts.map +1 -1
  132. package/dist/adapter/ezsp/driver/multicast.js +1 -1
  133. package/dist/adapter/ezsp/driver/multicast.js.map +1 -1
  134. package/dist/adapter/ezsp/driver/parser.d.ts.map +1 -1
  135. package/dist/adapter/ezsp/driver/parser.js +1 -1
  136. package/dist/adapter/ezsp/driver/parser.js.map +1 -1
  137. package/dist/adapter/ezsp/driver/types/basic.d.ts.map +1 -1
  138. package/dist/adapter/ezsp/driver/types/basic.js +5 -5
  139. package/dist/adapter/ezsp/driver/types/basic.js.map +1 -1
  140. package/dist/adapter/ezsp/driver/types/index.d.ts.map +1 -1
  141. package/dist/adapter/ezsp/driver/types/index.js.map +1 -1
  142. package/dist/adapter/ezsp/driver/types/named.d.ts.map +1 -1
  143. package/dist/adapter/ezsp/driver/types/named.js +236 -234
  144. package/dist/adapter/ezsp/driver/types/named.js.map +1 -1
  145. package/dist/adapter/ezsp/driver/types/struct.d.ts.map +1 -1
  146. package/dist/adapter/ezsp/driver/types/struct.js +5 -3
  147. package/dist/adapter/ezsp/driver/types/struct.js.map +1 -1
  148. package/dist/adapter/ezsp/driver/uart.d.ts.map +1 -1
  149. package/dist/adapter/ezsp/driver/uart.js +8 -8
  150. package/dist/adapter/ezsp/driver/uart.js.map +1 -1
  151. package/dist/adapter/ezsp/driver/utils/index.d.ts +1 -1
  152. package/dist/adapter/ezsp/driver/utils/index.d.ts.map +1 -1
  153. package/dist/adapter/ezsp/driver/utils/index.js +12 -11
  154. package/dist/adapter/ezsp/driver/utils/index.js.map +1 -1
  155. package/dist/adapter/ezsp/driver/writer.d.ts.map +1 -1
  156. package/dist/adapter/ezsp/driver/writer.js +6 -7
  157. package/dist/adapter/ezsp/driver/writer.js.map +1 -1
  158. package/dist/adapter/index.d.ts +2 -2
  159. package/dist/adapter/index.d.ts.map +1 -1
  160. package/dist/adapter/index.js +2 -2
  161. package/dist/adapter/index.js.map +1 -1
  162. package/dist/adapter/serialPort.d.ts +1 -1
  163. package/dist/adapter/serialPort.d.ts.map +1 -1
  164. package/dist/adapter/serialPort.js +1 -1
  165. package/dist/adapter/serialPort.js.map +1 -1
  166. package/dist/adapter/serialPortUtils.js +1 -1
  167. package/dist/adapter/serialPortUtils.js.map +1 -1
  168. package/dist/adapter/socketPortUtils.js +3 -3
  169. package/dist/adapter/tstype.d.ts +1 -1
  170. package/dist/adapter/tstype.d.ts.map +1 -1
  171. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts +3 -3
  172. package/dist/adapter/z-stack/adapter/adapter-backup.d.ts.map +1 -1
  173. package/dist/adapter/z-stack/adapter/adapter-backup.js +101 -86
  174. package/dist/adapter/z-stack/adapter/adapter-backup.js.map +1 -1
  175. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts +10 -10
  176. package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts.map +1 -1
  177. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +30 -24
  178. package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +1 -1
  179. package/dist/adapter/z-stack/adapter/endpoints.d.ts.map +1 -1
  180. package/dist/adapter/z-stack/adapter/endpoints.js +4 -4
  181. package/dist/adapter/z-stack/adapter/endpoints.js.map +1 -1
  182. package/dist/adapter/z-stack/adapter/index.d.ts +1 -1
  183. package/dist/adapter/z-stack/adapter/index.d.ts.map +1 -1
  184. package/dist/adapter/z-stack/adapter/index.js.map +1 -1
  185. package/dist/adapter/z-stack/adapter/manager.d.ts +5 -5
  186. package/dist/adapter/z-stack/adapter/manager.d.ts.map +1 -1
  187. package/dist/adapter/z-stack/adapter/manager.js +90 -81
  188. package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
  189. package/dist/adapter/z-stack/adapter/tstype.d.ts +1 -1
  190. package/dist/adapter/z-stack/adapter/tstype.d.ts.map +1 -1
  191. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +5 -5
  192. package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
  193. package/dist/adapter/z-stack/adapter/zStackAdapter.js +72 -57
  194. package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
  195. package/dist/adapter/z-stack/constants/af.js +5 -5
  196. package/dist/adapter/z-stack/constants/af.js.map +1 -1
  197. package/dist/adapter/z-stack/constants/dbg.js +2 -2
  198. package/dist/adapter/z-stack/constants/index.d.ts +2 -2
  199. package/dist/adapter/z-stack/constants/index.d.ts.map +1 -1
  200. package/dist/adapter/z-stack/constants/index.js +2 -2
  201. package/dist/adapter/z-stack/constants/index.js.map +1 -1
  202. package/dist/adapter/z-stack/constants/mac.js +11 -11
  203. package/dist/adapter/z-stack/constants/sapi.js +4 -4
  204. package/dist/adapter/z-stack/constants/sys.js +11 -11
  205. package/dist/adapter/z-stack/constants/util.js +11 -11
  206. package/dist/adapter/z-stack/constants/utils.d.ts.map +1 -1
  207. package/dist/adapter/z-stack/constants/utils.js +3 -3
  208. package/dist/adapter/z-stack/constants/utils.js.map +1 -1
  209. package/dist/adapter/z-stack/constants/zdo.js +13 -13
  210. package/dist/adapter/z-stack/models/index.d.ts +1 -1
  211. package/dist/adapter/z-stack/models/startup-options.d.ts +2 -2
  212. package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts +1 -1
  213. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js +4 -4
  214. package/dist/adapter/z-stack/structs/entries/address-manager-entry.js.map +1 -1
  215. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts +2 -2
  216. package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts.map +1 -1
  217. package/dist/adapter/z-stack/structs/entries/address-manager-table.js +4 -7
  218. package/dist/adapter/z-stack/structs/entries/address-manager-table.js.map +1 -1
  219. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts +1 -1
  220. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts.map +1 -1
  221. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js +1 -5
  222. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js.map +1 -1
  223. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts +2 -2
  224. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts.map +1 -1
  225. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js +3 -6
  226. package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js.map +1 -1
  227. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts +1 -1
  228. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js +6 -6
  229. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts +2 -2
  230. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts.map +1 -1
  231. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js +3 -6
  232. package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js.map +1 -1
  233. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts +1 -1
  234. package/dist/adapter/z-stack/structs/entries/channel-list.d.ts.map +1 -1
  235. package/dist/adapter/z-stack/structs/entries/channel-list.js +1 -3
  236. package/dist/adapter/z-stack/structs/entries/channel-list.js.map +1 -1
  237. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts +1 -1
  238. package/dist/adapter/z-stack/structs/entries/has-configured.d.ts.map +1 -1
  239. package/dist/adapter/z-stack/structs/entries/has-configured.js +2 -2
  240. package/dist/adapter/z-stack/structs/entries/has-configured.js.map +1 -1
  241. package/dist/adapter/z-stack/structs/entries/index.d.ts +16 -16
  242. package/dist/adapter/z-stack/structs/entries/nib.d.ts +1 -1
  243. package/dist/adapter/z-stack/structs/entries/nib.d.ts.map +1 -1
  244. package/dist/adapter/z-stack/structs/entries/nib.js +50 -50
  245. package/dist/adapter/z-stack/structs/entries/nib.js.map +1 -1
  246. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts +1 -1
  247. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts.map +1 -1
  248. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js +1 -4
  249. package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js.map +1 -1
  250. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts +1 -1
  251. package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts.map +1 -1
  252. package/dist/adapter/z-stack/structs/entries/nwk-key.js +1 -3
  253. package/dist/adapter/z-stack/structs/entries/nwk-key.js.map +1 -1
  254. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts +1 -1
  255. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts.map +1 -1
  256. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js +1 -3
  257. package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js.map +1 -1
  258. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts +1 -1
  259. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts.map +1 -1
  260. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js +3 -3
  261. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js.map +1 -1
  262. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts +2 -2
  263. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts.map +1 -1
  264. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js +3 -6
  265. package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js.map +1 -1
  266. package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts +1 -1
  267. package/dist/adapter/z-stack/structs/entries/security-manager-entry.js +4 -4
  268. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts +2 -2
  269. package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts.map +1 -1
  270. package/dist/adapter/z-stack/structs/entries/security-manager-table.js +3 -7
  271. package/dist/adapter/z-stack/structs/entries/security-manager-table.js.map +1 -1
  272. package/dist/adapter/z-stack/structs/index.d.ts +4 -4
  273. package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts +1 -1
  274. package/dist/adapter/z-stack/structs/struct.d.ts +6 -6
  275. package/dist/adapter/z-stack/structs/struct.d.ts.map +1 -1
  276. package/dist/adapter/z-stack/structs/struct.js +53 -52
  277. package/dist/adapter/z-stack/structs/struct.js.map +1 -1
  278. package/dist/adapter/z-stack/structs/table.d.ts +3 -3
  279. package/dist/adapter/z-stack/structs/table.d.ts.map +1 -1
  280. package/dist/adapter/z-stack/structs/table.js +16 -16
  281. package/dist/adapter/z-stack/structs/table.js.map +1 -1
  282. package/dist/adapter/z-stack/unpi/constants.d.ts +1 -1
  283. package/dist/adapter/z-stack/unpi/constants.d.ts.map +1 -1
  284. package/dist/adapter/z-stack/unpi/constants.js +1 -1
  285. package/dist/adapter/z-stack/unpi/constants.js.map +1 -1
  286. package/dist/adapter/z-stack/unpi/frame.d.ts.map +1 -1
  287. package/dist/adapter/z-stack/unpi/frame.js +5 -6
  288. package/dist/adapter/z-stack/unpi/frame.js.map +1 -1
  289. package/dist/adapter/z-stack/unpi/index.d.ts +4 -4
  290. package/dist/adapter/z-stack/unpi/index.d.ts.map +1 -1
  291. package/dist/adapter/z-stack/unpi/index.js +6 -6
  292. package/dist/adapter/z-stack/unpi/index.js.map +1 -1
  293. package/dist/adapter/z-stack/unpi/parser.d.ts.map +1 -1
  294. package/dist/adapter/z-stack/unpi/parser.js +1 -1
  295. package/dist/adapter/z-stack/unpi/parser.js.map +1 -1
  296. package/dist/adapter/z-stack/unpi/writer.d.ts.map +1 -1
  297. package/dist/adapter/z-stack/unpi/writer.js.map +1 -1
  298. package/dist/adapter/z-stack/utils/channel-list.d.ts.map +1 -1
  299. package/dist/adapter/z-stack/utils/channel-list.js +5 -2
  300. package/dist/adapter/z-stack/utils/channel-list.js.map +1 -1
  301. package/dist/adapter/z-stack/utils/index.d.ts +2 -2
  302. package/dist/adapter/z-stack/utils/network-options.d.ts +1 -1
  303. package/dist/adapter/z-stack/utils/network-options.d.ts.map +1 -1
  304. package/dist/adapter/z-stack/utils/network-options.js +1 -1
  305. package/dist/adapter/z-stack/utils/network-options.js.map +1 -1
  306. package/dist/adapter/z-stack/znp/buffaloZnp.d.ts.map +1 -1
  307. package/dist/adapter/z-stack/znp/buffaloZnp.js +8 -8
  308. package/dist/adapter/z-stack/znp/buffaloZnp.js.map +1 -1
  309. package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -1
  310. package/dist/adapter/z-stack/znp/definition.js +200 -592
  311. package/dist/adapter/z-stack/znp/definition.js.map +1 -1
  312. package/dist/adapter/z-stack/znp/index.d.ts +1 -1
  313. package/dist/adapter/z-stack/znp/index.d.ts.map +1 -1
  314. package/dist/adapter/z-stack/znp/index.js.map +1 -1
  315. package/dist/adapter/z-stack/znp/parameterType.d.ts.map +1 -1
  316. package/dist/adapter/z-stack/znp/parameterType.js.map +1 -1
  317. package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -1
  318. package/dist/adapter/z-stack/znp/znp.d.ts +3 -3
  319. package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -1
  320. package/dist/adapter/z-stack/znp/znp.js +12 -15
  321. package/dist/adapter/z-stack/znp/znp.js.map +1 -1
  322. package/dist/adapter/z-stack/znp/zpiObject.d.ts +1 -1
  323. package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -1
  324. package/dist/adapter/z-stack/znp/zpiObject.js +17 -9
  325. package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -1
  326. package/dist/adapter/zigate/adapter/index.d.ts.map +1 -1
  327. package/dist/adapter/zigate/adapter/index.js.map +1 -1
  328. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +1 -1
  329. package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
  330. package/dist/adapter/zigate/adapter/zigateAdapter.js +88 -92
  331. package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
  332. package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
  333. package/dist/adapter/zigate/driver/commandType.d.ts +2 -2
  334. package/dist/adapter/zigate/driver/commandType.d.ts.map +1 -1
  335. package/dist/adapter/zigate/driver/commandType.js +72 -80
  336. package/dist/adapter/zigate/driver/commandType.js.map +1 -1
  337. package/dist/adapter/zigate/driver/constants.d.ts +9 -9
  338. package/dist/adapter/zigate/driver/constants.d.ts.map +1 -1
  339. package/dist/adapter/zigate/driver/constants.js +11 -65
  340. package/dist/adapter/zigate/driver/constants.js.map +1 -1
  341. package/dist/adapter/zigate/driver/frame.d.ts.map +1 -1
  342. package/dist/adapter/zigate/driver/frame.js +3 -15
  343. package/dist/adapter/zigate/driver/frame.js.map +1 -1
  344. package/dist/adapter/zigate/driver/messageType.d.ts +1 -1
  345. package/dist/adapter/zigate/driver/messageType.d.ts.map +1 -1
  346. package/dist/adapter/zigate/driver/messageType.js +29 -30
  347. package/dist/adapter/zigate/driver/messageType.js.map +1 -1
  348. package/dist/adapter/zigate/driver/parameterType.d.ts.map +1 -1
  349. package/dist/adapter/zigate/driver/parameterType.js.map +1 -1
  350. package/dist/adapter/zigate/driver/ziGateObject.d.ts +2 -2
  351. package/dist/adapter/zigate/driver/ziGateObject.d.ts.map +1 -1
  352. package/dist/adapter/zigate/driver/ziGateObject.js +11 -5
  353. package/dist/adapter/zigate/driver/ziGateObject.js.map +1 -1
  354. package/dist/adapter/zigate/driver/zigate.d.ts +5 -5
  355. package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
  356. package/dist/adapter/zigate/driver/zigate.js +12 -12
  357. package/dist/adapter/zigate/driver/zigate.js.map +1 -1
  358. package/dist/buffalo/buffalo.d.ts +1 -1
  359. package/dist/buffalo/buffalo.d.ts.map +1 -1
  360. package/dist/buffalo/buffalo.js +1 -1
  361. package/dist/buffalo/buffalo.js.map +1 -1
  362. package/dist/controller/controller.d.ts.map +1 -1
  363. package/dist/controller/controller.js +34 -33
  364. package/dist/controller/controller.js.map +1 -1
  365. package/dist/controller/database.d.ts.map +1 -1
  366. package/dist/controller/database.js +6 -2
  367. package/dist/controller/database.js.map +1 -1
  368. package/dist/controller/events.d.ts +3 -3
  369. package/dist/controller/events.d.ts.map +1 -1
  370. package/dist/controller/greenPower.d.ts +1 -1
  371. package/dist/controller/greenPower.d.ts.map +1 -1
  372. package/dist/controller/greenPower.js +15 -17
  373. package/dist/controller/greenPower.js.map +1 -1
  374. package/dist/controller/helpers/index.d.ts +1 -1
  375. package/dist/controller/helpers/index.d.ts.map +1 -1
  376. package/dist/controller/helpers/index.js.map +1 -1
  377. package/dist/controller/helpers/request.d.ts +1 -1
  378. package/dist/controller/helpers/request.d.ts.map +1 -1
  379. package/dist/controller/helpers/request.js +7 -10
  380. package/dist/controller/helpers/request.js.map +1 -1
  381. package/dist/controller/helpers/requestQueue.d.ts.map +1 -1
  382. package/dist/controller/helpers/requestQueue.js +2 -3
  383. package/dist/controller/helpers/requestQueue.js.map +1 -1
  384. package/dist/controller/helpers/zclFrameConverter.d.ts +1 -1
  385. package/dist/controller/helpers/zclFrameConverter.d.ts.map +1 -1
  386. package/dist/controller/helpers/zclFrameConverter.js.map +1 -1
  387. package/dist/controller/index.d.ts +1 -1
  388. package/dist/controller/index.d.ts.map +1 -1
  389. package/dist/controller/index.js.map +1 -1
  390. package/dist/controller/model/device.d.ts +3 -3
  391. package/dist/controller/model/device.d.ts.map +1 -1
  392. package/dist/controller/model/device.js +247 -94
  393. package/dist/controller/model/device.js.map +1 -1
  394. package/dist/controller/model/endpoint.d.ts +4 -4
  395. package/dist/controller/model/endpoint.d.ts.map +1 -1
  396. package/dist/controller/model/endpoint.js +45 -31
  397. package/dist/controller/model/endpoint.js.map +1 -1
  398. package/dist/controller/model/entity.d.ts +2 -2
  399. package/dist/controller/model/entity.d.ts.map +1 -1
  400. package/dist/controller/model/entity.js.map +1 -1
  401. package/dist/controller/model/group.d.ts +2 -2
  402. package/dist/controller/model/group.d.ts.map +1 -1
  403. package/dist/controller/model/group.js +8 -6
  404. package/dist/controller/model/group.js.map +1 -1
  405. package/dist/controller/model/index.d.ts +1 -1
  406. package/dist/controller/model/index.d.ts.map +1 -1
  407. package/dist/controller/model/index.js.map +1 -1
  408. package/dist/controller/touchlink.d.ts.map +1 -1
  409. package/dist/controller/touchlink.js +2 -2
  410. package/dist/controller/touchlink.js.map +1 -1
  411. package/dist/controller/tstype.d.ts.map +1 -1
  412. package/dist/controller/tstype.js +0 -1
  413. package/dist/controller/tstype.js.map +1 -1
  414. package/dist/models/backup-storage-legacy.d.ts +4 -4
  415. package/dist/models/backup-storage-legacy.d.ts.map +1 -1
  416. package/dist/models/backup-storage-unified.d.ts +1 -1
  417. package/dist/models/backup.d.ts +2 -2
  418. package/dist/models/index.d.ts +4 -4
  419. package/dist/utils/backup.d.ts +1 -1
  420. package/dist/utils/backup.d.ts.map +1 -1
  421. package/dist/utils/backup.js +71 -58
  422. package/dist/utils/backup.js.map +1 -1
  423. package/dist/utils/index.d.ts +6 -6
  424. package/dist/utils/index.d.ts.map +1 -1
  425. package/dist/utils/index.js +10 -10
  426. package/dist/utils/index.js.map +1 -1
  427. package/dist/utils/isNumberArray.js +1 -1
  428. package/dist/utils/isNumberArray.js.map +1 -1
  429. package/dist/utils/queue.js +1 -1
  430. package/dist/utils/queue.js.map +1 -1
  431. package/dist/utils/waitress.d.ts.map +1 -1
  432. package/dist/utils/waitress.js +2 -2
  433. package/dist/utils/waitress.js.map +1 -1
  434. package/dist/zspec/consts.d.ts +1 -1
  435. package/dist/zspec/consts.d.ts.map +1 -1
  436. package/dist/zspec/consts.js +16 -16
  437. package/dist/zspec/consts.js.map +1 -1
  438. package/dist/zspec/enums.js +0 -1
  439. package/dist/zspec/enums.js.map +1 -1
  440. package/dist/zspec/utils.d.ts.map +1 -1
  441. package/dist/zspec/utils.js +5 -3
  442. package/dist/zspec/utils.js.map +1 -1
  443. package/dist/zspec/zcl/buffaloZcl.d.ts +2 -2
  444. package/dist/zspec/zcl/buffaloZcl.d.ts.map +1 -1
  445. package/dist/zspec/zcl/buffaloZcl.js +44 -51
  446. package/dist/zspec/zcl/buffaloZcl.js.map +1 -1
  447. package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
  448. package/dist/zspec/zcl/definition/cluster.js +283 -380
  449. package/dist/zspec/zcl/definition/cluster.js.map +1 -1
  450. package/dist/zspec/zcl/definition/consts.js +10 -10
  451. package/dist/zspec/zcl/definition/consts.js.map +1 -1
  452. package/dist/zspec/zcl/definition/enums.d.ts.map +1 -1
  453. package/dist/zspec/zcl/definition/enums.js.map +1 -1
  454. package/dist/zspec/zcl/definition/foundation.d.ts +1 -1
  455. package/dist/zspec/zcl/definition/foundation.d.ts.map +1 -1
  456. package/dist/zspec/zcl/definition/foundation.js +51 -22
  457. package/dist/zspec/zcl/definition/foundation.js.map +1 -1
  458. package/dist/zspec/zcl/definition/manufacturerCode.js +0 -1
  459. package/dist/zspec/zcl/definition/manufacturerCode.js.map +1 -1
  460. package/dist/zspec/zcl/definition/status.d.ts.map +1 -1
  461. package/dist/zspec/zcl/definition/tstype.d.ts +1 -1
  462. package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
  463. package/dist/zspec/zcl/definition/tstype.js +0 -1
  464. package/dist/zspec/zcl/definition/tstype.js.map +1 -1
  465. package/dist/zspec/zcl/utils.d.ts.map +1 -1
  466. package/dist/zspec/zcl/utils.js +59 -19
  467. package/dist/zspec/zcl/utils.js.map +1 -1
  468. package/dist/zspec/zcl/zclFrame.d.ts +1 -1
  469. package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
  470. package/dist/zspec/zcl/zclFrame.js +14 -15
  471. package/dist/zspec/zcl/zclFrame.js.map +1 -1
  472. package/dist/zspec/zcl/zclHeader.d.ts +1 -1
  473. package/dist/zspec/zcl/zclHeader.d.ts.map +1 -1
  474. package/dist/zspec/zcl/zclHeader.js +7 -7
  475. package/dist/zspec/zcl/zclHeader.js.map +1 -1
  476. package/dist/zspec/zcl/zclStatusError.d.ts.map +1 -1
  477. package/dist/zspec/zcl/zclStatusError.js.map +1 -1
  478. package/dist/zspec/zdo/buffaloZdo.d.ts +3 -3
  479. package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
  480. package/dist/zspec/zdo/buffaloZdo.js +92 -92
  481. package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
  482. package/dist/zspec/zdo/definition/clusters.d.ts.map +1 -1
  483. package/dist/zspec/zdo/definition/clusters.js +0 -1
  484. package/dist/zspec/zdo/definition/clusters.js.map +1 -1
  485. package/dist/zspec/zdo/definition/consts.d.ts.map +1 -1
  486. package/dist/zspec/zdo/definition/consts.js.map +1 -1
  487. package/dist/zspec/zdo/definition/enums.d.ts.map +1 -1
  488. package/dist/zspec/zdo/definition/enums.js +0 -5
  489. package/dist/zspec/zdo/definition/enums.js.map +1 -1
  490. package/dist/zspec/zdo/definition/status.d.ts.map +1 -1
  491. package/dist/zspec/zdo/definition/status.js +0 -1
  492. package/dist/zspec/zdo/definition/status.js.map +1 -1
  493. package/dist/zspec/zdo/definition/tstypes.d.ts +2 -2
  494. package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -1
  495. package/dist/zspec/zdo/utils.d.ts.map +1 -1
  496. package/dist/zspec/zdo/utils.js +14 -14
  497. package/dist/zspec/zdo/utils.js.map +1 -1
  498. package/dist/zspec/zdo/zdoStatusError.d.ts.map +1 -1
  499. package/dist/zspec/zdo/zdoStatusError.js.map +1 -1
  500. package/package.json +6 -1
  501. package/dist/adapter/ember/adapter/requestQueue.d.ts +0 -57
  502. package/dist/adapter/ember/adapter/requestQueue.d.ts.map +0 -1
  503. package/dist/adapter/ember/adapter/requestQueue.js +0 -139
  504. package/dist/adapter/ember/adapter/requestQueue.js.map +0 -1
  505. package/dist/adapter/ember/zdo.d.ts +0 -925
  506. package/dist/adapter/ember/zdo.d.ts.map +0 -1
  507. package/dist/adapter/ember/zdo.js +0 -723
  508. package/dist/adapter/ember/zdo.js.map +0 -1
@@ -28,32 +28,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.EmberAdapter = void 0;
30
30
  /* istanbul ignore file */
31
+ const crypto_1 = require("crypto");
31
32
  const es6_1 = __importDefault(require("fast-deep-equal/es6"));
32
33
  const fs_1 = require("fs");
33
34
  const path_1 = __importDefault(require("path"));
34
- const serialPortUtils_1 = __importDefault(require("../../serialPortUtils"));
35
- const socketPortUtils_1 = __importDefault(require("../../socketPortUtils"));
36
- const utils_1 = require("../../../utils");
37
35
  const __1 = require("../..");
36
+ const utils_1 = require("../../../utils");
37
+ const logger_1 = require("../../../utils/logger");
38
+ const ZSpec = __importStar(require("../../../zspec"));
38
39
  const Zcl = __importStar(require("../../../zspec/zcl"));
39
- const enums_1 = require("../../../zspec/enums");
40
- const ZSpec = __importStar(require("../../../zspec/consts"));
40
+ const Zdo = __importStar(require("../../../zspec/zdo"));
41
+ const buffaloZdo_1 = require("../../../zspec/zdo/buffaloZdo");
41
42
  const events_1 = require("../../events");
42
- const math_1 = require("../utils/math");
43
- const ezsp_1 = require("../ezsp/ezsp");
44
- const consts_1 = require("../ezsp/consts");
45
- const enums_2 = require("../ezsp/enums");
43
+ const serialPortUtils_1 = __importDefault(require("../../serialPortUtils"));
44
+ const socketPortUtils_1 = __importDefault(require("../../socketPortUtils"));
45
+ const consts_1 = require("../consts");
46
+ const enums_1 = require("../enums");
46
47
  const buffalo_1 = require("../ezsp/buffalo");
47
- const enums_3 = require("../enums");
48
- const zdo_1 = require("../zdo");
49
- const consts_2 = require("../consts");
50
- const requestQueue_1 = require("./requestQueue");
51
- const endpoints_1 = require("./endpoints");
48
+ const consts_2 = require("../ezsp/consts");
49
+ const enums_2 = require("../ezsp/enums");
50
+ const ezsp_1 = require("../ezsp/ezsp");
51
+ const ezspError_1 = require("../ezspError");
52
52
  const initters_1 = require("../utils/initters");
53
- const crypto_1 = require("crypto");
53
+ const math_1 = require("../utils/math");
54
+ const endpoints_1 = require("./endpoints");
54
55
  const oneWaitress_1 = require("./oneWaitress");
55
- const logger_1 = require("../../../utils/logger");
56
- // import {EmberTokensManager} from "./tokensManager";
57
56
  const NS = 'zh:ember';
58
57
  /** Enum to pass strings from numbers up to Z2M. */
59
58
  var RoutingTableStatus;
@@ -67,7 +66,6 @@ var RoutingTableStatus;
67
66
  RoutingTableStatus[RoutingTableStatus["RESERVED2"] = 6] = "RESERVED2";
68
67
  RoutingTableStatus[RoutingTableStatus["RESERVED3"] = 7] = "RESERVED3";
69
68
  })(RoutingTableStatus || (RoutingTableStatus = {}));
70
- ;
71
69
  var NetworkInitAction;
72
70
  (function (NetworkInitAction) {
73
71
  /** Ain't that nice! */
@@ -81,7 +79,6 @@ var NetworkInitAction;
81
79
  /** Re-form the network using full backed-up data. */
82
80
  NetworkInitAction[NetworkInitAction["FORM_BACKUP"] = 4] = "FORM_BACKUP";
83
81
  })(NetworkInitAction || (NetworkInitAction = {}));
84
- ;
85
82
  /** NOTE: Drivers can override `manufacturer`. Verify logic doesn't work in most cases anyway. */
86
83
  const autoDetectDefinitions = [
87
84
  /** NOTE: Manuf code "0x1321" for "Shenzhen Sonoff Technologies Co., Ltd." */
@@ -95,9 +92,9 @@ const autoDetectDefinitions = [
95
92
  * for coordination between the two entities, and allows both to send ZDO
96
93
  * messages with non-conflicting sequence numbers.
97
94
  */
98
- const APPLICATION_ZDO_SEQUENCE_MASK = 0x7F;
99
- /** Current revision of the spec by zigbee alliance. XXX: what are `Zigbee Pro 2023` devices reporting?? */
100
- const CURRENT_ZIGBEE_SPEC_REVISION = 23;
95
+ const APPLICATION_ZDO_SEQUENCE_MASK = 0x7f;
96
+ /** Current revision of the spec by zigbee alliance supported by Z2M. */
97
+ const CURRENT_ZIGBEE_SPEC_REVISION = 22;
101
98
  /** Each scan period is 15.36ms. Scan for at least 200ms (2^4 + 1 periods) to pick up WiFi beacon frames. */
102
99
  const ENERGY_SCAN_DURATION = 4;
103
100
  /** Oldest supported EZSP version for backups. Don't take the risk to restore a broken network until older backup versions can be investigated. */
@@ -107,6 +104,10 @@ const BACKUP_OLDEST_SUPPORTED_EZSP_VERSION = 12;
107
104
  * NOTE: This is blocking the request queue, so we shouldn't go crazy high.
108
105
  */
109
106
  const BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME = 15000;
107
+ const QUEUE_HIGH_COUNT = 4;
108
+ const QUEUE_MAX_SEND_ATTEMPTS = 3;
109
+ const QUEUE_BUSY_DEFER_MSEC = 500;
110
+ const QUEUE_NETWORK_DOWN_DEFER_MSEC = 1500;
110
111
  /**
111
112
  * Default stack configuration values.
112
113
  * @see https://www.silabs.com/documents/public/user-guides/ug100-ezsp-reference-guide.pdf 2.3.1 for descriptions/RAM costs
@@ -123,20 +124,12 @@ const DEFAULT_STACK_CONFIG = {
123
124
  CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD: 1, // zigpc: 1, ZigbeeMinimalHost: 3
124
125
  CONCENTRATOR_MAX_HOPS: 0, // zigpc: 0
125
126
  MAX_END_DEVICE_CHILDREN: 32, // zigpc: 6, nabucasa: 32, Dongle-E (Sonoff firmware): 32
126
- APS_UNICAST_MESSAGE_COUNT: 32, // zigpc: 10, darkxst: 20, nabucasa: 20
127
- RETRY_QUEUE_SIZE: 16, // nabucasa: 16
128
- ADDRESS_TABLE_SIZE: 16, // zigpc: 32, darkxst: 16, nabucasa: 16
129
- TRUST_CENTER_ADDRESS_CACHE_SIZE: 2,
130
- KEY_TABLE_SIZE: 0, // zigpc: 4
131
- BINDING_TABLE_SIZE: 32, // zigpc: 2, Z3GatewayGPCombo: 5, nabucasa: 32
132
- BROADCAST_TABLE_SIZE: 15, // zigpc: 15, Z3GatewayGPCombo: 35 - NOTE: Sonoff Dongle-E fails at 35
133
- MULTICAST_TABLE_SIZE: 16, // darkxst: 16, nabucasa: 16 - NOTE: should always be at least enough to register FIXED_ENDPOINTS multicastIds
134
- NEIGHBOR_TABLE_SIZE: 26, // zigpc: 16, darkxst: 26, nabucasa: 26
135
- SOURCE_ROUTE_TABLE_SIZE: 200, // Z3GatewayGPCombo: 100, darkxst: 200, nabucasa: 200
136
127
  TRANSIENT_DEVICE_TIMEOUT: 10000,
137
128
  END_DEVICE_POLL_TIMEOUT: 8, // zigpc: 8
138
129
  TRANSIENT_KEY_TIMEOUT_S: 300, // zigpc: 65535
139
130
  };
131
+ /** Default behavior is to disable app key requests */
132
+ const ALLOW_APP_KEY_REQUESTS = false;
140
133
  /**
141
134
  * NOTE: This from SDK is currently ignored here because of issues in below links:
142
135
  * - BUGZID 12261: Concentrators use MTORRs for route discovery and should not enable route discovery in the APS options.
@@ -145,13 +138,7 @@ const DEFAULT_STACK_CONFIG = {
145
138
  *
146
139
  * Removing `ENABLE_ROUTE_DISCOVERY` leads to devices that won't reconnect/go offline, and various other issues. Keeping it for now.
147
140
  */
148
- const DEFAULT_APS_OPTIONS = (enums_3.EmberApsOption.RETRY | enums_3.EmberApsOption.ENABLE_ROUTE_DISCOVERY | enums_3.EmberApsOption.ENABLE_ADDRESS_DISCOVERY);
149
- /**
150
- * Enabling this allows to immediately reject requests that won't be able to get to their destination.
151
- * However, it causes more NCP calls, notably to get the source route overhead.
152
- * XXX: Needs further testing before enabling
153
- */
154
- const CHECK_APS_PAYLOAD_LENGTH = false;
141
+ const DEFAULT_APS_OPTIONS = enums_1.EmberApsOption.RETRY | enums_1.EmberApsOption.ENABLE_ROUTE_DISCOVERY | enums_1.EmberApsOption.ENABLE_ADDRESS_DISCOVERY;
155
142
  /** Time for a ZDO request to get a callback response. ASH is 2400*6 for ACK timeout. */
156
143
  const DEFAULT_ZDO_REQUEST_TIMEOUT = 15000; // msec
157
144
  /** Time for a ZCL request to get a callback response. ASH is 2400*6 for ACK timeout. */
@@ -169,7 +156,7 @@ const DEFAULT_MANUFACTURER_CODE = Zcl.ManufacturerCode.SILICON_LABORATORIES;
169
156
  const WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE = {
170
157
  // NOTE: Lumi has a new prefix registered since 2021, in case they start using that one with new devices, it might need to be added here too...
171
158
  // "0x18c23c" https://maclookup.app/vendors/lumi-united-technology-co-ltd
172
- "0x54ef44": Zcl.ManufacturerCode.LUMI_UNITED_TECHOLOGY_LTD_SHENZHEN,
159
+ '0x54ef44': Zcl.ManufacturerCode.LUMI_UNITED_TECHOLOGY_LTD_SHENZHEN,
173
160
  };
174
161
  /**
175
162
  * Relay calls between Z2M and EZSP-layer and handle any error that might occur via queue & waitress.
@@ -182,12 +169,10 @@ class EmberAdapter extends __1.Adapter {
182
169
  stackConfig;
183
170
  ezsp;
184
171
  version;
185
- requestQueue;
172
+ queue;
186
173
  oneWaitress;
187
174
  /** Periodically retrieve counters then clear them. */
188
175
  watchdogCountersHandle;
189
- /** Hold ZDO request in process. */
190
- zdoRequestBuffalo;
191
176
  /** Sequence number used for ZDO requests. static uint8_t */
192
177
  zdoRequestSequence;
193
178
  /** Default radius used for broadcast ZDO requests. uint8_t */
@@ -202,20 +187,18 @@ class EmberAdapter extends __1.Adapter {
202
187
  constructor(networkOptions, serialPortOptions, backupPath, adapterOptions) {
203
188
  super(networkOptions, serialPortOptions, backupPath, adapterOptions);
204
189
  this.stackConfig = this.loadStackConfig();
205
- const delay = (typeof this.adapterOptions.delay === 'number') ? Math.min(Math.max(this.adapterOptions.delay, 5), 60) : 5;
190
+ const delay = typeof this.adapterOptions.delay === 'number' ? Math.min(Math.max(this.adapterOptions.delay, 5), 60) : 5;
206
191
  logger_1.logger.debug(`Using delay=${delay}.`, NS);
207
- this.requestQueue = new requestQueue_1.EmberRequestQueue(delay);
192
+ this.queue = new utils_1.Queue(typeof this.adapterOptions.concurrent === 'number' ? Math.min(Math.max(this.adapterOptions.concurrent, 1), 32) : 16);
208
193
  this.oneWaitress = new oneWaitress_1.EmberOneWaitress();
209
- this.zdoRequestBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_1.EZSP_MAX_FRAME_LENGTH));
210
- this.ezsp = new ezsp_1.Ezsp(delay, serialPortOptions);
211
- this.ezsp.on(ezsp_1.EzspEvents.STACK_STATUS, this.onStackStatus.bind(this));
212
- this.ezsp.on(ezsp_1.EzspEvents.MESSAGE_SENT, this.onMessageSent.bind(this));
194
+ this.ezsp = new ezsp_1.Ezsp(serialPortOptions);
213
195
  this.ezsp.on(ezsp_1.EzspEvents.ZDO_RESPONSE, this.onZDOResponse.bind(this));
214
- this.ezsp.on(ezsp_1.EzspEvents.END_DEVICE_ANNOUNCE, this.onEndDeviceAnnounce.bind(this));
215
196
  this.ezsp.on(ezsp_1.EzspEvents.INCOMING_MESSAGE, this.onIncomingMessage.bind(this));
216
197
  this.ezsp.on(ezsp_1.EzspEvents.TOUCHLINK_MESSAGE, this.onTouchlinkMessage.bind(this));
217
- this.ezsp.on(ezsp_1.EzspEvents.GREENPOWER_MESSAGE, this.onGreenpowerMessage.bind(this));
198
+ this.ezsp.on(ezsp_1.EzspEvents.STACK_STATUS, this.onStackStatus.bind(this));
218
199
  this.ezsp.on(ezsp_1.EzspEvents.TRUST_CENTER_JOIN, this.onTrustCenterJoin.bind(this));
200
+ this.ezsp.on(ezsp_1.EzspEvents.MESSAGE_SENT, this.onMessageSent.bind(this));
201
+ this.ezsp.on(ezsp_1.EzspEvents.GREENPOWER_MESSAGE, this.onGreenpowerMessage.bind(this));
219
202
  }
220
203
  loadStackConfig() {
221
204
  // store stack config in same dir as backup
@@ -224,16 +207,16 @@ class EmberAdapter extends __1.Adapter {
224
207
  const customConfig = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf8'));
225
208
  // set any undefined config to default
226
209
  const config = { ...DEFAULT_STACK_CONFIG, ...customConfig };
227
- const inRange = (value, min, max) => (value == undefined || value < min || value > max) ? false : true;
210
+ const inRange = (value, min, max) => (value == undefined || value < min || value > max ? false : true);
228
211
  if (!['high', 'low'].includes(config.CONCENTRATOR_RAM_TYPE)) {
229
212
  config.CONCENTRATOR_RAM_TYPE = DEFAULT_STACK_CONFIG.CONCENTRATOR_RAM_TYPE;
230
213
  logger_1.logger.error(`[STACK CONFIG] Invalid CONCENTRATOR_RAM_TYPE, using default.`, NS);
231
214
  }
232
- if (!inRange(config.CONCENTRATOR_MIN_TIME, 1, 60) || (config.CONCENTRATOR_MIN_TIME >= config.CONCENTRATOR_MAX_TIME)) {
215
+ if (!inRange(config.CONCENTRATOR_MIN_TIME, 1, 60) || config.CONCENTRATOR_MIN_TIME >= config.CONCENTRATOR_MAX_TIME) {
233
216
  config.CONCENTRATOR_MIN_TIME = DEFAULT_STACK_CONFIG.CONCENTRATOR_MIN_TIME;
234
217
  logger_1.logger.error(`[STACK CONFIG] Invalid CONCENTRATOR_MIN_TIME, using default.`, NS);
235
218
  }
236
- if (!inRange(config.CONCENTRATOR_MAX_TIME, 30, 300) || (config.CONCENTRATOR_MAX_TIME <= config.CONCENTRATOR_MIN_TIME)) {
219
+ if (!inRange(config.CONCENTRATOR_MAX_TIME, 30, 300) || config.CONCENTRATOR_MAX_TIME <= config.CONCENTRATOR_MIN_TIME) {
237
220
  config.CONCENTRATOR_MAX_TIME = DEFAULT_STACK_CONFIG.CONCENTRATOR_MAX_TIME;
238
221
  logger_1.logger.error(`[STACK CONFIG] Invalid CONCENTRATOR_MAX_TIME, using default.`, NS);
239
222
  }
@@ -253,47 +236,6 @@ class EmberAdapter extends __1.Adapter {
253
236
  config.MAX_END_DEVICE_CHILDREN = DEFAULT_STACK_CONFIG.MAX_END_DEVICE_CHILDREN;
254
237
  logger_1.logger.error(`[STACK CONFIG] Invalid MAX_END_DEVICE_CHILDREN, using default.`, NS);
255
238
  }
256
- if (!inRange(config.APS_UNICAST_MESSAGE_COUNT, 1, 255)) {
257
- config.APS_UNICAST_MESSAGE_COUNT = DEFAULT_STACK_CONFIG.APS_UNICAST_MESSAGE_COUNT;
258
- logger_1.logger.error(`[STACK CONFIG] Invalid APS_UNICAST_MESSAGE_COUNT, using default.`, NS);
259
- }
260
- if (!inRange(config.RETRY_QUEUE_SIZE, 0, 255)) {
261
- config.RETRY_QUEUE_SIZE = DEFAULT_STACK_CONFIG.RETRY_QUEUE_SIZE;
262
- logger_1.logger.error(`[STACK CONFIG] Invalid RETRY_QUEUE_SIZE, using default.`, NS);
263
- }
264
- if (!inRange(config.ADDRESS_TABLE_SIZE, 1, 250)) {
265
- config.ADDRESS_TABLE_SIZE = DEFAULT_STACK_CONFIG.ADDRESS_TABLE_SIZE;
266
- logger_1.logger.error(`[STACK CONFIG] Invalid ADDRESS_TABLE_SIZE, using default.`, NS);
267
- }
268
- if (!inRange(config.TRUST_CENTER_ADDRESS_CACHE_SIZE, 0, 4)) {
269
- config.TRUST_CENTER_ADDRESS_CACHE_SIZE = DEFAULT_STACK_CONFIG.TRUST_CENTER_ADDRESS_CACHE_SIZE;
270
- logger_1.logger.error(`[STACK CONFIG] Invalid TRUST_CENTER_ADDRESS_CACHE_SIZE, using default.`, NS);
271
- }
272
- if (!inRange(config.KEY_TABLE_SIZE, 0, 127)) {
273
- config.KEY_TABLE_SIZE = DEFAULT_STACK_CONFIG.KEY_TABLE_SIZE;
274
- logger_1.logger.error(`[STACK CONFIG] Invalid KEY_TABLE_SIZE, using default.`, NS);
275
- }
276
- if (!inRange(config.BINDING_TABLE_SIZE, 0, 127)) {
277
- config.BINDING_TABLE_SIZE = DEFAULT_STACK_CONFIG.BINDING_TABLE_SIZE;
278
- logger_1.logger.error(`[STACK CONFIG] Invalid BINDING_TABLE_SIZE, using default.`, NS);
279
- }
280
- if (!inRange(config.BROADCAST_TABLE_SIZE, 15, 254)) {
281
- config.BROADCAST_TABLE_SIZE = DEFAULT_STACK_CONFIG.BROADCAST_TABLE_SIZE;
282
- logger_1.logger.error(`[STACK CONFIG] Invalid BROADCAST_TABLE_SIZE, using default.`, NS);
283
- }
284
- // min should always be enough to cover `multicastIds` in `FIXED_ENDPOINTS`
285
- if (!inRange(config.MULTICAST_TABLE_SIZE, 5, 250)) {
286
- config.MULTICAST_TABLE_SIZE = DEFAULT_STACK_CONFIG.MULTICAST_TABLE_SIZE;
287
- logger_1.logger.error(`[STACK CONFIG] Invalid MULTICAST_TABLE_SIZE, using default.`, NS);
288
- }
289
- if (![16, 26].includes(config.NEIGHBOR_TABLE_SIZE)) {
290
- config.NEIGHBOR_TABLE_SIZE = DEFAULT_STACK_CONFIG.NEIGHBOR_TABLE_SIZE;
291
- logger_1.logger.error(`[STACK CONFIG] Invalid NEIGHBOR_TABLE_SIZE, using default.`, NS);
292
- }
293
- if (!inRange(config.SOURCE_ROUTE_TABLE_SIZE, 0, 254)) {
294
- config.SOURCE_ROUTE_TABLE_SIZE = DEFAULT_STACK_CONFIG.SOURCE_ROUTE_TABLE_SIZE;
295
- logger_1.logger.error(`[STACK CONFIG] Invalid SOURCE_ROUTE_TABLE_SIZE, using default.`, NS);
296
- }
297
239
  if (!inRange(config.TRANSIENT_DEVICE_TIMEOUT, 0, 65535)) {
298
240
  config.TRANSIENT_DEVICE_TIMEOUT = DEFAULT_STACK_CONFIG.TRANSIENT_DEVICE_TIMEOUT;
299
241
  logger_1.logger.error(`[STACK CONFIG] Invalid TRANSIENT_DEVICE_TIMEOUT, using default.`, NS);
@@ -321,35 +263,35 @@ class EmberAdapter extends __1.Adapter {
321
263
  // to be extra careful, should clear network cache upon receiving this.
322
264
  this.clearNetworkCache();
323
265
  switch (status) {
324
- case enums_3.EmberStatus.NETWORK_UP: {
266
+ case enums_1.SLStatus.NETWORK_UP: {
325
267
  this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP);
326
268
  logger_1.logger.info(`[STACK STATUS] Network up.`, NS);
327
269
  break;
328
270
  }
329
- case enums_3.EmberStatus.NETWORK_DOWN: {
271
+ case enums_1.SLStatus.NETWORK_DOWN: {
330
272
  this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN);
331
273
  logger_1.logger.info(`[STACK STATUS] Network down.`, NS);
332
274
  break;
333
275
  }
334
- case enums_3.EmberStatus.NETWORK_OPENED: {
276
+ case enums_1.SLStatus.ZIGBEE_NETWORK_OPENED: {
335
277
  this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_OPENED);
336
278
  logger_1.logger.info(`[STACK STATUS] Network opened.`, NS);
337
279
  break;
338
280
  }
339
- case enums_3.EmberStatus.NETWORK_CLOSED: {
281
+ case enums_1.SLStatus.ZIGBEE_NETWORK_CLOSED: {
340
282
  this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_CLOSED);
341
283
  logger_1.logger.info(`[STACK STATUS] Network closed.`, NS);
342
284
  break;
343
285
  }
344
- case enums_3.EmberStatus.CHANNEL_CHANGED: {
286
+ case enums_1.SLStatus.ZIGBEE_CHANNEL_CHANGED: {
345
287
  this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED);
346
288
  // invalidate cache
347
- this.networkCache.parameters.radioChannel = consts_2.INVALID_RADIO_CHANNEL;
289
+ this.networkCache.parameters.radioChannel = consts_1.INVALID_RADIO_CHANNEL;
348
290
  logger_1.logger.info(`[STACK STATUS] Channel changed.`, NS);
349
291
  break;
350
292
  }
351
293
  default: {
352
- logger_1.logger.debug(`[STACK STATUS] ${enums_3.EmberStatus[status]}.`, NS);
294
+ logger_1.logger.debug(`[STACK STATUS] ${enums_1.SLStatus[status]}.`, NS);
353
295
  break;
354
296
  }
355
297
  }
@@ -364,17 +306,17 @@ class EmberAdapter extends __1.Adapter {
364
306
  * @param messageTag
365
307
  * @param status
366
308
  */
367
- async onMessageSent(type, indexOrDestination, apsFrame, messageTag, status) {
368
- if (status === enums_3.EmberStatus.DELIVERY_FAILED) {
309
+ async onMessageSent(status, type, indexOrDestination, apsFrame, messageTag) {
310
+ if (status === enums_1.SLStatus.ZIGBEE_DELIVERY_FAILED) {
369
311
  // no ACK was received from the destination
370
312
  switch (type) {
371
- case enums_3.EmberOutgoingMessageType.BROADCAST:
372
- case enums_3.EmberOutgoingMessageType.BROADCAST_WITH_ALIAS:
373
- case enums_3.EmberOutgoingMessageType.MULTICAST:
374
- case enums_3.EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
313
+ case enums_1.EmberOutgoingMessageType.BROADCAST:
314
+ case enums_1.EmberOutgoingMessageType.BROADCAST_WITH_ALIAS:
315
+ case enums_1.EmberOutgoingMessageType.MULTICAST:
316
+ case enums_1.EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
375
317
  // BC/MC not checking for message sent, avoid unnecessary waitress lookups
376
- logger_1.logger.error(`Delivery of ${enums_3.EmberOutgoingMessageType[type]} failed for "${indexOrDestination}" `
377
- + `[apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
318
+ logger_1.logger.error(`Delivery of ${enums_1.EmberOutgoingMessageType[type]} failed for "${indexOrDestination}" ` +
319
+ `[apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
378
320
  break;
379
321
  }
380
322
  default: {
@@ -384,9 +326,11 @@ class EmberAdapter extends __1.Adapter {
384
326
  }
385
327
  }
386
328
  }
387
- else if (status === enums_3.EmberStatus.SUCCESS) {
388
- if (type === enums_3.EmberOutgoingMessageType.MULTICAST && apsFrame.destinationEndpoint === 0xFF &&
389
- apsFrame.groupId < consts_2.EMBER_MIN_BROADCAST_ADDRESS && !this.multicastTable.includes(apsFrame.groupId)) {
329
+ else if (status === enums_1.SLStatus.OK) {
330
+ if (type === enums_1.EmberOutgoingMessageType.MULTICAST &&
331
+ apsFrame.destinationEndpoint === 0xff &&
332
+ apsFrame.groupId < consts_1.EMBER_MIN_BROADCAST_ADDRESS &&
333
+ !this.multicastTable.includes(apsFrame.groupId)) {
390
334
  // workaround for devices using multicast for state update (coordinator passthrough)
391
335
  const tableIdx = this.multicastTable.length;
392
336
  const multicastEntry = {
@@ -396,22 +340,20 @@ class EmberAdapter extends __1.Adapter {
396
340
  };
397
341
  // set immediately to avoid potential race
398
342
  this.multicastTable.push(multicastEntry.multicastId);
399
- await new Promise((resolve, reject) => {
400
- this.requestQueue.enqueue(async () => {
401
- const status = (await this.ezsp.ezspSetMulticastTableEntry(tableIdx, multicastEntry));
402
- if (status !== enums_3.EmberStatus.SUCCESS) {
403
- logger_1.logger.error(`Failed to register group "${multicastEntry.multicastId}" in multicast table with status=${enums_3.EmberStatus[status]}.`, NS);
404
- return status;
343
+ try {
344
+ await this.queue.execute(async () => {
345
+ const status = await this.ezsp.ezspSetMulticastTableEntry(tableIdx, multicastEntry);
346
+ if (status !== enums_1.SLStatus.OK) {
347
+ throw new Error(`Failed to register group "${multicastEntry.multicastId}" in multicast table with status=${enums_1.SLStatus[status]}.`);
405
348
  }
406
349
  logger_1.logger.debug(`Registered multicast table entry (${tableIdx}): ${JSON.stringify(multicastEntry)}.`, NS);
407
- resolve();
408
- return enums_3.EmberStatus.SUCCESS;
409
- }, (reason) => {
410
- // remove to allow retry on next occurrence
411
- this.multicastTable.splice(tableIdx, 1);
412
- reject(reason);
413
- }, true);
414
- });
350
+ });
351
+ }
352
+ catch (error) {
353
+ // remove to allow retry on next occurrence
354
+ this.multicastTable.splice(tableIdx, 1);
355
+ throw error;
356
+ }
415
357
  }
416
358
  }
417
359
  // shouldn't be any other status
@@ -419,26 +361,31 @@ class EmberAdapter extends __1.Adapter {
419
361
  /**
420
362
  * Emitted from @see Ezsp.ezspIncomingMessageHandler
421
363
  *
422
- * @param clusterId The ZDO response cluster ID.
364
+ * @param apsFrame The APS frame associated with the response.
423
365
  * @param sender The sender of the response. Should match `payload.nodeId` in many responses.
424
- * @param payload If null, the response indicated a failure.
366
+ * @param messageContents The content of the response.
425
367
  */
426
- async onZDOResponse(status, sender, apsFrame, payload) {
427
- this.oneWaitress.resolveZDO(status, sender, apsFrame, payload);
428
- }
429
- /**
430
- * Emitted from @see Ezsp.ezspIncomingMessageHandler
431
- *
432
- * @param sender
433
- * @param nodeId
434
- * @param eui64
435
- * @param macCapFlags
436
- */
437
- async onEndDeviceAnnounce(sender, apsFrame, payload) {
438
- // reduced function device
439
- // if ((payload.capabilities.deviceType === 0)) {
440
- // }
441
- this.emit(events_1.Events.deviceAnnounce, { networkAddress: payload.nodeId, ieeeAddr: payload.eui64 });
368
+ async onZDOResponse(apsFrame, sender, messageContents) {
369
+ try {
370
+ const payload = buffaloZdo_1.BuffaloZdo.readResponse(apsFrame.clusterId, messageContents);
371
+ logger_1.logger.debug(`<~~~ [ZDO ${Zdo.ClusterId[apsFrame.clusterId]} from=${sender} ${payload ? JSON.stringify(payload) : 'OK'}]`, NS);
372
+ this.oneWaitress.resolveZDO(sender, apsFrame, payload);
373
+ if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
374
+ this.emit(events_1.Events.networkAddress, {
375
+ networkAddress: payload.nwkAddress,
376
+ ieeeAddr: payload.eui64,
377
+ });
378
+ }
379
+ else if (apsFrame.clusterId === Zdo.ClusterId.END_DEVICE_ANNOUNCE) {
380
+ this.emit(events_1.Events.deviceAnnounce, {
381
+ networkAddress: payload.nwkAddress,
382
+ ieeeAddr: payload.eui64,
383
+ });
384
+ }
385
+ }
386
+ catch (error) {
387
+ this.oneWaitress.resolveZDO(sender, apsFrame, error);
388
+ }
442
389
  }
443
390
  /**
444
391
  * Emitted from @see Ezsp.ezspIncomingMessageHandler
@@ -458,7 +405,7 @@ class EmberAdapter extends __1.Adapter {
458
405
  endpoint: apsFrame.sourceEndpoint,
459
406
  linkquality: lastHopLqi,
460
407
  groupID: apsFrame.groupId,
461
- wasBroadcast: ((type === enums_3.EmberIncomingMessageType.BROADCAST) || (type === enums_3.EmberIncomingMessageType.BROADCAST_LOOPBACK)),
408
+ wasBroadcast: type === enums_1.EmberIncomingMessageType.BROADCAST || type === enums_1.EmberIncomingMessageType.BROADCAST_LOOPBACK,
462
409
  destinationEndpoint: apsFrame.destinationEndpoint,
463
410
  };
464
411
  this.oneWaitress.resolveZCL(payload);
@@ -543,7 +490,7 @@ class EmberAdapter extends __1.Adapter {
543
490
  * @param parentOfNewNodeId
544
491
  */
545
492
  async onTrustCenterJoin(newNodeId, newNodeEui64, status, policyDecision, parentOfNewNodeId) {
546
- if (status === enums_3.EmberDeviceUpdate.DEVICE_LEFT) {
493
+ if (status === enums_1.EmberDeviceUpdate.DEVICE_LEFT) {
547
494
  const payload = {
548
495
  networkAddress: newNodeId,
549
496
  ieeeAddr: newNodeEui64,
@@ -551,7 +498,7 @@ class EmberAdapter extends __1.Adapter {
551
498
  this.emit(events_1.Events.deviceLeave, payload);
552
499
  }
553
500
  else {
554
- if (policyDecision !== enums_3.EmberJoinDecision.DENY_JOIN) {
501
+ if (policyDecision !== enums_1.EmberJoinDecision.DENY_JOIN) {
555
502
  const payload = {
556
503
  networkAddress: newNodeId,
557
504
  ieeeAddr: newNodeEui64,
@@ -559,15 +506,11 @@ class EmberAdapter extends __1.Adapter {
559
506
  // set workaround manuf code if necessary, or revert to default if previous joined device required workaround and new one does not
560
507
  const joinManufCode = WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE[newNodeEui64.substring(0, 8)] ?? DEFAULT_MANUFACTURER_CODE;
561
508
  if (this.manufacturerCode !== joinManufCode) {
562
- await new Promise((resolve, reject) => {
563
- this.requestQueue.enqueue(async () => {
564
- logger_1.logger.debug(`[WORKAROUND] Setting coordinator manufacturer code to ${Zcl.ManufacturerCode[joinManufCode]}.`, NS);
565
- await this.ezsp.ezspSetManufacturerCode(joinManufCode);
566
- this.manufacturerCode = joinManufCode;
567
- this.emit(events_1.Events.deviceJoined, payload);
568
- resolve();
569
- return enums_3.EmberStatus.SUCCESS;
570
- }, reject, true);
509
+ await this.queue.execute(async () => {
510
+ logger_1.logger.debug(`[WORKAROUND] Setting coordinator manufacturer code to ${Zcl.ManufacturerCode[joinManufCode]}.`, NS);
511
+ await this.ezsp.ezspSetManufacturerCode(joinManufCode);
512
+ this.manufacturerCode = joinManufCode;
513
+ this.emit(events_1.Events.deviceJoined, payload);
571
514
  });
572
515
  }
573
516
  else {
@@ -580,22 +523,18 @@ class EmberAdapter extends __1.Adapter {
580
523
  }
581
524
  }
582
525
  async watchdogCounters() {
583
- await new Promise((resolve, reject) => {
584
- this.requestQueue.enqueue(async () => {
585
- // listed as per EmberCounterType
586
- const ncpCounters = (await this.ezsp.ezspReadAndClearCounters());
587
- logger_1.logger.info(`[NCP COUNTERS] ${ncpCounters.join(',')}`, NS);
588
- const ashCounters = this.ezsp.ash.readAndClearCounters();
589
- logger_1.logger.info(`[ASH COUNTERS] ${ashCounters.join(',')}`, NS);
590
- resolve();
591
- return enums_3.EmberStatus.SUCCESS;
592
- }, reject);
526
+ await this.queue.execute(async () => {
527
+ // listed as per EmberCounterType
528
+ const ncpCounters = await this.ezsp.ezspReadAndClearCounters();
529
+ logger_1.logger.info(`[NCP COUNTERS] ${ncpCounters.join(',')}`, NS);
530
+ const ashCounters = this.ezsp.ash.readAndClearCounters();
531
+ logger_1.logger.info(`[ASH COUNTERS] ${ashCounters.join(',')}`, NS);
593
532
  });
594
533
  }
595
534
  initVariables() {
596
535
  this.ezsp.removeAllListeners(ezsp_1.EzspEvents.NCP_NEEDS_RESET_AND_INIT);
597
536
  clearInterval(this.watchdogCountersHandle);
598
- this.zdoRequestBuffalo.setPosition(0);
537
+ this.queue.clear();
599
538
  this.zdoRequestSequence = 0; // start at 1
600
539
  this.zdoRequestRadius = 255;
601
540
  this.interpanLock = false;
@@ -609,96 +548,49 @@ class EmberAdapter extends __1.Adapter {
609
548
  * This is called by start and on internal reset.
610
549
  */
611
550
  async initEzsp() {
612
- let result = "resumed";
551
+ let result = 'resumed';
613
552
  // NOTE: something deep in this call can throw too
614
- const startResult = (await this.ezsp.start());
615
- if (startResult !== enums_3.EzspStatus.SUCCESS) {
616
- throw new Error(`Failed to start EZSP layer with status=${enums_3.EzspStatus[startResult]}.`);
553
+ const startResult = await this.ezsp.start();
554
+ if (startResult !== enums_1.EzspStatus.SUCCESS) {
555
+ throw new Error(`Failed to start EZSP layer with status=${enums_1.EzspStatus[startResult]}.`);
617
556
  }
618
557
  // call before any other command, else fails
619
558
  await this.emberVersion();
620
- await this.initNCPPreConfiguration();
621
- await this.initNCPAddressTable();
622
- await this.initNCPConfiguration();
623
- // WARNING: From here on EZSP commands that affect memory allocation on the NCP should no longer be called (like resizing tables)
624
- await this.registerFixedEndpoints();
625
- this.clearNetworkCache();
626
- result = (await this.initTrustCenter());
627
- // after network UP, as per SDK, ensures clean slate
628
- await this.initNCPConcentrator();
629
- // await (this.emberStartEnergyScan());// TODO: via config of some kind, better off waiting for UI supports though
630
- // populate network cache info
631
- const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
632
- if (status !== enums_3.EmberStatus.SUCCESS) {
633
- throw new Error(`Failed to get network parameters with status=${enums_3.EmberStatus[status]}.`);
634
- }
635
- this.networkCache.parameters = parameters;
636
- this.networkCache.status = (await this.ezsp.ezspNetworkState());
637
- this.networkCache.eui64 = (await this.ezsp.ezspGetEui64());
638
- logger_1.logger.debug(`[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`, NS);
639
- this.watchdogCountersHandle = setInterval(this.watchdogCounters.bind(this), WATCHDOG_COUNTERS_FEED_INTERVAL);
640
- this.requestQueue.startDispatching();
641
- return result;
642
- }
643
- /**
644
- * NCP Config init. Should always be called first in the init stack (after version cmd).
645
- * @returns
646
- */
647
- async initNCPPreConfiguration() {
648
- // this can only decrease, not increase, NCP-side value
649
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.ADDRESS_TABLE_SIZE, this.stackConfig.ADDRESS_TABLE_SIZE);
650
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE, this.stackConfig.TRUST_CENTER_ADDRESS_CACHE_SIZE);
651
- // BUG 14222: If stack profile is 2 (ZigBee Pro), we need to enforce
652
- // the standard stack configuration values for that feature set.
653
- /** MAC indirect timeout should be 7.68 secs */
559
+ /** MAC indirect timeout should be 7.68 secs (STACK_PROFILE_ZIGBEE_PRO) */
654
560
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.INDIRECT_TRANSMISSION_TIMEOUT, 7680);
655
- /** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 */
561
+ /** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 (STACK_PROFILE_ZIGBEE_PRO) */
656
562
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_HOPS, 30);
657
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TX_POWER_MODE, enums_3.EmberTXPowerMode.USE_TOKEN);
658
563
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SUPPORTED_NETWORKS, 1);
659
- await this.emberSetEzspValue(enums_2.EzspValueId.END_DEVICE_KEEP_ALIVE_SUPPORT_MODE, 1, [enums_3.EmberKeepAliveMode.KEEP_ALIVE_SUPPORT_ALL]);
660
564
  // allow other devices to modify the binding table
661
565
  await this.emberSetEzspPolicy(enums_2.EzspPolicyId.BINDING_MODIFICATION_POLICY, enums_2.EzspDecisionId.CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS);
662
- // return message tag and message contents in ezspMessageSentHandler()
663
- await this.emberSetEzspPolicy(enums_2.EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, enums_2.EzspDecisionId.MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK);
664
- await this.emberSetEzspValue(enums_2.EzspValueId.MAXIMUM_INCOMING_TRANSFER_SIZE, 2, (0, math_1.lowHighBytes)(consts_2.MAXIMUM_APS_PAYLOAD_LENGTH));
665
- await this.emberSetEzspValue(enums_2.EzspValueId.MAXIMUM_OUTGOING_TRANSFER_SIZE, 2, (0, math_1.lowHighBytes)(consts_2.MAXIMUM_APS_PAYLOAD_LENGTH));
566
+ // return message tag only in ezspMessageSentHandler()
567
+ await this.emberSetEzspPolicy(enums_2.EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, enums_2.EzspDecisionId.MESSAGE_TAG_ONLY_IN_CALLBACK);
666
568
  await this.emberSetEzspValue(enums_2.EzspValueId.TRANSIENT_DEVICE_TIMEOUT, 2, (0, math_1.lowHighBytes)(this.stackConfig.TRANSIENT_DEVICE_TIMEOUT));
667
569
  await this.ezsp.ezspSetManufacturerCode(this.manufacturerCode);
668
570
  // network security init
669
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.STACK_PROFILE, consts_2.STACK_PROFILE_ZIGBEE_PRO);
670
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SECURITY_LEVEL, consts_2.SECURITY_LEVEL_Z3);
671
- }
672
- /**
673
- * NCP Address table init.
674
- * @returns
675
- */
676
- async initNCPAddressTable() {
677
- const desiredTableSize = this.stackConfig.ADDRESS_TABLE_SIZE;
678
- // If the host and the ncp disagree on the address table size, explode.
679
- const [status, addressTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.ADDRESS_TABLE_SIZE));
680
- // After the change of ncp memory model in UC, we can not increase the default NCP table sizes anymore.
681
- // Therefore, checking for desiredTableSize == (ncp)addressTableSize might not be always true anymore
682
- // assert(desiredTableSize <= addressTableSize);
683
- if ((status !== enums_3.EzspStatus.SUCCESS) || (addressTableSize > desiredTableSize)) {
684
- throw new Error(`[INIT] NCP (${addressTableSize}) disagrees with Host (min ${desiredTableSize}) on table size. status=${enums_3.EzspStatus[status]}`);
685
- }
686
- }
687
- /**
688
- * NCP configuration init
689
- */
690
- async initNCPConfiguration() {
691
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.BINDING_TABLE_SIZE, this.stackConfig.BINDING_TABLE_SIZE);
692
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.KEY_TABLE_SIZE, this.stackConfig.KEY_TABLE_SIZE);
571
+ await this.emberSetEzspConfigValue(enums_2.EzspConfigId.STACK_PROFILE, consts_1.STACK_PROFILE_ZIGBEE_PRO);
572
+ await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SECURITY_LEVEL, consts_1.SECURITY_LEVEL_Z3);
573
+ // common configs
693
574
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_END_DEVICE_CHILDREN, this.stackConfig.MAX_END_DEVICE_CHILDREN);
694
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.APS_UNICAST_MESSAGE_COUNT, this.stackConfig.APS_UNICAST_MESSAGE_COUNT);
695
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.BROADCAST_TABLE_SIZE, this.stackConfig.BROADCAST_TABLE_SIZE);
696
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.NEIGHBOR_TABLE_SIZE, this.stackConfig.NEIGHBOR_TABLE_SIZE);
697
575
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.END_DEVICE_POLL_TIMEOUT, this.stackConfig.END_DEVICE_POLL_TIMEOUT);
698
576
  await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRANSIENT_KEY_TIMEOUT_S, this.stackConfig.TRANSIENT_KEY_TIMEOUT_S);
699
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.RETRY_QUEUE_SIZE, this.stackConfig.RETRY_QUEUE_SIZE);
700
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SOURCE_ROUTE_TABLE_SIZE, this.stackConfig.SOURCE_ROUTE_TABLE_SIZE);
701
- await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MULTICAST_TABLE_SIZE, this.stackConfig.MULTICAST_TABLE_SIZE);
577
+ // WARNING: From here on EZSP commands that affect memory allocation on the NCP should no longer be called (like resizing tables)
578
+ await this.registerFixedEndpoints();
579
+ this.clearNetworkCache();
580
+ result = await this.initTrustCenter();
581
+ // after network UP, as per SDK, ensures clean slate
582
+ await this.initNCPConcentrator();
583
+ // populate network cache info
584
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
585
+ if (status !== enums_1.SLStatus.OK) {
586
+ throw new Error(`Failed to get network parameters with status=${enums_1.SLStatus[status]}.`);
587
+ }
588
+ this.networkCache.parameters = parameters;
589
+ this.networkCache.status = await this.ezsp.ezspNetworkState();
590
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
591
+ logger_1.logger.debug(`[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`, NS);
592
+ this.watchdogCountersHandle = setInterval(this.watchdogCounters.bind(this), WATCHDOG_COUNTERS_FEED_INTERVAL);
593
+ return result;
702
594
  }
703
595
  /**
704
596
  * NCP concentrator init. Also enables source route discovery mode with RESCHEDULE.
@@ -715,11 +607,11 @@ class EmberAdapter extends __1.Adapter {
715
607
  * (through a target node that is neither the trust center nor one of its neighboring routers.)
716
608
  */
717
609
  async initNCPConcentrator() {
718
- const status = (await this.ezsp.ezspSetConcentrator(true, (this.stackConfig.CONCENTRATOR_RAM_TYPE === 'low') ? consts_2.EMBER_LOW_RAM_CONCENTRATOR : consts_2.EMBER_HIGH_RAM_CONCENTRATOR, this.stackConfig.CONCENTRATOR_MIN_TIME, this.stackConfig.CONCENTRATOR_MAX_TIME, this.stackConfig.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, this.stackConfig.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, this.stackConfig.CONCENTRATOR_MAX_HOPS));
719
- if (status !== enums_3.EmberStatus.SUCCESS) {
720
- throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${status}.`);
610
+ const status = await this.ezsp.ezspSetConcentrator(true, this.stackConfig.CONCENTRATOR_RAM_TYPE === 'low' ? consts_1.EMBER_LOW_RAM_CONCENTRATOR : consts_1.EMBER_HIGH_RAM_CONCENTRATOR, this.stackConfig.CONCENTRATOR_MIN_TIME, this.stackConfig.CONCENTRATOR_MAX_TIME, this.stackConfig.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, this.stackConfig.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, this.stackConfig.CONCENTRATOR_MAX_HOPS);
611
+ if (status !== enums_1.SLStatus.OK) {
612
+ throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${enums_1.SLStatus[status]}.`);
721
613
  }
722
- const remainTilMTORR = (await this.ezsp.ezspSetSourceRouteDiscoveryMode(enums_3.EmberSourceRouteDiscoveryMode.RESCHEDULE));
614
+ const remainTilMTORR = await this.ezsp.ezspSetSourceRouteDiscoveryMode(enums_1.EmberSourceRouteDiscoveryMode.RESCHEDULE);
723
615
  logger_1.logger.info(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`, NS);
724
616
  }
725
617
  /**
@@ -731,18 +623,18 @@ class EmberAdapter extends __1.Adapter {
731
623
  logger_1.logger.debug(`Multi-network not currently supported. Skipping endpoint ${JSON.stringify(ep)}.`, NS);
732
624
  continue;
733
625
  }
734
- const [epStatus,] = (await this.ezsp.ezspGetEndpointFlags(ep.endpoint));
626
+ const [epStatus] = await this.ezsp.ezspGetEndpointFlags(ep.endpoint);
735
627
  // endpoint not already registered
736
- if (epStatus !== enums_3.EzspStatus.SUCCESS) {
628
+ if (epStatus !== enums_1.SLStatus.OK) {
737
629
  // check to see if ezspAddEndpoint needs to be called
738
630
  // if ezspInit is called without NCP reset, ezspAddEndpoint is not necessary and will return an error
739
- const status = (await this.ezsp.ezspAddEndpoint(ep.endpoint, ep.profileId, ep.deviceId, ep.deviceVersion, ep.inClusterList.slice(), // copy
740
- ep.outClusterList.slice()));
741
- if (status === enums_3.EzspStatus.SUCCESS) {
742
- logger_1.logger.debug(`Registered endpoint "${ep.endpoint}" with status=${enums_3.EzspStatus[status]}.`, NS);
631
+ const status = await this.ezsp.ezspAddEndpoint(ep.endpoint, ep.profileId, ep.deviceId, ep.deviceVersion, ep.inClusterList.slice(), // copy
632
+ ep.outClusterList.slice());
633
+ if (status === enums_1.SLStatus.OK) {
634
+ logger_1.logger.debug(`Registered endpoint '${ep.endpoint}'.`, NS);
743
635
  }
744
636
  else {
745
- throw new Error(`Failed to register endpoint "${ep.endpoint}" with status=${enums_3.EzspStatus[status]}.`);
637
+ throw new Error(`Failed to register endpoint "${ep.endpoint}" with status=${enums_1.SLStatus[status]}.`);
746
638
  }
747
639
  }
748
640
  else {
@@ -754,9 +646,9 @@ class EmberAdapter extends __1.Adapter {
754
646
  endpoint: ep.endpoint,
755
647
  networkIndex: ep.networkIndex,
756
648
  };
757
- const status = (await this.ezsp.ezspSetMulticastTableEntry(this.multicastTable.length, multicastEntry));
758
- if (status !== enums_3.EmberStatus.SUCCESS) {
759
- throw new Error(`Failed to register group "${multicastId}" in multicast table with status=${enums_3.EmberStatus[status]}.`);
649
+ const status = await this.ezsp.ezspSetMulticastTableEntry(this.multicastTable.length, multicastEntry);
650
+ if (status !== enums_1.SLStatus.OK) {
651
+ throw new Error(`Failed to register group "${multicastId}" in multicast table with status=${enums_1.SLStatus[status]}.`);
760
652
  }
761
653
  logger_1.logger.debug(`Registered multicast table entry (${this.multicastTable.length}): ${JSON.stringify(multicastEntry)}.`, NS);
762
654
  this.multicastTable.push(multicastEntry.multicastId);
@@ -770,49 +662,49 @@ class EmberAdapter extends __1.Adapter {
770
662
  async initTrustCenter() {
771
663
  // init TC policies
772
664
  {
773
- let status = (await this.emberSetEzspPolicy(enums_2.EzspPolicyId.TC_KEY_REQUEST_POLICY, enums_2.EzspDecisionId.ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY));
774
- if (status !== enums_3.EzspStatus.SUCCESS) {
775
- throw new Error(`[INIT TC] Failed to set EzspPolicyId TC_KEY_REQUEST_POLICY to ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY `
776
- + `with status=${enums_3.EzspStatus[status]}.`);
665
+ let status = await this.emberSetEzspPolicy(enums_2.EzspPolicyId.TC_KEY_REQUEST_POLICY, enums_2.EzspDecisionId.ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY);
666
+ if (status !== enums_1.SLStatus.OK) {
667
+ throw new Error(`[INIT TC] Failed to set EzspPolicyId TC_KEY_REQUEST_POLICY to ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY ` +
668
+ `with status=${enums_1.SLStatus[status]}.`);
777
669
  }
778
- const appKeyPolicy = this.stackConfig.KEY_TABLE_SIZE ? enums_2.EzspDecisionId.ALLOW_APP_KEY_REQUESTS : enums_2.EzspDecisionId.DENY_APP_KEY_REQUESTS;
779
- status = (await this.emberSetEzspPolicy(enums_2.EzspPolicyId.APP_KEY_REQUEST_POLICY, appKeyPolicy));
780
- if (status !== enums_3.EzspStatus.SUCCESS) {
781
- throw new Error(`[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${enums_2.EzspDecisionId[appKeyPolicy]} `
782
- + `with status=${enums_3.EzspStatus[status]}.`);
670
+ const appKeyRequestsPolicy = ALLOW_APP_KEY_REQUESTS ? enums_2.EzspDecisionId.ALLOW_APP_KEY_REQUESTS : enums_2.EzspDecisionId.DENY_APP_KEY_REQUESTS;
671
+ status = await this.emberSetEzspPolicy(enums_2.EzspPolicyId.APP_KEY_REQUEST_POLICY, appKeyRequestsPolicy);
672
+ if (status !== enums_1.SLStatus.OK) {
673
+ throw new Error(`[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${enums_2.EzspDecisionId[appKeyRequestsPolicy]} ` +
674
+ `with status=${enums_1.SLStatus[status]}.`);
783
675
  }
784
- status = (await this.emberSetJoinPolicy(enums_3.EmberJoinDecision.USE_PRECONFIGURED_KEY));
785
- if (status !== enums_3.EzspStatus.SUCCESS) {
786
- throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${enums_3.EzspStatus[status]}.`);
676
+ status = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY);
677
+ if (status !== enums_1.SLStatus.OK) {
678
+ throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${enums_1.SLStatus[status]}.`);
787
679
  }
788
680
  }
789
681
  const configNetworkKey = Buffer.from(this.networkOptions.networkKey);
790
682
  const networkInitStruct = {
791
- bitmask: (enums_3.EmberNetworkInitBitmask.PARENT_INFO_IN_TOKEN | enums_3.EmberNetworkInitBitmask.END_DEVICE_REJOIN_ON_REBOOT)
683
+ bitmask: enums_1.EmberNetworkInitBitmask.PARENT_INFO_IN_TOKEN | enums_1.EmberNetworkInitBitmask.END_DEVICE_REJOIN_ON_REBOOT,
792
684
  };
793
- const initStatus = (await this.ezsp.ezspNetworkInit(networkInitStruct));
794
- logger_1.logger.debug(`[INIT TC] Network init status=${enums_3.EmberStatus[initStatus]}.`, NS);
795
- if ((initStatus !== enums_3.EmberStatus.SUCCESS) && (initStatus !== enums_3.EmberStatus.NOT_JOINED)) {
796
- throw new Error(`[INIT TC] Failed network init request with status=${enums_3.EmberStatus[initStatus]}.`);
685
+ const initStatus = await this.ezsp.ezspNetworkInit(networkInitStruct);
686
+ logger_1.logger.debug(`[INIT TC] Network init status=${enums_1.SLStatus[initStatus]}.`, NS);
687
+ if (initStatus !== enums_1.SLStatus.OK && initStatus !== enums_1.SLStatus.NOT_JOINED) {
688
+ throw new Error(`[INIT TC] Failed network init request with status=${enums_1.SLStatus[initStatus]}.`);
797
689
  }
798
690
  let action = NetworkInitAction.DONE;
799
- if (initStatus === enums_3.EmberStatus.SUCCESS) {
691
+ if (initStatus === enums_1.SLStatus.OK) {
800
692
  // network
801
693
  await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT TC] Network init');
802
- const [npStatus, nodeType, netParams] = (await this.ezsp.ezspGetNetworkParameters());
803
- logger_1.logger.debug(`[INIT TC] Current network config=${JSON.stringify(this.networkOptions)}`, NS);
804
- logger_1.logger.debug(`[INIT TC] Current NCP network: nodeType=${enums_3.EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS);
805
- if ((npStatus === enums_3.EmberStatus.SUCCESS) && (nodeType === enums_3.EmberNodeType.COORDINATOR) && (this.networkOptions.panID === netParams.panId)
806
- && ((0, es6_1.default)(this.networkOptions.extendedPanID, netParams.extendedPanId))) {
694
+ const [npStatus, nodeType, netParams] = await this.ezsp.ezspGetNetworkParameters();
695
+ logger_1.logger.debug(`[INIT TC] Current adapter network: nodeType=${enums_1.EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS);
696
+ if (npStatus === enums_1.SLStatus.OK &&
697
+ nodeType === enums_1.EmberNodeType.COORDINATOR &&
698
+ this.networkOptions.panID === netParams.panId &&
699
+ (0, es6_1.default)(this.networkOptions.extendedPanID, netParams.extendedPanId)) {
807
700
  // config matches adapter so far, no error, we can check the network key
808
701
  const context = (0, initters_1.initSecurityManagerContext)();
809
- context.coreKeyType = enums_3.SecManKeyType.NETWORK;
702
+ context.coreKeyType = enums_1.SecManKeyType.NETWORK;
810
703
  context.keyIndex = 0;
811
- const [networkKey, nkStatus] = (await this.ezsp.ezspExportKey(context));
812
- if (nkStatus !== enums_3.SLStatus.OK) {
813
- throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_3.SLStatus[nkStatus]}.`);
704
+ const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
705
+ if (nkStatus !== enums_1.SLStatus.OK) {
706
+ throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_1.SLStatus[nkStatus]}.`);
814
707
  }
815
- logger_1.logger.debug(`[INIT TC] Current NCP network: networkKey=${networkKey.contents.toString('hex')}`, NS);
816
708
  // config doesn't match adapter anymore
817
709
  if (!networkKey.contents.equals(configNetworkKey)) {
818
710
  action = NetworkInitAction.LEAVE;
@@ -823,10 +715,10 @@ class EmberAdapter extends __1.Adapter {
823
715
  action = NetworkInitAction.LEAVE;
824
716
  }
825
717
  if (action === NetworkInitAction.LEAVE) {
826
- logger_1.logger.info(`[INIT TC] NCP network does not match config. Leaving network...`, NS);
827
- const leaveStatus = (await this.ezsp.ezspLeaveNetwork());
828
- if (leaveStatus !== enums_3.EmberStatus.SUCCESS) {
829
- throw new Error(`[INIT TC] Failed leave network request with status=${enums_3.EmberStatus[leaveStatus]}.`);
718
+ logger_1.logger.info(`[INIT TC] Adapter network does not match config. Leaving network...`, NS);
719
+ const leaveStatus = await this.ezsp.ezspLeaveNetwork();
720
+ if (leaveStatus !== enums_1.SLStatus.OK) {
721
+ throw new Error(`[INIT TC] Failed leave network request with status=${enums_1.SLStatus[leaveStatus]}.`);
830
722
  }
831
723
  await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT TC] Leave network');
832
724
  await (0, utils_1.Wait)(200); // settle down
@@ -834,13 +726,13 @@ class EmberAdapter extends __1.Adapter {
834
726
  }
835
727
  }
836
728
  const backup = this.getStoredBackup();
837
- if ((initStatus === enums_3.EmberStatus.NOT_JOINED) || (action === NetworkInitAction.LEFT)) {
729
+ if (initStatus === enums_1.SLStatus.NOT_JOINED || action === NetworkInitAction.LEFT) {
838
730
  // no network
839
731
  if (backup != null) {
840
- if ((this.networkOptions.panID === backup.networkOptions.panId)
841
- && (Buffer.from(this.networkOptions.extendedPanID).equals(backup.networkOptions.extendedPanId))
842
- && (this.networkOptions.channelList.includes(backup.logicalChannel))
843
- && (configNetworkKey.equals(backup.networkOptions.networkKey))) {
732
+ if (this.networkOptions.panID === backup.networkOptions.panId &&
733
+ Buffer.from(this.networkOptions.extendedPanID).equals(backup.networkOptions.extendedPanId) &&
734
+ this.networkOptions.channelList.includes(backup.logicalChannel) &&
735
+ configNetworkKey.equals(backup.networkOptions.networkKey)) {
844
736
  // config matches backup
845
737
  action = NetworkInitAction.FORM_BACKUP;
846
738
  }
@@ -863,29 +755,27 @@ class EmberAdapter extends __1.Adapter {
863
755
  logger_1.logger.info(`[INIT TC] Forming from backup.`, NS);
864
756
  const keyList = backup.devices.map((device) => {
865
757
  const octets = Array.from(device.ieeeAddress.reverse());
866
- const deviceEui64 = '0x' + octets.map(octet => octet.toString(16).padStart(2, '0')).join("");
867
- const key = {
868
- deviceEui64,
758
+ return {
759
+ deviceEui64: `0x${octets.map((octet) => octet.toString(16).padStart(2, '0')).join('')}`,
869
760
  key: { contents: device.linkKey.key },
870
761
  outgoingFrameCounter: device.linkKey.txCounter,
871
762
  incomingFrameCounter: device.linkKey.rxCounter,
872
763
  };
873
- return key;
874
764
  });
875
765
  // before forming
876
766
  await this.importLinkKeys(keyList);
877
- await this.formNetwork(true, /*from backup*/ backup.networkOptions.networkKey, backup.networkKeyInfo.sequenceNumber, backup.networkOptions.panId, Array.from(backup.networkOptions.extendedPanId), backup.logicalChannel, backup.ezsp.hashed_tclk);
767
+ await this.formNetwork(true /*from backup*/, backup.networkOptions.networkKey, backup.networkKeyInfo.sequenceNumber, backup.networkOptions.panId, Array.from(backup.networkOptions.extendedPanId), backup.logicalChannel, backup.ezsp.hashed_tclk);
878
768
  result = 'restored';
879
769
  break;
880
770
  }
881
771
  case NetworkInitAction.FORM_CONFIG: {
882
772
  logger_1.logger.info(`[INIT TC] Forming from config.`, NS);
883
- await this.formNetwork(false, /*from config*/ configNetworkKey, 0, this.networkOptions.panID, this.networkOptions.extendedPanID, this.networkOptions.channelList[0], (0, crypto_1.randomBytes)(consts_1.EMBER_ENCRYPTION_KEY_SIZE));
773
+ await this.formNetwork(false /*from config*/, configNetworkKey, 0, this.networkOptions.panID, this.networkOptions.extendedPanID, this.networkOptions.channelList[0], (0, crypto_1.randomBytes)(consts_2.EMBER_ENCRYPTION_KEY_SIZE));
884
774
  result = 'reset';
885
775
  break;
886
776
  }
887
777
  case NetworkInitAction.DONE: {
888
- logger_1.logger.info(`[INIT TC] NCP network matches config.`, NS);
778
+ logger_1.logger.info(`[INIT TC] Adapter network matches config.`, NS);
889
779
  break;
890
780
  }
891
781
  default: {
@@ -893,7 +783,7 @@ class EmberAdapter extends __1.Adapter {
893
783
  }
894
784
  }
895
785
  // can't let frame counter wrap to zero (uint32_t), will force a broadcast after init if getting too close
896
- if (backup != null && (backup.networkKeyInfo.frameCounter > 0xFEEEEEEE)) {
786
+ if (backup != null && backup.networkKeyInfo.frameCounter > 0xfeeeeeee) {
897
787
  // XXX: while this remains a pretty low occurrence in most (small) networks,
898
788
  // currently Z2M won't support the key update because of one-way config...
899
789
  // need to investigate handling this properly
@@ -902,9 +792,9 @@ class EmberAdapter extends __1.Adapter {
902
792
  // // XXX: no idea here on the proper timer value, but this will block the network for several seconds on exec
903
793
  // // (probably have to take the behavior of sleepy-end devices into account to improve chances of reaching everyone right away?)
904
794
  // setTimeout(async () => {
905
- // this.requestQueue.enqueue(async (): Promise<EmberStatus> => {
795
+ // this.requestQueue.enqueue(async (): Promise<SLStatus> => {
906
796
  // await this.broadcastNetworkKeyUpdate();
907
- // return EmberStatus.SUCCESS;
797
+ // return SLStatus.OK;
908
798
  // }, logger.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected
909
799
  // }, 300000);
910
800
  logger_1.logger.warning(`[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.`, NS);
@@ -916,30 +806,32 @@ class EmberAdapter extends __1.Adapter {
916
806
  */
917
807
  async formNetwork(fromBackup, networkKey, networkKeySequenceNumber, panId, extendedPanId, radioChannel, tcLinkKey) {
918
808
  const state = {
919
- bitmask: (enums_3.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY | enums_3.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
920
- | enums_3.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY | enums_3.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY
921
- | enums_3.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY),
809
+ bitmask: enums_1.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY |
810
+ enums_1.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY |
811
+ enums_1.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY |
812
+ enums_1.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY |
813
+ enums_1.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY,
922
814
  preconfiguredKey: { contents: tcLinkKey },
923
815
  networkKey: { contents: networkKey },
924
816
  networkKeySequenceNumber: networkKeySequenceNumber,
925
817
  preconfiguredTrustCenterEui64: ZSpec.BLANK_EUI64,
926
818
  };
927
819
  if (fromBackup) {
928
- state.bitmask |= enums_3.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET;
820
+ state.bitmask |= enums_1.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET;
929
821
  }
930
- let emberStatus = (await this.ezsp.ezspSetInitialSecurityState(state));
931
- if (emberStatus !== enums_3.EmberStatus.SUCCESS) {
932
- throw new Error(`[INIT FORM] Failed to set initial security state with status=${enums_3.EmberStatus[emberStatus]}.`);
822
+ let status = await this.ezsp.ezspSetInitialSecurityState(state);
823
+ if (status !== enums_1.SLStatus.OK) {
824
+ throw new Error(`[INIT FORM] Failed to set initial security state with status=${enums_1.SLStatus[status]}.`);
933
825
  }
934
- const extended = (enums_3.EmberExtendedSecurityBitmask.JOINER_GLOBAL_LINK_KEY | enums_3.EmberExtendedSecurityBitmask.NWK_LEAVE_REQUEST_NOT_ALLOWED);
935
- const extSecStatus = (await this.ezsp.ezspSetExtendedSecurityBitmask(extended));
936
- if (extSecStatus !== enums_3.EzspStatus.SUCCESS) {
937
- throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${enums_3.EzspStatus[extSecStatus]}.`);
826
+ const extended = enums_1.EmberExtendedSecurityBitmask.JOINER_GLOBAL_LINK_KEY | enums_1.EmberExtendedSecurityBitmask.NWK_LEAVE_REQUEST_NOT_ALLOWED;
827
+ status = await this.ezsp.ezspSetExtendedSecurityBitmask(extended);
828
+ if (status !== enums_1.SLStatus.OK) {
829
+ throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${enums_1.SLStatus[status]}.`);
938
830
  }
939
- if (!fromBackup && this.stackConfig.KEY_TABLE_SIZE > 0) {
940
- emberStatus = await this.ezsp.ezspClearKeyTable();
941
- if (emberStatus !== enums_3.EmberStatus.SUCCESS) {
942
- throw new Error(`[INIT FORM] Failed to clear key table with status=${enums_3.EmberStatus[emberStatus]}.`);
831
+ if (!fromBackup) {
832
+ status = await this.ezsp.ezspClearKeyTable();
833
+ if (status !== enums_1.SLStatus.OK) {
834
+ logger_1.logger.error(`[INIT FORM] Failed to clear key table with status=${enums_1.SLStatus[status]}.`, NS);
943
835
  }
944
836
  }
945
837
  const netParams = {
@@ -947,19 +839,19 @@ class EmberAdapter extends __1.Adapter {
947
839
  extendedPanId,
948
840
  radioTxPower: 5,
949
841
  radioChannel,
950
- joinMethod: enums_3.EmberJoinMethod.MAC_ASSOCIATION,
842
+ joinMethod: enums_1.EmberJoinMethod.MAC_ASSOCIATION,
951
843
  nwkManagerId: ZSpec.COORDINATOR_ADDRESS,
952
844
  nwkUpdateId: 0,
953
- channels: consts_2.EMBER_ALL_802_15_4_CHANNELS_MASK,
845
+ channels: consts_1.EMBER_ALL_802_15_4_CHANNELS_MASK,
954
846
  };
955
847
  logger_1.logger.info(`[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`, NS);
956
- emberStatus = (await this.ezsp.ezspFormNetwork(netParams));
957
- if (emberStatus !== enums_3.EmberStatus.SUCCESS) {
958
- throw new Error(`[INIT FORM] Failed form network request with status=${enums_3.EmberStatus[emberStatus]}.`);
848
+ status = await this.ezsp.ezspFormNetwork(netParams);
849
+ if (status !== enums_1.SLStatus.OK) {
850
+ throw new Error(`[INIT FORM] Failed form network request with status=${enums_1.SLStatus[status]}.`);
959
851
  }
960
852
  await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, '[INIT FORM] Form network');
961
- const stStatus = await this.ezsp.ezspStartWritingStackTokens();
962
- logger_1.logger.debug(`[INIT FORM] Start writing stack tokens status=${enums_3.EzspStatus[stStatus]}.`, NS);
853
+ status = await this.ezsp.ezspStartWritingStackTokens();
854
+ logger_1.logger.debug(`[INIT FORM] Start writing stack tokens status=${enums_1.SLStatus[status]}.`, NS);
963
855
  logger_1.logger.info(`[INIT FORM] New network formed!`, NS);
964
856
  }
965
857
  /**
@@ -971,12 +863,12 @@ class EmberAdapter extends __1.Adapter {
971
863
  }
972
864
  let data;
973
865
  try {
974
- data = JSON.parse(((0, fs_1.readFileSync)(this.backupPath)).toString());
866
+ data = JSON.parse((0, fs_1.readFileSync)(this.backupPath).toString());
975
867
  }
976
868
  catch (error) {
977
869
  throw new Error(`[BACKUP] Coordinator backup is corrupted.`);
978
870
  }
979
- if (data.metadata?.format === "zigpy/open-coordinator-backup" && data.metadata?.version) {
871
+ if (data.metadata?.format === 'zigpy/open-coordinator-backup' && data.metadata?.version) {
980
872
  if (data.metadata?.version !== 1) {
981
873
  throw new Error(`[BACKUP] Unsupported open coordinator backup version (version=${data.metadata?.version}).`);
982
874
  }
@@ -1000,27 +892,27 @@ class EmberAdapter extends __1.Adapter {
1000
892
  * @return List of keys data with AES hashed keys
1001
893
  */
1002
894
  async exportLinkKeys() {
1003
- const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE));
1004
- if (confStatus !== enums_3.EzspStatus.SUCCESS) {
1005
- throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_3.EzspStatus[confStatus]}.`);
895
+ const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE);
896
+ if (confStatus !== enums_1.SLStatus.OK) {
897
+ throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_1.SLStatus[confStatus]}.`);
1006
898
  }
1007
- let deviceEui64;
899
+ let context;
1008
900
  let plaintextKey;
1009
901
  let apsKeyMeta;
1010
902
  let status;
1011
903
  const keyList = [];
1012
904
  for (let i = 0; i < keyTableSize; i++) {
1013
- [deviceEui64, plaintextKey, apsKeyMeta, status] = (await this.ezsp.ezspExportLinkKeyByIndex(i));
1014
- logger_1.logger.debug(`[BACKUP] Export link key at index ${i}, status=${enums_3.SLStatus[status]}.`, NS);
905
+ [status, context, plaintextKey, apsKeyMeta] = await this.ezsp.ezspExportLinkKeyByIndex(i);
906
+ logger_1.logger.debug(`[BACKUP] Export link key at index ${i}, status=${enums_1.SLStatus[status]}.`, NS);
1015
907
  // only include key if we could retrieve one at index and hash it properly
1016
- if (status === enums_3.SLStatus.OK) {
908
+ if (status === enums_1.SLStatus.OK) {
1017
909
  // Rather than give the real link key, the backup contains a hashed version of the key.
1018
910
  // This is done to prevent a compromise of the backup data from compromising the current link keys.
1019
911
  // This is per the Smart Energy spec.
1020
- const [hashStatus, hashedKey] = (await this.emberAesHashSimple(plaintextKey.contents));
1021
- if (hashStatus === enums_3.EmberStatus.SUCCESS) {
912
+ const [hashStatus, hashedKey] = await this.emberAesHashSimple(plaintextKey.contents);
913
+ if (hashStatus === enums_1.SLStatus.OK) {
1022
914
  keyList.push({
1023
- deviceEui64,
915
+ deviceEui64: context.eui64,
1024
916
  key: { contents: hashedKey },
1025
917
  outgoingFrameCounter: apsKeyMeta.outgoingFrameCounter,
1026
918
  incomingFrameCounter: apsKeyMeta.incomingFrameCounter,
@@ -1028,7 +920,7 @@ class EmberAdapter extends __1.Adapter {
1028
920
  }
1029
921
  else {
1030
922
  // this should never happen?
1031
- logger_1.logger.error(`[BACKUP] Failed to hash link key at index ${i} with status=${enums_3.EmberStatus[hashStatus]}. Omitting from backup.`, NS);
923
+ logger_1.logger.error(`[BACKUP] Failed to hash link key at index ${i} with status=${enums_1.SLStatus[hashStatus]}. Omitting from backup.`, NS);
1032
924
  }
1033
925
  }
1034
926
  }
@@ -1044,30 +936,27 @@ class EmberAdapter extends __1.Adapter {
1044
936
  if (!backupData?.length) {
1045
937
  return;
1046
938
  }
1047
- const [confStatus, keyTableSize] = (await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE));
1048
- if (confStatus !== enums_3.EzspStatus.SUCCESS) {
1049
- throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_3.EzspStatus[confStatus]}.`);
939
+ const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE);
940
+ if (confStatus !== enums_1.SLStatus.OK) {
941
+ throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_1.SLStatus[confStatus]}.`);
1050
942
  }
1051
943
  if (backupData.length > keyTableSize) {
1052
944
  throw new Error(`[BACKUP] Current key table of ${keyTableSize} is too small to import backup of ${backupData.length}!`);
1053
945
  }
1054
- const networkStatus = (await this.emberNetworkState());
1055
- if (networkStatus !== enums_3.EmberNetworkStatus.NO_NETWORK) {
1056
- throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${enums_3.EmberNetworkStatus[networkStatus]}.`);
946
+ const networkStatus = await this.emberNetworkState();
947
+ if (networkStatus !== enums_1.EmberNetworkStatus.NO_NETWORK) {
948
+ throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${enums_1.EmberNetworkStatus[networkStatus]}.`);
1057
949
  }
1058
950
  let status;
1059
951
  for (let i = 0; i < keyTableSize; i++) {
1060
- if (i >= backupData.length) {
1061
- // erase any key index not present in backup but available on the NCP
1062
- status = (await this.ezsp.ezspEraseKeyTableEntry(i));
1063
- }
1064
- else {
1065
- const importStatus = (await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key));
1066
- status = ((importStatus === enums_3.SLStatus.OK) ? enums_3.EmberStatus.SUCCESS : enums_3.EmberStatus.KEY_TABLE_INVALID_ADDRESS);
1067
- }
1068
- if (status !== enums_3.EmberStatus.SUCCESS) {
1069
- throw new Error(`[BACKUP] Failed to ${((i >= backupData.length) ? "erase" : "set")} key table entry at index ${i} `
1070
- + `with status=${enums_3.EmberStatus[status]}`);
952
+ // erase any key index not present in backup but available on the NCP
953
+ status =
954
+ i >= backupData.length
955
+ ? await this.ezsp.ezspEraseKeyTableEntry(i)
956
+ : await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key);
957
+ if (status !== enums_1.SLStatus.OK) {
958
+ throw new Error(`[BACKUP] Failed to ${i >= backupData.length ? 'erase' : 'set'} key table entry at index ${i} ` +
959
+ `with status=${enums_1.SLStatus[status]}`);
1071
960
  }
1072
961
  }
1073
962
  logger_1.logger.info(`[BACKUP] Imported ${backupData.length} keys.`, NS);
@@ -1079,27 +968,21 @@ class EmberAdapter extends __1.Adapter {
1079
968
  * On the other hand, the more often this runs, the more secure the network is...
1080
969
  */
1081
970
  async broadcastNetworkKeyUpdate() {
1082
- return new Promise((resolve, reject) => {
1083
- this.requestQueue.enqueue(async () => {
1084
- logger_1.logger.warning(`[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.`, NS);
1085
- // zero-filled = let stack generate new random network key
1086
- let status = await this.ezsp.ezspBroadcastNextNetworkKey({ contents: Buffer.alloc(consts_1.EMBER_ENCRYPTION_KEY_SIZE) });
1087
- if (status !== enums_3.EmberStatus.SUCCESS) {
1088
- logger_1.logger.error(`[TRUST CENTER] Failed to broadcast next network key with status=${enums_3.EmberStatus[status]}.`, NS);
1089
- return status;
1090
- }
1091
- // XXX: this will block other requests for a while, but should ensure the key propagates without interference?
1092
- // could also stop dispatching entirely and do this outside the queue if necessary/better
1093
- await (0, utils_1.Wait)(BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME);
1094
- status = (await this.ezsp.ezspBroadcastNetworkKeySwitch());
1095
- if (status !== enums_3.EmberStatus.SUCCESS) {
1096
- // XXX: Not sure how likely this is, but this is bad, probably should hard fail?
1097
- logger_1.logger.error(`[TRUST CENTER] Failed to broadcast network key switch with status=${enums_3.EmberStatus[status]}.`, NS);
1098
- return status;
1099
- }
1100
- resolve();
1101
- return status;
1102
- }, reject);
971
+ return this.queue.execute(async () => {
972
+ logger_1.logger.warning(`[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.`, NS);
973
+ // zero-filled = let stack generate new random network key
974
+ let status = await this.ezsp.ezspBroadcastNextNetworkKey({ contents: Buffer.alloc(consts_2.EMBER_ENCRYPTION_KEY_SIZE) });
975
+ if (status !== enums_1.SLStatus.OK) {
976
+ throw new Error(`[TRUST CENTER] Failed to broadcast next network key with status=${enums_1.SLStatus[status]}.`);
977
+ }
978
+ // XXX: this will block other requests for a while, but should ensure the key propagates without interference?
979
+ // could also stop dispatching entirely and do this outside the queue if necessary/better
980
+ await (0, utils_1.Wait)(BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME);
981
+ status = await this.ezsp.ezspBroadcastNetworkKeySwitch();
982
+ if (status !== enums_1.SLStatus.OK) {
983
+ // XXX: Not sure how likely this is, but this is bad, probably should hard fail?
984
+ throw new Error(`[TRUST CENTER] Failed to broadcast network key switch with status=${enums_1.SLStatus[status]}.`);
985
+ }
1103
986
  });
1104
987
  }
1105
988
  /**
@@ -1107,16 +990,23 @@ class EmberAdapter extends __1.Adapter {
1107
990
  * @param status
1108
991
  */
1109
992
  async onNcpNeedsResetAndInit(status) {
1110
- logger_1.logger.error(`!!! NCP FATAL ERROR reason=${enums_3.EzspStatus[status]}. ATTEMPTING RESET... !!!`, NS);
1111
- try {
1112
- await this.stop();
1113
- await (0, utils_1.Wait)(500); // just because
1114
- await this.start();
1115
- }
1116
- catch (err) {
1117
- logger_1.logger.error(`Failed to reset and init NCP. ${err}`, NS);
993
+ logger_1.logger.error(`!!! ADAPTER FATAL ERROR reason=${enums_1.EzspStatus[status]}. !!!`, NS);
994
+ if (this.queue.count() > QUEUE_HIGH_COUNT) {
995
+ logger_1.logger.info(`Request queue is high (${this.queue.count()}), triggering full restart to prevent stressing the adapter.`, NS);
1118
996
  this.emit(events_1.Events.disconnected);
1119
997
  }
998
+ else {
999
+ logger_1.logger.info(`Attempting adapter reset...`, NS);
1000
+ try {
1001
+ await this.stop();
1002
+ await (0, utils_1.Wait)(500); // just because
1003
+ await this.start();
1004
+ }
1005
+ catch (err) {
1006
+ logger_1.logger.error(`Failed to reset and init adapter. ${err}`, NS);
1007
+ this.emit(events_1.Events.disconnected);
1008
+ }
1009
+ }
1120
1010
  }
1121
1011
  //---- START Events
1122
1012
  //---- END Events
@@ -1133,8 +1023,8 @@ class EmberAdapter extends __1.Adapter {
1133
1023
  * Check against UNKNOWN_NETWORK_STATE for validity.
1134
1024
  */
1135
1025
  async emberNetworkState() {
1136
- if (this.networkCache.status === consts_2.UNKNOWN_NETWORK_STATE) {
1137
- const networkStatus = (await this.ezsp.ezspNetworkState());
1026
+ if (this.networkCache.status === consts_1.UNKNOWN_NETWORK_STATE) {
1027
+ const networkStatus = await this.ezsp.ezspNetworkState();
1138
1028
  this.networkCache.status = networkStatus;
1139
1029
  }
1140
1030
  return this.networkCache.status;
@@ -1146,7 +1036,7 @@ class EmberAdapter extends __1.Adapter {
1146
1036
  */
1147
1037
  async emberGetEui64() {
1148
1038
  if (this.networkCache.eui64 === ZSpec.BLANK_EUI64) {
1149
- this.networkCache.eui64 = (await this.ezsp.ezspGetEui64());
1039
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
1150
1040
  }
1151
1041
  return this.networkCache.eui64;
1152
1042
  }
@@ -1157,12 +1047,12 @@ class EmberAdapter extends __1.Adapter {
1157
1047
  */
1158
1048
  async emberGetPanId() {
1159
1049
  if (this.networkCache.parameters.panId === ZSpec.INVALID_PAN_ID) {
1160
- const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
1161
- if (status === enums_3.EmberStatus.SUCCESS) {
1050
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1051
+ if (status === enums_1.SLStatus.OK) {
1162
1052
  this.networkCache.parameters = parameters;
1163
1053
  }
1164
1054
  else {
1165
- logger_1.logger.error(`Failed to get PAN ID (via network parameters) with status=${enums_3.EmberStatus[status]}.`, NS);
1055
+ logger_1.logger.error(`Failed to get PAN ID (via network parameters) with status=${enums_1.SLStatus[status]}.`, NS);
1166
1056
  }
1167
1057
  }
1168
1058
  return this.networkCache.parameters.panId;
@@ -1174,12 +1064,12 @@ class EmberAdapter extends __1.Adapter {
1174
1064
  */
1175
1065
  async emberGetExtendedPanId() {
1176
1066
  if ((0, es6_1.default)(this.networkCache.parameters.extendedPanId, ZSpec.BLANK_EXTENDED_PAN_ID)) {
1177
- const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
1178
- if (status === enums_3.EmberStatus.SUCCESS) {
1067
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1068
+ if (status === enums_1.SLStatus.OK) {
1179
1069
  this.networkCache.parameters = parameters;
1180
1070
  }
1181
1071
  else {
1182
- logger_1.logger.error(`Failed to get Extended PAN ID (via network parameters) with status=${enums_3.EmberStatus[status]}.`, NS);
1072
+ logger_1.logger.error(`Failed to get Extended PAN ID (via network parameters) with status=${enums_1.SLStatus[status]}.`, NS);
1183
1073
  }
1184
1074
  }
1185
1075
  return this.networkCache.parameters.extendedPanId;
@@ -1190,30 +1080,25 @@ class EmberAdapter extends __1.Adapter {
1190
1080
  * Check against INVALID_RADIO_CHANNEL for validity.
1191
1081
  */
1192
1082
  async emberGetRadioChannel() {
1193
- if (this.networkCache.parameters.radioChannel === consts_2.INVALID_RADIO_CHANNEL) {
1194
- const [status, , parameters] = (await this.ezsp.ezspGetNetworkParameters());
1195
- if (status === enums_3.EmberStatus.SUCCESS) {
1083
+ if (this.networkCache.parameters.radioChannel === consts_1.INVALID_RADIO_CHANNEL) {
1084
+ const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
1085
+ if (status === enums_1.SLStatus.OK) {
1196
1086
  this.networkCache.parameters = parameters;
1197
1087
  }
1198
1088
  else {
1199
- logger_1.logger.error(`Failed to get radio channel (via network parameters) with status=${enums_3.EmberStatus[status]}.`, NS);
1089
+ logger_1.logger.error(`Failed to get radio channel (via network parameters) with status=${enums_1.SLStatus[status]}.`, NS);
1200
1090
  }
1201
1091
  }
1202
1092
  return this.networkCache.parameters.radioChannel;
1203
1093
  }
1204
1094
  // queued
1205
1095
  async emberStartEnergyScan() {
1206
- return new Promise((resolve, reject) => {
1207
- this.requestQueue.enqueue(async () => {
1208
- const status = (await this.ezsp.ezspStartScan(enums_3.EzspNetworkScanType.ENERGY_SCAN, consts_2.EMBER_ALL_802_15_4_CHANNELS_MASK, ENERGY_SCAN_DURATION));
1209
- if (status !== enums_3.SLStatus.OK) {
1210
- logger_1.logger.error(`Failed energy scan request with status=${enums_3.SLStatus[status]}.`, NS);
1211
- return enums_3.EmberStatus.ERR_FATAL;
1212
- }
1213
- // TODO: result in logs only atm, since UI doesn't support it
1214
- resolve();
1215
- return enums_3.EmberStatus.SUCCESS;
1216
- }, reject);
1096
+ return this.queue.execute(async () => {
1097
+ const status = await this.ezsp.ezspStartScan(enums_1.EzspNetworkScanType.ENERGY_SCAN, consts_1.EMBER_ALL_802_15_4_CHANNELS_MASK, ENERGY_SCAN_DURATION);
1098
+ if (status !== enums_1.SLStatus.OK) {
1099
+ throw new Error(`Failed energy scan request with status=${enums_1.SLStatus[status]}.`);
1100
+ }
1101
+ // TODO: result in logs only atm, since UI doesn't support it
1217
1102
  });
1218
1103
  }
1219
1104
  //---- END Cache-enabled EZSP wrappers
@@ -1227,35 +1112,40 @@ class EmberAdapter extends __1.Adapter {
1227
1112
  * Does nothing if ncpNeedsResetAndInit == true.
1228
1113
  */
1229
1114
  async emberVersion() {
1230
- // Note that NCP == Network Co-Processor
1231
- // the EZSP protocol version that the Host is running, we are the host so we set this value
1232
- const hostEzspProtocolVer = consts_1.EZSP_PROTOCOL_VERSION;
1233
1115
  // send the Host version number to the NCP.
1234
1116
  // The NCP returns the EZSP version that the NCP is running along with the stackType and stackVersion
1235
- const [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = (await this.ezsp.ezspVersion(hostEzspProtocolVer));
1117
+ let [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(consts_2.EZSP_PROTOCOL_VERSION);
1236
1118
  // verify that the stack type is what is expected
1237
- if (ncpStackType !== consts_1.EZSP_STACK_TYPE_MESH) {
1119
+ if (ncpStackType !== consts_2.EZSP_STACK_TYPE_MESH) {
1238
1120
  throw new Error(`Stack type ${ncpStackType} is not expected!`);
1239
1121
  }
1240
- // verify that the NCP EZSP Protocol version is what is expected
1241
- if (ncpEzspProtocolVer !== consts_1.EZSP_PROTOCOL_VERSION) {
1242
- throw new Error(`NCP EZSP protocol version of ${ncpEzspProtocolVer} does not match Host version ${hostEzspProtocolVer}`);
1122
+ if (ncpEzspProtocolVer === consts_2.EZSP_PROTOCOL_VERSION) {
1123
+ logger_1.logger.debug(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) matches Host.`, NS);
1124
+ }
1125
+ else if (ncpEzspProtocolVer < consts_2.EZSP_PROTOCOL_VERSION && ncpEzspProtocolVer >= consts_2.EZSP_MIN_PROTOCOL_VERSION) {
1126
+ [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(ncpEzspProtocolVer);
1127
+ logger_1.logger.info(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) lower than Host. Switched.`, NS);
1128
+ }
1129
+ else {
1130
+ throw new Error(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) is not supported ` +
1131
+ `by Host [${consts_2.EZSP_MIN_PROTOCOL_VERSION}-${consts_2.EZSP_PROTOCOL_VERSION}].`);
1243
1132
  }
1244
- logger_1.logger.debug(`NCP info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS);
1245
- const [status, versionStruct] = (await this.ezsp.ezspGetVersionStruct());
1246
- if (status !== enums_3.EzspStatus.SUCCESS) {
1133
+ this.ezsp.setProtocolVersion(ncpEzspProtocolVer);
1134
+ logger_1.logger.debug(`Adapter info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS);
1135
+ const [status, versionStruct] = await this.ezsp.ezspGetVersionStruct();
1136
+ if (status !== enums_1.SLStatus.OK) {
1247
1137
  // Should never happen with support of only EZSP v13+
1248
1138
  throw new Error(`NCP has old-style version number. Not supported.`);
1249
1139
  }
1250
1140
  this.version = {
1251
1141
  ezsp: ncpEzspProtocolVer,
1252
- revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${enums_3.EmberVersionType[versionStruct.type]}]`,
1142
+ revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${enums_1.EmberVersionType[versionStruct.type]}]`,
1253
1143
  ...versionStruct,
1254
1144
  };
1255
- if (versionStruct.type !== enums_3.EmberVersionType.GA) {
1256
- logger_1.logger.warning(`NCP is running a non-GA version (${enums_3.EmberVersionType[versionStruct.type]}).`, NS);
1145
+ if (versionStruct.type !== enums_1.EmberVersionType.GA) {
1146
+ logger_1.logger.warning(`Adapter is running a non-GA version (${enums_1.EmberVersionType[versionStruct.type]}).`, NS);
1257
1147
  }
1258
- logger_1.logger.debug(`NCP version info: ${JSON.stringify(this.version)}`, NS);
1148
+ logger_1.logger.info(`Adapter version info: ${JSON.stringify(this.version)}`, NS);
1259
1149
  }
1260
1150
  /**
1261
1151
  * This function sets an EZSP config value.
@@ -1266,15 +1156,11 @@ class EmberAdapter extends __1.Adapter {
1266
1156
  * @returns
1267
1157
  */
1268
1158
  async emberSetEzspConfigValue(configId, value) {
1269
- const status = (await this.ezsp.ezspSetConfigurationValue(configId, value));
1270
- logger_1.logger.debug(`[EzspConfigId] SET "${enums_2.EzspConfigId[configId]}" TO "${value}" with status=${enums_3.EzspStatus[status]}.`, NS);
1271
- if (status === enums_3.EzspStatus.ERROR_INVALID_ID) {
1272
- // can be ZLL where not all NCPs need or support it.
1273
- logger_1.logger.warning(`[EzspConfigId] Unsupported configuration ID ${enums_2.EzspConfigId[configId]} by NCP.`, NS);
1274
- }
1275
- else if (status !== enums_3.EzspStatus.SUCCESS) {
1276
- logger_1.logger.warning(`[EzspConfigId] Failed to SET "${enums_2.EzspConfigId[configId]}" TO "${value}" with status=${enums_3.EzspStatus[status]}. `
1277
- + `Firmware value will be used instead.`, NS);
1159
+ const status = await this.ezsp.ezspSetConfigurationValue(configId, value);
1160
+ logger_1.logger.debug(`[EzspConfigId] SET "${enums_2.EzspConfigId[configId]}" TO "${value}" with status=${enums_1.SLStatus[status]}.`, NS);
1161
+ if (status !== enums_1.SLStatus.OK) {
1162
+ logger_1.logger.info(`[EzspConfigId] Failed to SET "${enums_2.EzspConfigId[configId]}" TO "${value}" with status=${enums_1.SLStatus[status]}. ` +
1163
+ `Firmware value will be used instead.`, NS);
1278
1164
  }
1279
1165
  return status;
1280
1166
  }
@@ -1286,8 +1172,8 @@ class EmberAdapter extends __1.Adapter {
1286
1172
  * @returns
1287
1173
  */
1288
1174
  async emberSetEzspValue(valueId, valueLength, value) {
1289
- const status = (await this.ezsp.ezspSetValue(valueId, valueLength, value));
1290
- logger_1.logger.debug(`[EzspValueId] SET "${enums_2.EzspValueId[valueId]}" TO "${value}" with status=${enums_3.EzspStatus[status]}.`, NS);
1175
+ const status = await this.ezsp.ezspSetValue(valueId, valueLength, value);
1176
+ logger_1.logger.debug(`[EzspValueId] SET "${enums_2.EzspValueId[valueId]}" TO "${value}" with status=${enums_1.SLStatus[status]}.`, NS);
1291
1177
  return status;
1292
1178
  }
1293
1179
  /**
@@ -1297,8 +1183,8 @@ class EmberAdapter extends __1.Adapter {
1297
1183
  * @returns
1298
1184
  */
1299
1185
  async emberSetEzspPolicy(policyId, decisionId) {
1300
- const status = (await this.ezsp.ezspSetPolicy(policyId, decisionId));
1301
- logger_1.logger.debug(`[EzspPolicyId] SET "${enums_2.EzspPolicyId[policyId]}" TO "${decisionId}" with status=${enums_3.EzspStatus[status]}.`, NS);
1186
+ const status = await this.ezsp.ezspSetPolicy(policyId, decisionId);
1187
+ logger_1.logger.debug(`[EzspPolicyId] SET "${enums_2.EzspPolicyId[policyId]}" TO "${decisionId}" with status=${enums_1.SLStatus[status]}.`, NS);
1302
1188
  return status;
1303
1189
  }
1304
1190
  /**
@@ -1314,9 +1200,10 @@ class EmberAdapter extends __1.Adapter {
1314
1200
  */
1315
1201
  async aesMmoHash(context, finalize, data) {
1316
1202
  if (data.length > 255) {
1317
- throw new Error(enums_3.EzspStatus[enums_3.EzspStatus.ERROR_INVALID_CALL]);
1203
+ // will be caught by request queue and rejected internally.
1204
+ throw new ezspError_1.EzspError(enums_1.EzspStatus.ERROR_INVALID_CALL);
1318
1205
  }
1319
- const [status, reContext] = (await this.ezsp.ezspAesMmoHash(context, finalize, data));
1206
+ const [status, reContext] = await this.ezsp.ezspAesMmoHash(context, finalize, data);
1320
1207
  return [status, reContext];
1321
1208
  }
1322
1209
  /**
@@ -1327,7 +1214,7 @@ class EmberAdapter extends __1.Adapter {
1327
1214
  * @param context EmberAesMmoHashContext* A pointer to the location of the hash context to update.
1328
1215
  * @param data const uint8_t* A pointer to the location of the data to hash.
1329
1216
  *
1330
- * @returns An ::EmberStatus value indicating EMBER_SUCCESS if the hash was
1217
+ * @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
1331
1218
  * calculated successfully. EMBER_INVALID_CALL if the block size is not a
1332
1219
  * multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
1333
1220
  * data exceeds the maximum limits of the hash function.
@@ -1347,7 +1234,7 @@ class EmberAdapter extends __1.Adapter {
1347
1234
  * @param context EmberAesMmoHashContext * A pointer to the location of the hash context to finalize.
1348
1235
  * @param data uint8_t * A pointer to the location of data to hash. May be NULL.
1349
1236
  *
1350
- * @returns An ::EmberStatus value indicating EMBER_SUCCESS if the hash was
1237
+ * @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
1351
1238
  * calculated successfully. EMBER_INVALID_CALL if the block size is not a
1352
1239
  * multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
1353
1240
  * data exceeds the maximum limits of the hash function.
@@ -1362,7 +1249,7 @@ class EmberAdapter extends __1.Adapter {
1362
1249
  *
1363
1250
  * @param data const uint8_t* The data to hash. Expected of valid length (as in, not larger alloc)
1364
1251
  *
1365
- * @returns An ::EmberStatus value indicating EMBER_SUCCESS if the hash was
1252
+ * @returns An ::SLStatus value indicating EMBER_SUCCESS if the hash was
1366
1253
  * calculated successfully. EMBER_INVALID_CALL if the block size is not a
1367
1254
  * multiple of 16 bytes, and EMBER_INDEX_OUT_OF_RANGE is returned when the
1368
1255
  * data exceeds the maximum limits of the hash function.
@@ -1370,7 +1257,7 @@ class EmberAdapter extends __1.Adapter {
1370
1257
  */
1371
1258
  async emberAesHashSimple(data) {
1372
1259
  const context = (0, initters_1.aesMmoHashInit)();
1373
- const [status, reContext] = (await this.emberAesMmoHashFinal(context, data));
1260
+ const [status, reContext] = await this.emberAesMmoHashFinal(context, data);
1374
1261
  return [status, reContext?.result];
1375
1262
  }
1376
1263
  /**
@@ -1387,13 +1274,14 @@ class EmberAdapter extends __1.Adapter {
1387
1274
  * @returns messageTag The tag passed to ezspSend${x} function.
1388
1275
  */
1389
1276
  async emberPermitJoining(duration, broadcastMgmtPermitJoin) {
1390
- let status = (await this.ezsp.ezspPermitJoining(duration));
1277
+ let status = await this.ezsp.ezspPermitJoining(duration);
1391
1278
  let apsFrame = null;
1392
1279
  let messageTag = null;
1393
1280
  logger_1.logger.debug(`Permit joining for ${duration} sec. status=${[status]}`, NS);
1394
1281
  if (broadcastMgmtPermitJoin) {
1395
1282
  // `authentication`: TC significance always 1 (zb specs)
1396
- [status, apsFrame, messageTag] = (await this.emberPermitJoiningRequest(enums_1.BroadcastAddress.DEFAULT, duration, 1, DEFAULT_APS_OPTIONS));
1283
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildPermitJoining(duration, 1, []);
1284
+ [status, apsFrame, messageTag] = await this.sendZDORequest(ZSpec.BroadcastAddress.DEFAULT, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1397
1285
  }
1398
1286
  return [status, apsFrame, messageTag];
1399
1287
  }
@@ -1404,92 +1292,17 @@ class EmberAdapter extends __1.Adapter {
1404
1292
  */
1405
1293
  async emberSetJoinPolicy(decision) {
1406
1294
  let policy = enums_2.EzspDecisionBitmask.DEFAULT_CONFIGURATION;
1407
- if (decision == enums_3.EmberJoinDecision.USE_PRECONFIGURED_KEY) {
1408
- policy = (enums_2.EzspDecisionBitmask.ALLOW_JOINS | enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS);
1295
+ if (decision == enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY) {
1296
+ policy = enums_2.EzspDecisionBitmask.ALLOW_JOINS | enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
1409
1297
  }
1410
- else if (decision == enums_3.EmberJoinDecision.SEND_KEY_IN_THE_CLEAR) {
1411
- policy = (enums_2.EzspDecisionBitmask.ALLOW_JOINS | enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS | enums_2.EzspDecisionBitmask.SEND_KEY_IN_CLEAR);
1298
+ else if (decision == enums_1.EmberJoinDecision.SEND_KEY_IN_THE_CLEAR) {
1299
+ policy = enums_2.EzspDecisionBitmask.ALLOW_JOINS | enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS | enums_2.EzspDecisionBitmask.SEND_KEY_IN_CLEAR;
1412
1300
  }
1413
- else if (decision == enums_3.EmberJoinDecision.ALLOW_REJOINS_ONLY) {
1301
+ else if (decision == enums_1.EmberJoinDecision.ALLOW_REJOINS_ONLY) {
1414
1302
  policy = enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
1415
1303
  }
1416
1304
  return this.emberSetEzspPolicy(enums_2.EzspPolicyId.TRUST_CENTER_POLICY, policy);
1417
1305
  }
1418
- /**
1419
- * Get Source Route Overhead
1420
- *
1421
- * Returns the number of bytes needed in a packet for source routing.
1422
- * Since each hop consumes 2 bytes in the packet, this routine calculates the
1423
- * total number of bytes needed based on number of hops to reach the destination.
1424
- *
1425
- * This function is called by the framework to determine the overhead required
1426
- * in the network frame for source routing to a particular destination.
1427
- *
1428
- * @param destination The node id of the destination Ver.: always
1429
- * @returns int8u The number of bytes needed for source routing in a packet.
1430
- */
1431
- async emberGetSourceRouteOverhead(destination) {
1432
- const [status, value] = (await this.ezsp.ezspGetSourceRouteOverhead(destination));
1433
- if (status === enums_3.EzspStatus.SUCCESS) {
1434
- return value;
1435
- }
1436
- else {
1437
- logger_1.logger.debug(`Failed to get source route overhead (via extended value), status=${enums_3.EzspStatus[status]}.`, NS);
1438
- }
1439
- return 0;
1440
- }
1441
- /**
1442
- * Return the maximum size of the payload that the Application Support sub-layer will accept for
1443
- * the given message type, destination, and APS frame.
1444
- *
1445
- * The size depends on multiple factors, including the security level in use and additional information
1446
- * added to the message to support the various options.
1447
- *
1448
- * @param type The outgoing message type.
1449
- * @param indexOrDestination uint16_t Depending on the message type, this is either the
1450
- * EmberNodeId of the destination, an index into the address table, an index
1451
- * into the binding table, the multicast identifier, or a broadcast address.
1452
- * @param apsFrame EmberApsFrame *The APS frame for the message.
1453
- * @return uint8_t The maximum APS payload length for the given message.
1454
- */
1455
- async maximumApsPayloadLength(type, indexOrDestination, apsFrame) {
1456
- let destination = consts_2.EMBER_UNKNOWN_NODE_ID;
1457
- let max = consts_2.MAXIMUM_APS_PAYLOAD_LENGTH; // uint8_t
1458
- if ((apsFrame.options & enums_3.EmberApsOption.ENCRYPTION) !== 0) {
1459
- max -= consts_2.APS_ENCRYPTION_OVERHEAD;
1460
- }
1461
- if ((apsFrame.options & enums_3.EmberApsOption.SOURCE_EUI64) !== 0) {
1462
- max -= consts_1.EUI64_SIZE;
1463
- }
1464
- if ((apsFrame.options & enums_3.EmberApsOption.DESTINATION_EUI64) !== 0) {
1465
- max -= consts_1.EUI64_SIZE;
1466
- }
1467
- if ((apsFrame.options & enums_3.EmberApsOption.FRAGMENT) !== 0) {
1468
- max -= consts_2.APS_FRAGMENTATION_OVERHEAD;
1469
- }
1470
- switch (type) {
1471
- case enums_3.EmberOutgoingMessageType.DIRECT:
1472
- destination = indexOrDestination;
1473
- break;
1474
- case enums_3.EmberOutgoingMessageType.VIA_ADDRESS_TABLE:
1475
- destination = (await this.ezsp.ezspGetAddressTableRemoteNodeId(indexOrDestination));
1476
- break;
1477
- case enums_3.EmberOutgoingMessageType.VIA_BINDING:
1478
- destination = (await this.ezsp.ezspGetBindingRemoteNodeId(indexOrDestination));
1479
- break;
1480
- case enums_3.EmberOutgoingMessageType.MULTICAST:
1481
- // APS multicast messages include the two-byte group id and exclude the one-byte destination endpoint,
1482
- // for a net loss of an extra byte.
1483
- max--;
1484
- break;
1485
- case enums_3.EmberOutgoingMessageType.BROADCAST:
1486
- break;
1487
- default:
1488
- break;
1489
- }
1490
- max -= (await this.emberGetSourceRouteOverhead(destination));
1491
- return max;
1492
- }
1493
1306
  //---- END EZSP wrappers
1494
1307
  //---- START Ember ZDO
1495
1308
  /**
@@ -1521,525 +1334,55 @@ class EmberAdapter extends __1.Adapter {
1521
1334
  * @return uint8_t The next device request sequence number
1522
1335
  */
1523
1336
  nextZDORequestSequence() {
1524
- return (this.zdoRequestSequence = ((++this.zdoRequestSequence) & APPLICATION_ZDO_SEQUENCE_MASK));
1337
+ return (this.zdoRequestSequence = ++this.zdoRequestSequence & APPLICATION_ZDO_SEQUENCE_MASK);
1525
1338
  }
1526
1339
  /**
1527
1340
  * ZDO
1528
1341
  *
1529
1342
  * @param destination
1530
1343
  * @param clusterId uint16_t
1344
+ * @param messageContents Content of the ZDO request (sequence to be assigned at index zero)
1531
1345
  * @param options
1532
- * @param length uint8_t
1533
1346
  * @returns status Indicates success or failure (with reason) of send
1534
1347
  * @returns apsFrame The APS Frame resulting of the request being built and sent (`sequence` set from stack-given value).
1535
1348
  * @returns messageTag The tag passed to ezspSend${x} function.
1536
1349
  */
1537
- async sendZDORequestBuffer(destination, clusterId, options) {
1538
- if (this.zdoRequestBuffalo.getPosition() > consts_1.EZSP_MAX_FRAME_LENGTH) {
1539
- return [enums_3.EmberStatus.MESSAGE_TOO_LONG, null, null];
1350
+ async sendZDORequest(destination, clusterId, messageContents, options) {
1351
+ if (messageContents.length > consts_2.EZSP_MAX_FRAME_LENGTH) {
1352
+ return [enums_1.SLStatus.MESSAGE_TOO_LONG, null, null];
1540
1353
  }
1541
1354
  const messageTag = this.nextZDORequestSequence();
1542
- this.zdoRequestBuffalo.setCommandByte(0, messageTag);
1355
+ messageContents[0] = messageTag;
1543
1356
  const apsFrame = {
1544
- profileId: zdo_1.ZDO_PROFILE_ID,
1545
- clusterId: clusterId,
1546
- sourceEndpoint: zdo_1.ZDO_ENDPOINT,
1547
- destinationEndpoint: zdo_1.ZDO_ENDPOINT,
1548
- options: options,
1357
+ profileId: Zdo.ZDO_PROFILE_ID,
1358
+ clusterId,
1359
+ sourceEndpoint: Zdo.ZDO_ENDPOINT,
1360
+ destinationEndpoint: Zdo.ZDO_ENDPOINT,
1361
+ options,
1549
1362
  groupId: 0,
1550
1363
  sequence: 0, // set by stack
1551
1364
  };
1552
- const messageContents = this.zdoRequestBuffalo.getWritten();
1553
- if (destination === enums_1.BroadcastAddress.DEFAULT || destination === enums_1.BroadcastAddress.RX_ON_WHEN_IDLE
1554
- || destination === enums_1.BroadcastAddress.SLEEPY) {
1555
- logger_1.logger.debug(`~~~> [ZDO BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
1556
- const [status, apsSequence] = (await this.ezsp.ezspSendBroadcast(destination, apsFrame, this.getZDORequestRadius(), messageTag, messageContents));
1365
+ if (destination === ZSpec.BroadcastAddress.DEFAULT ||
1366
+ destination === ZSpec.BroadcastAddress.RX_ON_WHEN_IDLE ||
1367
+ destination === ZSpec.BroadcastAddress.SLEEPY) {
1368
+ logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} BROADCAST to=${destination} messageTag=${messageTag} ` +
1369
+ `messageContents=${messageContents.toString('hex')}]`, NS);
1370
+ const [status, apsSequence] = await this.ezsp.ezspSendBroadcast(ZSpec.NULL_NODE_ID, // alias
1371
+ destination, 0, // nwkSequence
1372
+ apsFrame, this.getZDORequestRadius(), messageTag, messageContents);
1557
1373
  apsFrame.sequence = apsSequence;
1558
- logger_1.logger.debug(`~~~> [SENT ZDO type=BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${enums_3.EmberStatus[status]}]`, NS);
1374
+ logger_1.logger.debug(`~~~> [SENT ZDO type=BROADCAST apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_1.SLStatus[status]}`, NS);
1559
1375
  return [status, apsFrame, messageTag];
1560
1376
  }
1561
1377
  else {
1562
- logger_1.logger.debug(`~~~> [ZDO UNICAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
1563
- const [status, apsSequence] = (await this.ezsp.ezspSendUnicast(enums_3.EmberOutgoingMessageType.DIRECT, destination, apsFrame, messageTag, messageContents));
1378
+ logger_1.logger.debug(`~~~> [ZDO ${Zdo.ClusterId[clusterId]} UNICAST to=${destination} messageTag=${messageTag} ` +
1379
+ `messageContents=${messageContents.toString('hex')}]`, NS);
1380
+ const [status, apsSequence] = await this.ezsp.ezspSendUnicast(enums_1.EmberOutgoingMessageType.DIRECT, destination, apsFrame, messageTag, messageContents);
1564
1381
  apsFrame.sequence = apsSequence;
1565
- logger_1.logger.debug(`~~~> [SENT ZDO type=DIRECT apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${enums_3.EmberStatus[status]}]`, NS);
1382
+ logger_1.logger.debug(`~~~> [SENT ZDO type=DIRECT apsSequence=${apsSequence} messageTag=${messageTag} status=${enums_1.SLStatus[status]}`, NS);
1566
1383
  return [status, apsFrame, messageTag];
1567
1384
  }
1568
1385
  }
1569
- /**
1570
- * ZDO
1571
- * Service Discovery Functions
1572
- * Request the specified node to send a list of its endpoints that
1573
- * match the specified application profile and, optionally, lists of input
1574
- * and/or output clusters.
1575
- * @param target The node whose matching endpoints are desired. The request can
1576
- * be sent unicast or broadcast ONLY to the "RX-on-when-idle-address" (0xFFFD)
1577
- * If sent as a broadcast, any node that has matching endpoints will send a
1578
- * response.
1579
- * @param profile uint16_t The application profile to match.
1580
- * @param inCount uint8_t The number of input clusters. To not match any input
1581
- * clusters, set this value to 0.
1582
- * @param outCount uint8_t The number of output clusters. To not match any output
1583
- * clusters, set this value to 0.
1584
- * @param inClusters uint16_t * The list of input clusters.
1585
- * @param outClusters uint16_t * The list of output clusters.
1586
- * @param options The options to use when sending the unicast request. See
1587
- * emberSendUnicast() for a description. This parameter is ignored if the target
1588
- * is a broadcast address.
1589
- * @returns An EmberStatus value. EMBER_SUCCESS, MESSAGE_TOO_LONG,
1590
- * EMBER_NETWORK_DOWN or EMBER_NETWORK_BUSY.
1591
- */
1592
- async emberMatchDescriptorsRequest(target, profile, inClusters, outClusters, options) {
1593
- // 2 bytes for NWK Address + 2 bytes for Profile Id + 1 byte for in Cluster Count
1594
- // + in times 2 for 2 byte Clusters + out Cluster Count + out times 2 for 2 byte Clusters
1595
- const length = (zdo_1.ZDO_MESSAGE_OVERHEAD + 2 + 2 + 1 + (inClusters.length * 2) + 1 + (outClusters.length * 2));
1596
- // sanity check
1597
- if (length > consts_1.EZSP_MAX_FRAME_LENGTH) {
1598
- return [enums_3.EmberStatus.MESSAGE_TOO_LONG, null, null];
1599
- }
1600
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1601
- this.zdoRequestBuffalo.writeUInt16(target);
1602
- this.zdoRequestBuffalo.writeUInt16(profile);
1603
- this.zdoRequestBuffalo.writeUInt8(inClusters.length);
1604
- this.zdoRequestBuffalo.writeListUInt16(inClusters);
1605
- this.zdoRequestBuffalo.writeUInt8(outClusters.length);
1606
- this.zdoRequestBuffalo.writeListUInt16(outClusters);
1607
- logger_1.logger.debug(`~~~> [ZDO MATCH_DESCRIPTORS_REQUEST target=${target} profile=${profile} inClusters=${inClusters} outClusters=${outClusters}]`, NS);
1608
- return this.sendZDORequestBuffer(target, zdo_1.MATCH_DESCRIPTORS_REQUEST, options);
1609
- }
1610
- /**
1611
- * ZDO
1612
- * Device Discovery Functions
1613
- * Request the 16 bit network address of a node whose EUI64 is known.
1614
- *
1615
- * @param target The EUI64 of the node.
1616
- * @param reportKids true to request that the target list their children
1617
- * in the response.
1618
- * @param childStartIndex uint8_t The index of the first child to list in the response.
1619
- * Ignored if @c reportKids is false.
1620
- *
1621
- * @return An ::EmberStatus value.
1622
- * - ::EMBER_SUCCESS - The request was transmitted successfully.
1623
- * - ::EMBER_NO_BUFFERS - Insufficient message buffers were available to construct the request.
1624
- * - ::EMBER_NETWORK_DOWN - The node is not part of a network.
1625
- * - ::EMBER_NETWORK_BUSY - Transmission of the request failed.
1626
- */
1627
- async emberNetworkAddressRequest(target, reportKids, childStartIndex) {
1628
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1629
- this.zdoRequestBuffalo.writeIeeeAddr(target);
1630
- this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
1631
- this.zdoRequestBuffalo.writeUInt8(childStartIndex);
1632
- logger_1.logger.debug(`~~~> [ZDO NETWORK_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
1633
- return this.sendZDORequestBuffer(enums_1.BroadcastAddress.RX_ON_WHEN_IDLE, zdo_1.NETWORK_ADDRESS_REQUEST, enums_3.EmberApsOption.SOURCE_EUI64);
1634
- }
1635
- /**
1636
- * ZDO
1637
- * Device Discovery Functions
1638
- * @brief Request the EUI64 of a node whose 16 bit network address is known.
1639
- *
1640
- * @param target uint16_t The network address of the node.
1641
- * @param reportKids uint8_t true to request that the target list their children
1642
- * in the response.
1643
- * @param childStartIndex uint8_t The index of the first child to list in the response.
1644
- * Ignored if reportKids is false.
1645
- * @param options The options to use when sending the request. See ::emberSendUnicast() for a description.
1646
- *
1647
- * @return An ::EmberStatus value.
1648
- * - ::EMBER_SUCCESS
1649
- * - ::EMBER_NO_BUFFERS
1650
- * - ::EMBER_NETWORK_DOWN
1651
- * - ::EMBER_NETWORK_BUSY
1652
- */
1653
- async emberIeeeAddressRequest(target, reportKids, childStartIndex, options) {
1654
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1655
- this.zdoRequestBuffalo.writeUInt16(target);
1656
- this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
1657
- this.zdoRequestBuffalo.writeUInt8(childStartIndex);
1658
- logger_1.logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
1659
- return this.sendZDORequestBuffer(target, zdo_1.IEEE_ADDRESS_REQUEST, options);
1660
- }
1661
- /**
1662
- * ZDO
1663
- * @param discoveryNodeId uint16_t
1664
- * @param reportKids uint8_t
1665
- * @param childStartIndex uint8_t
1666
- * @param options
1667
- * @param targetNodeIdOfRequest
1668
- */
1669
- async emberIeeeAddressRequestToTarget(discoveryNodeId, reportKids, childStartIndex, options, targetNodeIdOfRequest) {
1670
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1671
- this.zdoRequestBuffalo.writeUInt16(discoveryNodeId);
1672
- this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0);
1673
- this.zdoRequestBuffalo.writeUInt8(childStartIndex);
1674
- logger_1.logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST targetNodeIdOfRequest=${targetNodeIdOfRequest} discoveryNodeId=${discoveryNodeId} `
1675
- + `reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS);
1676
- return this.sendZDORequestBuffer(targetNodeIdOfRequest, zdo_1.IEEE_ADDRESS_REQUEST, options);
1677
- }
1678
- /**
1679
- * ZDO
1680
- *
1681
- * @param target uint16_t
1682
- * @param clusterId uint16_t
1683
- * @param options
1684
- * @returns
1685
- */
1686
- async emberSendZigDevRequestTarget(target, clusterId, options) {
1687
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1688
- this.zdoRequestBuffalo.writeUInt16(target);
1689
- return this.sendZDORequestBuffer(target, clusterId, options);
1690
- }
1691
- /**
1692
- * ZDO
1693
- * @brief Request the specified node to send the simple descriptor for
1694
- * the specified endpoint.
1695
- * The simple descriptor contains information specific
1696
- * to a single endpoint. It describes the application profile identifier,
1697
- * application device identifier, application device version, application flags,
1698
- * application input clusters and application output clusters. It is defined in
1699
- * the ZigBee Application Framework Specification.
1700
- *
1701
- * @param target uint16_t The node of interest.
1702
- * @param targetEndpoint uint8_t The endpoint on the target node whose simple
1703
- * descriptor is desired.
1704
- * @param options The options to use when sending the request. See
1705
- * emberSendUnicast() for a description.
1706
- *
1707
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1708
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1709
- */
1710
- async emberSimpleDescriptorRequest(target, targetEndpoint, options) {
1711
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1712
- this.zdoRequestBuffalo.writeUInt16(target);
1713
- this.zdoRequestBuffalo.writeUInt8(targetEndpoint);
1714
- logger_1.logger.debug(`~~~> [ZDO SIMPLE_DESCRIPTOR_REQUEST target=${target} targetEndpoint=${targetEndpoint}]`, NS);
1715
- return this.sendZDORequestBuffer(target, zdo_1.SIMPLE_DESCRIPTOR_REQUEST, options);
1716
- }
1717
- /**
1718
- * ZDO
1719
- * Common logic used by `emberBindRequest` & `emberUnbindRequest`.
1720
- *
1721
- * @param target
1722
- * @param bindClusterId
1723
- * @param source
1724
- * @param sourceEndpoint
1725
- * @param clusterId
1726
- * @param type
1727
- * @param destination
1728
- * @param groupAddress
1729
- * @param destinationEndpoint
1730
- * @param options
1731
- *
1732
- * @returns An ::EmberStatus value.
1733
- * - ::EMBER_SUCCESS
1734
- * - ::EMBER_NO_BUFFERS
1735
- * - ::EMBER_NETWORK_DOWN
1736
- * - ::EMBER_NETWORK_BUSY
1737
- * @returns APS frame created for the request
1738
- * @returns The tag used on the message.
1739
- */
1740
- async emberSendZigDevBindRequest(target, bindClusterId, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
1741
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1742
- this.zdoRequestBuffalo.writeIeeeAddr(source);
1743
- this.zdoRequestBuffalo.writeUInt8(sourceEndpoint);
1744
- this.zdoRequestBuffalo.writeUInt16(clusterId);
1745
- this.zdoRequestBuffalo.writeUInt8(type);
1746
- switch (type) {
1747
- case zdo_1.UNICAST_BINDING:
1748
- this.zdoRequestBuffalo.writeIeeeAddr(destination);
1749
- this.zdoRequestBuffalo.writeUInt8(destinationEndpoint);
1750
- break;
1751
- case zdo_1.MULTICAST_BINDING:
1752
- this.zdoRequestBuffalo.writeUInt16(groupAddress);
1753
- break;
1754
- default:
1755
- return [enums_3.EmberStatus.ERR_FATAL, null, null];
1756
- }
1757
- return this.sendZDORequestBuffer(target, bindClusterId, options);
1758
- }
1759
- /**
1760
- * ZDO
1761
- * Send a request to create a binding entry with the specified
1762
- * contents on the specified node.
1763
- *
1764
- * @param target The node on which the binding will be created.
1765
- * @param source The source EUI64 in the binding entry.
1766
- * @param sourceEndpoint The source endpoint in the binding entry.
1767
- * @param clusterId The cluster ID in the binding entry.
1768
- * @param type The type of binding, either ::UNICAST_BINDING,
1769
- * ::MULTICAST_BINDING, or ::UNICAST_MANY_TO_ONE_BINDING.
1770
- * ::UNICAST_MANY_TO_ONE_BINDING is an Ember-specific extension
1771
- * and should be used only when the target is an Ember device.
1772
- * @param destination The destination EUI64 in the binding entry for
1773
- * ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
1774
- * @param groupAddress The group address for the ::MULTICAST_BINDING.
1775
- * @param destinationEndpoint The destination endpoint in the binding entry for
1776
- * the ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
1777
- * @param options The options to use when sending the request. See
1778
- * emberSendUnicast() for a description.
1779
- *
1780
- * @returns An ::EmberStatus value.
1781
- * - ::EMBER_SUCCESS
1782
- * - ::EMBER_NO_BUFFERS
1783
- * - ::EMBER_NETWORK_DOWN
1784
- * - ::EMBER_NETWORK_BUSY
1785
- * @returns APS frame created for the request
1786
- * @returns The tag used on the message.
1787
- */
1788
- async emberBindRequest(target, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
1789
- logger_1.logger.debug(`~~~> [ZDO BIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} `
1790
- + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, NS);
1791
- return this.emberSendZigDevBindRequest(target, zdo_1.BIND_REQUEST, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options);
1792
- }
1793
- /**
1794
- * ZDO
1795
- * Send a request to remove a binding entry with the specified
1796
- * contents from the specified node.
1797
- *
1798
- * @param target The node on which the binding will be removed.
1799
- * @param source The source EUI64 in the binding entry.
1800
- * @param sourceEndpoint uint8_t The source endpoint in the binding entry.
1801
- * @param clusterId uint16_t The cluster ID in the binding entry.
1802
- * @param type uint8_t The type of binding, either ::UNICAST_BINDING,
1803
- * ::MULTICAST_BINDING, or ::UNICAST_MANY_TO_ONE_BINDING.
1804
- * ::UNICAST_MANY_TO_ONE_BINDING is an Ember-specific extension
1805
- * and should be used only when the target is an Ember device.
1806
- * @param destination The destination EUI64 in the binding entry for the
1807
- * ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
1808
- * @param groupAddress The group address for the ::MULTICAST_BINDING.
1809
- * @param destinationEndpoint uint8_t The destination endpoint in the binding entry for
1810
- * the ::UNICAST_BINDING or ::UNICAST_MANY_TO_ONE_BINDING.
1811
- * @param options The options to use when sending the request. See
1812
- * emberSendUnicast() for a description.
1813
- *
1814
- * @returns An ::EmberStatus value.
1815
- * - ::EMBER_SUCCESS
1816
- * - ::EMBER_NO_BUFFERS
1817
- * - ::EMBER_NETWORK_DOWN
1818
- * - ::EMBER_NETWORK_BUSY
1819
- * @returns APS frame created for the request
1820
- * @returns The tag used on the message.
1821
- */
1822
- async emberUnbindRequest(target, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options) {
1823
- logger_1.logger.debug(`~~~> [ZDO UNBIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} `
1824
- + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, NS);
1825
- return this.emberSendZigDevBindRequest(target, zdo_1.UNBIND_REQUEST, source, sourceEndpoint, clusterId, type, destination, groupAddress, destinationEndpoint, options);
1826
- }
1827
- /**
1828
- * ZDO
1829
- * Request the specified node to send a list of its active
1830
- * endpoints. An active endpoint is one for which a simple descriptor is
1831
- * available.
1832
- *
1833
- * @param target The node whose active endpoints are desired.
1834
- * @param options The options to use when sending the request. See
1835
- * emberSendUnicast() for a description.
1836
- *
1837
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1838
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1839
- */
1840
- async emberActiveEndpointsRequest(target, options) {
1841
- logger_1.logger.debug(`~~~> [ZDO ACTIVE_ENDPOINTS_REQUEST target=${target}]`, NS);
1842
- return this.emberSendZigDevRequestTarget(target, zdo_1.ACTIVE_ENDPOINTS_REQUEST, options);
1843
- }
1844
- /**
1845
- * ZDO
1846
- * Request the specified node to send its power descriptor.
1847
- * The power descriptor gives a dynamic indication of the power
1848
- * status of the node. It describes current power mode,
1849
- * available power sources, current power source and
1850
- * current power source level. It is defined in the ZigBee
1851
- * Application Framework Specification.
1852
- *
1853
- * @param target The node whose power descriptor is desired.
1854
- * @param options The options to use when sending the request. See
1855
- * emberSendUnicast() for a description.
1856
- *
1857
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1858
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1859
- */
1860
- async emberPowerDescriptorRequest(target, options) {
1861
- logger_1.logger.debug(`~~~> [ZDO POWER_DESCRIPTOR_REQUEST target=${target}]`, NS);
1862
- return this.emberSendZigDevRequestTarget(target, zdo_1.POWER_DESCRIPTOR_REQUEST, options);
1863
- }
1864
- /**
1865
- * ZDO
1866
- * Request the specified node to send its node descriptor.
1867
- * The node descriptor contains information about the capabilities of the ZigBee
1868
- * node. It describes logical type, APS flags, frequency band, MAC capabilities
1869
- * flags, manufacturer code and maximum buffer size. It is defined in the ZigBee
1870
- * Application Framework Specification.
1871
- *
1872
- * @param target The node whose node descriptor is desired.
1873
- * @param options The options to use when sending the request. See
1874
- * emberSendUnicast() for a description.
1875
- *
1876
- * @return An ::EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1877
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1878
- */
1879
- async emberNodeDescriptorRequest(target, options) {
1880
- logger_1.logger.debug(`~~~> [ZDO NODE_DESCRIPTOR_REQUEST target=${target}]`, NS);
1881
- return this.emberSendZigDevRequestTarget(target, zdo_1.NODE_DESCRIPTOR_REQUEST, options);
1882
- }
1883
- /**
1884
- * ZDO
1885
- * Request the specified node to send its LQI (neighbor) table.
1886
- * The response gives PAN ID, EUI64, node ID and cost for each neighbor. The
1887
- * EUI64 is only available if security is enabled. The other fields in the
1888
- * response are set to zero. The response format is defined in the ZigBee Device
1889
- * Profile Specification.
1890
- *
1891
- * @param target The node whose LQI table is desired.
1892
- * @param startIndex uint8_t The index of the first neighbor to include in the
1893
- * response.
1894
- * @param options The options to use when sending the request. See
1895
- * emberSendUnicast() for a description.
1896
- *
1897
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1898
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1899
- */
1900
- async emberLqiTableRequest(target, startIndex, options) {
1901
- logger_1.logger.debug(`~~~> [ZDO LQI_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
1902
- return this.emberTableRequest(zdo_1.LQI_TABLE_REQUEST, target, startIndex, options);
1903
- }
1904
- /**
1905
- * ZDO
1906
- * Request the specified node to send its routing table.
1907
- * The response gives destination node ID, status and many-to-one flags,
1908
- * and the next hop node ID.
1909
- * The response format is defined in the ZigBee Device
1910
- * Profile Specification.
1911
- *
1912
- * @param target The node whose routing table is desired.
1913
- * @param startIndex uint8_t The index of the first route entry to include in the
1914
- * response.
1915
- * @param options The options to use when sending the request. See
1916
- * emberSendUnicast() for a description.
1917
- *
1918
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1919
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1920
- */
1921
- async emberRoutingTableRequest(target, startIndex, options) {
1922
- logger_1.logger.debug(`~~~> [ZDO ROUTING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
1923
- return this.emberTableRequest(zdo_1.ROUTING_TABLE_REQUEST, target, startIndex, options);
1924
- }
1925
- /**
1926
- * ZDO
1927
- * Request the specified node to send its nonvolatile bindings.
1928
- * The response gives source address, source endpoint, cluster ID, destination
1929
- * address and destination endpoint for each binding entry. The response format
1930
- * is defined in the ZigBee Device Profile Specification.
1931
- * Note that bindings that have the Ember-specific ::UNICAST_MANY_TO_ONE_BINDING
1932
- * type are reported as having the standard ::UNICAST_BINDING type.
1933
- *
1934
- * @param target The node whose binding table is desired.
1935
- * @param startIndex uint8_t The index of the first binding entry to include in the
1936
- * response.
1937
- * @param options The options to use when sending the request. See
1938
- * emberSendUnicast() for a description.
1939
- *
1940
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1941
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1942
- */
1943
- async emberBindingTableRequest(target, startIndex, options) {
1944
- logger_1.logger.debug(`~~~> [ZDO BINDING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS);
1945
- return this.emberTableRequest(zdo_1.BINDING_TABLE_REQUEST, target, startIndex, options);
1946
- }
1947
- /**
1948
- * ZDO
1949
- *
1950
- * @param clusterId uint16_t
1951
- * @param target
1952
- * @param startIndex uint8_t
1953
- * @param options
1954
- * @returns
1955
- */
1956
- async emberTableRequest(clusterId, target, startIndex, options) {
1957
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1958
- this.zdoRequestBuffalo.writeUInt8(startIndex);
1959
- return this.sendZDORequestBuffer(target, clusterId, options);
1960
- }
1961
- /**
1962
- * ZDO
1963
- * Request the specified node to remove the specified device from
1964
- * the network. The device to be removed must be the node to which the request
1965
- * is sent or one of its children.
1966
- *
1967
- * @param target The node which will remove the device.
1968
- * @param deviceAddress All zeros if the target is to remove itself from
1969
- * the network or the EUI64 of a child of the target device to remove
1970
- * that child.
1971
- * @param leaveRequestFlags uint8_t A bitmask of leave options.
1972
- * Include ::AND_REJOIN if the target is to rejoin the network immediately after leaving.
1973
- * @param options The options to use when sending the request. See
1974
- * emberSendUnicast() for a description.
1975
- *
1976
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
1977
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
1978
- */
1979
- async emberLeaveRequest(target, deviceAddress, leaveRequestFlags, options) {
1980
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
1981
- this.zdoRequestBuffalo.writeIeeeAddr(deviceAddress);
1982
- this.zdoRequestBuffalo.writeUInt8(leaveRequestFlags);
1983
- logger_1.logger.debug(`~~~> [ZDO LEAVE_REQUEST target=${target} deviceAddress=${deviceAddress} leaveRequestFlags=${leaveRequestFlags}]`, NS);
1984
- return this.sendZDORequestBuffer(target, zdo_1.LEAVE_REQUEST, options);
1985
- }
1986
- /**
1987
- * ZDO
1988
- * Request the specified node to allow or disallow association.
1989
- *
1990
- * @param target The node which will allow or disallow association. The request
1991
- * can be broadcast by using a broadcast address (0xFFFC/0xFFFD/0xFFFF). No
1992
- * response is sent if the request is broadcast.
1993
- * @param duration uint8_t A value of 0x00 disables joining. A value of 0xFF enables
1994
- * joining. Any other value enables joining for that number of seconds.
1995
- * @param authentication uint8_t Controls Trust Center authentication behavior.
1996
- * @param options The options to use when sending the request. See
1997
- * emberSendUnicast() for a description. This parameter is ignored if the target
1998
- * is a broadcast address.
1999
- *
2000
- * @return An EmberStatus value. ::EMBER_SUCCESS, ::EMBER_NO_BUFFERS,
2001
- * ::EMBER_NETWORK_DOWN or ::EMBER_NETWORK_BUSY.
2002
- */
2003
- async emberPermitJoiningRequest(target, duration, authentication, options) {
2004
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
2005
- this.zdoRequestBuffalo.writeUInt8(duration);
2006
- this.zdoRequestBuffalo.writeUInt8(authentication);
2007
- logger_1.logger.debug(`~~~> [ZDO PERMIT_JOINING_REQUEST target=${target} duration=${duration} authentication=${authentication}]`, NS);
2008
- return this.sendZDORequestBuffer(target, zdo_1.PERMIT_JOINING_REQUEST, options);
2009
- }
2010
- /**
2011
- * ZDO
2012
- *
2013
- * @see NWK_UPDATE_REQUEST
2014
- *
2015
- * @param target
2016
- * @param scanChannels uint8_t[]
2017
- * @param duration uint8_t
2018
- * @param count uint8_t
2019
- * @param manager
2020
- */
2021
- async emberNetworkUpdateRequest(target, scanChannels, duration, count, manager, options) {
2022
- this.zdoRequestBuffalo.setPosition(zdo_1.ZDO_MESSAGE_OVERHEAD);
2023
- this.zdoRequestBuffalo.writeUInt32(scanChannels.reduce((a, c) => a + (1 << c), 0)); // to uint32_t
2024
- this.zdoRequestBuffalo.writeUInt8(duration);
2025
- if (count != null) {
2026
- this.zdoRequestBuffalo.writeUInt8(count);
2027
- }
2028
- if (manager != null) {
2029
- this.zdoRequestBuffalo.writeUInt16(manager);
2030
- }
2031
- logger_1.logger.debug(`~~~> [ZDO NWK_UPDATE_REQUEST target=${target} scanChannels=${scanChannels} duration=${duration} count=${count} manager=${manager}]`, NS);
2032
- return this.sendZDORequestBuffer(target, zdo_1.NWK_UPDATE_REQUEST, options);
2033
- }
2034
- async emberScanChannelsRequest(target, scanChannels, duration, count, options) {
2035
- return this.emberNetworkUpdateRequest(target, scanChannels, duration, count, null, options);
2036
- }
2037
- async emberChannelChangeRequest(target, channel, options) {
2038
- return this.emberNetworkUpdateRequest(target, [channel], 0xFE, null, null, options);
2039
- }
2040
- async emberSetActiveChannelsAndNwkManagerIdRequest(target, scanChannels, manager, options) {
2041
- return this.emberNetworkUpdateRequest(target, scanChannels, 0xFF, null, manager, options);
2042
- }
2043
1386
  //---- END Ember ZDO
2044
1387
  //-- START Adapter implementation
2045
1388
  static async isValidPath(path) {
@@ -2057,7 +1400,7 @@ class EmberAdapter extends __1.Adapter {
2057
1400
  }
2058
1401
  static async autoDetectPath() {
2059
1402
  const paths = await serialPortUtils_1.default.find(autoDetectDefinitions);
2060
- paths.sort((a, b) => (a < b) ? -1 : 1);
1403
+ paths.sort((a, b) => (a < b ? -1 : 1));
2061
1404
  return paths.length > 0 ? paths[0] : null;
2062
1405
  }
2063
1406
  async start() {
@@ -2067,34 +1410,30 @@ class EmberAdapter extends __1.Adapter {
2067
1410
  return result;
2068
1411
  }
2069
1412
  async stop() {
2070
- this.requestQueue.stopDispatching();
2071
1413
  await this.ezsp.stop();
2072
1414
  this.initVariables();
2073
1415
  logger_1.logger.info(`======== Ember Adapter Stopped ========`, NS);
2074
1416
  }
2075
1417
  // queued, non-InterPAN
2076
1418
  async getCoordinator() {
2077
- return new Promise((resolve, reject) => {
2078
- this.requestQueue.enqueue(async () => {
2079
- this.checkInterpanLock();
2080
- // in all likelihood this will be retrieved from cache
2081
- const ieeeAddr = (await this.emberGetEui64());
2082
- resolve({
2083
- ieeeAddr,
2084
- networkAddress: ZSpec.COORDINATOR_ADDRESS,
2085
- manufacturerID: DEFAULT_MANUFACTURER_CODE,
2086
- endpoints: endpoints_1.FIXED_ENDPOINTS.map((ep) => {
2087
- return {
2088
- profileID: ep.profileId,
2089
- ID: ep.endpoint,
2090
- deviceID: ep.deviceId,
2091
- inputClusters: ep.inClusterList.slice(), // copy
2092
- outputClusters: ep.outClusterList.slice(), // copy
2093
- };
2094
- }),
2095
- });
2096
- return enums_3.EmberStatus.SUCCESS;
2097
- }, reject);
1419
+ return this.queue.execute(async () => {
1420
+ this.checkInterpanLock();
1421
+ // in all likelihood this will be retrieved from cache
1422
+ const ieeeAddr = await this.emberGetEui64();
1423
+ return {
1424
+ ieeeAddr,
1425
+ networkAddress: ZSpec.COORDINATOR_ADDRESS,
1426
+ manufacturerID: DEFAULT_MANUFACTURER_CODE,
1427
+ endpoints: endpoints_1.FIXED_ENDPOINTS.map((ep) => {
1428
+ return {
1429
+ profileID: ep.profileId,
1430
+ ID: ep.endpoint,
1431
+ deviceID: ep.deviceId,
1432
+ inputClusters: ep.inClusterList.slice(), // copy
1433
+ outputClusters: ep.outClusterList.slice(), // copy
1434
+ };
1435
+ }),
1436
+ };
2098
1437
  });
2099
1438
  }
2100
1439
  async getCoordinatorVersion() {
@@ -2103,7 +1442,7 @@ class EmberAdapter extends __1.Adapter {
2103
1442
  // queued
2104
1443
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2105
1444
  async reset(type) {
2106
- return Promise.reject(new Error("Not supported"));
1445
+ return Promise.reject(new Error('Not supported'));
2107
1446
  // NOTE: although this function is legacy atm, a couple of new untested EZSP functions that could also prove useful:
2108
1447
  // this.ezsp.ezspTokenFactoryReset(true/*excludeOutgoingFC*/, true/*excludeBootCounter*/);
2109
1448
  // this.ezsp.ezspResetNode()
@@ -2114,103 +1453,86 @@ class EmberAdapter extends __1.Adapter {
2114
1453
  // queued
2115
1454
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2116
1455
  async backup(ieeeAddressesInDatabase) {
2117
- return new Promise((resolve, reject) => {
2118
- this.requestQueue.enqueue(async () => {
2119
- // grab fresh version here, bypass cache
2120
- const [netStatus, , netParams] = (await this.ezsp.ezspGetNetworkParameters());
2121
- if (netStatus !== enums_3.EmberStatus.SUCCESS) {
2122
- logger_1.logger.error(`[BACKUP] Failed to get network parameters.`, NS);
2123
- return netStatus;
2124
- }
2125
- // update cache
2126
- this.networkCache.parameters = netParams;
2127
- this.networkCache.eui64 = (await this.ezsp.ezspGetEui64());
2128
- const [netKeyStatus, netKeyInfo] = (await this.ezsp.ezspGetNetworkKeyInfo());
2129
- if (netKeyStatus !== enums_3.SLStatus.OK) {
2130
- logger_1.logger.error(`[BACKUP] Failed to get network keys info.`, NS);
2131
- return ((netKeyStatus === enums_3.SLStatus.BUSY) || (netKeyStatus === enums_3.SLStatus.NOT_READY))
2132
- ? enums_3.EmberStatus.NETWORK_BUSY : enums_3.EmberStatus.ERR_FATAL; // allow retry on statuses that should be temporary
2133
- }
2134
- if (!netKeyInfo.networkKeySet) {
2135
- throw new Error(`[BACKUP] No network key set.`);
2136
- }
2137
- let keyList = [];
2138
- if (this.stackConfig.KEY_TABLE_SIZE > 0) {
2139
- keyList = (await this.exportLinkKeys());
2140
- }
2141
- // XXX: this only makes sense on stop (if that), not hourly/on start, plus network needs to be at near-standstill @see AN1387
2142
- // const tokensBuf = (await EmberTokensManager.saveTokens(
2143
- // this.ezsp,
2144
- // Buffer.from(this.networkCache.eui64.substring(2/*0x*/), 'hex').reverse()
2145
- // ));
2146
- let context = (0, initters_1.initSecurityManagerContext)();
2147
- context.coreKeyType = enums_3.SecManKeyType.TC_LINK;
2148
- const [tcLinkKey, tclkStatus] = (await this.ezsp.ezspExportKey(context));
2149
- if (tclkStatus !== enums_3.SLStatus.OK) {
2150
- throw new Error(`[BACKUP] Failed to export TC Link Key with status=${enums_3.SLStatus[tclkStatus]}.`);
2151
- }
2152
- context = (0, initters_1.initSecurityManagerContext)(); // make sure it's back to zeroes
2153
- context.coreKeyType = enums_3.SecManKeyType.NETWORK;
2154
- context.keyIndex = 0;
2155
- const [networkKey, nkStatus] = (await this.ezsp.ezspExportKey(context));
2156
- if (nkStatus !== enums_3.SLStatus.OK) {
2157
- throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_3.SLStatus[nkStatus]}.`);
2158
- }
2159
- const zbChannels = Array.from(Array(consts_2.EMBER_NUM_802_15_4_CHANNELS), (e, i) => i + consts_2.EMBER_MIN_802_15_4_CHANNEL_NUMBER);
2160
- resolve({
2161
- networkOptions: {
2162
- panId: netParams.panId, // uint16_t
2163
- extendedPanId: Buffer.from(netParams.extendedPanId),
2164
- channelList: zbChannels.map((c) => ((2 ** c) & netParams.channels) ? c : null).filter((x) => x),
2165
- networkKey: networkKey.contents,
2166
- networkKeyDistribute: false,
2167
- },
2168
- logicalChannel: netParams.radioChannel,
2169
- networkKeyInfo: {
2170
- sequenceNumber: netKeyInfo.networkKeySequenceNumber,
2171
- frameCounter: netKeyInfo.networkKeyFrameCounter,
1456
+ return this.queue.execute(async () => {
1457
+ // grab fresh version here, bypass cache
1458
+ const [netStatus, , netParams] = await this.ezsp.ezspGetNetworkParameters();
1459
+ if (netStatus !== enums_1.SLStatus.OK) {
1460
+ throw new Error(`[BACKUP] Failed to get network parameters with status=${enums_1.SLStatus[netStatus]}.`);
1461
+ }
1462
+ // update cache
1463
+ this.networkCache.parameters = netParams;
1464
+ this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
1465
+ const [netKeyStatus, netKeyInfo] = await this.ezsp.ezspGetNetworkKeyInfo();
1466
+ if (netKeyStatus !== enums_1.SLStatus.OK) {
1467
+ throw new Error(`[BACKUP] Failed to get network keys info with status=${enums_1.SLStatus[netKeyStatus]}.`);
1468
+ }
1469
+ if (!netKeyInfo.networkKeySet) {
1470
+ throw new Error(`[BACKUP] No network key set.`);
1471
+ }
1472
+ const keyList = ALLOW_APP_KEY_REQUESTS ? await this.exportLinkKeys() : [];
1473
+ let context = (0, initters_1.initSecurityManagerContext)();
1474
+ context.coreKeyType = enums_1.SecManKeyType.TC_LINK;
1475
+ const [tclkStatus, tcLinkKey] = await this.ezsp.ezspExportKey(context);
1476
+ if (tclkStatus !== enums_1.SLStatus.OK) {
1477
+ throw new Error(`[BACKUP] Failed to export TC Link Key with status=${enums_1.SLStatus[tclkStatus]}.`);
1478
+ }
1479
+ context = (0, initters_1.initSecurityManagerContext)(); // make sure it's back to zeroes
1480
+ context.coreKeyType = enums_1.SecManKeyType.NETWORK;
1481
+ context.keyIndex = 0;
1482
+ const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
1483
+ if (nkStatus !== enums_1.SLStatus.OK) {
1484
+ throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_1.SLStatus[nkStatus]}.`);
1485
+ }
1486
+ const zbChannels = Array.from(Array(consts_1.EMBER_NUM_802_15_4_CHANNELS), (e, i) => i + consts_1.EMBER_MIN_802_15_4_CHANNEL_NUMBER);
1487
+ return {
1488
+ networkOptions: {
1489
+ panId: netParams.panId, // uint16_t
1490
+ extendedPanId: Buffer.from(netParams.extendedPanId),
1491
+ channelList: zbChannels.map((c) => ((2 ** c) & netParams.channels ? c : null)).filter((x) => x),
1492
+ networkKey: networkKey.contents,
1493
+ networkKeyDistribute: false,
1494
+ },
1495
+ logicalChannel: netParams.radioChannel,
1496
+ networkKeyInfo: {
1497
+ sequenceNumber: netKeyInfo.networkKeySequenceNumber,
1498
+ frameCounter: netKeyInfo.networkKeyFrameCounter,
1499
+ },
1500
+ securityLevel: consts_1.SECURITY_LEVEL_Z3,
1501
+ networkUpdateId: netParams.nwkUpdateId,
1502
+ coordinatorIeeeAddress: Buffer.from(this.networkCache.eui64.substring(2) /*take out 0x*/, 'hex').reverse(),
1503
+ devices: keyList.map((key) => ({
1504
+ networkAddress: null, // not used for restore, no reason to make NCP calls for nothing
1505
+ ieeeAddress: Buffer.from(key.deviceEui64.substring(2) /*take out 0x*/, 'hex').reverse(),
1506
+ isDirectChild: false, // not used
1507
+ linkKey: {
1508
+ key: key.key.contents,
1509
+ rxCounter: key.incomingFrameCounter,
1510
+ txCounter: key.outgoingFrameCounter,
2172
1511
  },
2173
- securityLevel: consts_2.SECURITY_LEVEL_Z3,
2174
- networkUpdateId: netParams.nwkUpdateId,
2175
- coordinatorIeeeAddress: Buffer.from(this.networkCache.eui64.substring(2) /*take out 0x*/, 'hex').reverse(),
2176
- devices: keyList.map((key) => ({
2177
- networkAddress: null, // not used for restore, no reason to make NCP calls for nothing
2178
- ieeeAddress: Buffer.from(key.deviceEui64.substring(2) /*take out 0x*/, 'hex').reverse(),
2179
- isDirectChild: false, // not used
2180
- linkKey: {
2181
- key: key.key.contents,
2182
- rxCounter: key.incomingFrameCounter,
2183
- txCounter: key.outgoingFrameCounter,
2184
- },
2185
- })),
2186
- ezsp: {
2187
- version: this.version.ezsp,
2188
- hashed_tclk: tcLinkKey.contents,
2189
- // tokens: tokensBuf.toString('hex'),
2190
- // altNetworkKey: altNetworkKey.contents,
2191
- }
2192
- });
2193
- return enums_3.EmberStatus.SUCCESS;
2194
- }, reject, true);
1512
+ })),
1513
+ ezsp: {
1514
+ version: this.version.ezsp,
1515
+ hashed_tclk: tcLinkKey.contents,
1516
+ // tokens: tokensBuf.toString('hex'),
1517
+ // altNetworkKey: altNetworkKey.contents,
1518
+ },
1519
+ };
2195
1520
  });
2196
1521
  }
2197
1522
  // queued, non-InterPAN
2198
1523
  async getNetworkParameters() {
2199
- return new Promise((resolve, reject) => {
2200
- this.requestQueue.enqueue(async () => {
2201
- this.checkInterpanLock();
2202
- // first call will cache for the others, but in all likelihood, it will all be from freshly cached after init
2203
- // since Controller caches this also.
2204
- const channel = (await this.emberGetRadioChannel());
2205
- const panID = (await this.emberGetPanId());
2206
- const extendedPanID = (await this.emberGetExtendedPanId());
2207
- resolve({
2208
- panID,
2209
- extendedPanID: parseInt(Buffer.from(extendedPanID).toString('hex'), 16),
2210
- channel,
2211
- });
2212
- return enums_3.EmberStatus.SUCCESS;
2213
- }, reject);
1524
+ return this.queue.execute(async () => {
1525
+ this.checkInterpanLock();
1526
+ // first call will cache for the others, but in all likelihood, it will all be from freshly cached after init
1527
+ // since Controller caches this also.
1528
+ const channel = await this.emberGetRadioChannel();
1529
+ const panID = await this.emberGetPanId();
1530
+ const extendedPanID = await this.emberGetExtendedPanId();
1531
+ return {
1532
+ panID,
1533
+ extendedPanID: parseInt(Buffer.from(extendedPanID).toString('hex'), 16),
1534
+ channel,
1535
+ };
2214
1536
  });
2215
1537
  }
2216
1538
  async supportsChangeChannel() {
@@ -2218,38 +1540,44 @@ class EmberAdapter extends __1.Adapter {
2218
1540
  }
2219
1541
  // queued
2220
1542
  async changeChannel(newChannel) {
2221
- return new Promise((resolve, reject) => {
2222
- this.requestQueue.enqueue(async () => {
2223
- this.checkInterpanLock();
2224
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2225
- const [status, apsFrame, messageTag] = (await this.emberChannelChangeRequest(enums_1.BroadcastAddress.SLEEPY, newChannel, DEFAULT_APS_OPTIONS));
2226
- if (status !== enums_3.EmberStatus.SUCCESS) {
2227
- logger_1.logger.error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${enums_3.EmberStatus[status]}.`, NS);
2228
- return status;
2229
- }
2230
- await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED }, DEFAULT_NETWORK_REQUEST_TIMEOUT * 2, // observed to ~9sec
2231
- '[ZDO] Change Channel');
2232
- resolve();
2233
- return enums_3.EmberStatus.SUCCESS;
2234
- }, reject);
1543
+ return this.queue.execute(async () => {
1544
+ this.checkInterpanLock();
1545
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildChannelChangeRequest(newChannel, null);
1546
+ const [status] = await this.sendZDORequest(ZSpec.BroadcastAddress.SLEEPY, Zdo.ClusterId.NWK_UPDATE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1547
+ if (status !== enums_1.SLStatus.OK) {
1548
+ throw new Error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${enums_1.SLStatus[status]}.`);
1549
+ }
1550
+ await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED }, DEFAULT_NETWORK_REQUEST_TIMEOUT * 2, // observed to ~9sec
1551
+ '[ZDO] Change Channel');
1552
+ });
1553
+ }
1554
+ // queued
1555
+ async scanChannels(networkAddress, channels, duration, count) {
1556
+ return this.queue.execute(async () => {
1557
+ this.checkInterpanLock();
1558
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildScanChannelsRequest(channels, duration, count);
1559
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.NWK_UPDATE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1560
+ if (status !== enums_1.SLStatus.OK) {
1561
+ throw new Error(`[ZDO] Failed to scan channels '${channels}' on '${networkAddress} with status=${enums_1.SLStatus[status]}.`);
1562
+ }
1563
+ const result = await this.oneWaitress.startWaitingFor({
1564
+ target: networkAddress,
1565
+ apsFrame,
1566
+ responseClusterId: Zdo.ClusterId.NWK_UPDATE_RESPONSE,
1567
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT + (((2 ** duration + 1) * (16 * 960)) / 1000) * count * channels.length); // time for scan
1568
+ return result;
2235
1569
  });
2236
1570
  }
2237
1571
  // queued
2238
1572
  async setTransmitPower(value) {
2239
1573
  if (typeof value !== 'number') {
2240
- logger_1.logger.error(`Tried to set transmit power to non-number. Value ${value} of type ${typeof value}.`, NS);
2241
- return;
1574
+ throw new Error(`Tried to set transmit power to non-number. Value ${value} of type ${typeof value}.`);
2242
1575
  }
2243
- return new Promise((resolve, reject) => {
2244
- this.requestQueue.enqueue(async () => {
2245
- const status = await this.ezsp.ezspSetRadioPower(value);
2246
- if (status !== enums_3.EmberStatus.SUCCESS) {
2247
- logger_1.logger.error(`Failed to set transmit power to ${value} status=${enums_3.EmberStatus[status]}.`, NS);
2248
- return status;
2249
- }
2250
- resolve();
2251
- return enums_3.EmberStatus.SUCCESS;
2252
- }, reject);
1576
+ return this.queue.execute(async () => {
1577
+ const status = await this.ezsp.ezspSetRadioPower(value);
1578
+ if (status !== enums_1.SLStatus.OK) {
1579
+ throw new Error(`Failed to set transmit power to ${value} status=${enums_1.SLStatus[status]}.`);
1580
+ }
2253
1581
  });
2254
1582
  }
2255
1583
  // queued
@@ -2258,47 +1586,41 @@ class EmberAdapter extends __1.Adapter {
2258
1586
  throw new Error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}'; no code given.`);
2259
1587
  }
2260
1588
  // codes with CRC, check CRC before sending to NCP, otherwise let NCP handle
2261
- if (consts_2.EMBER_INSTALL_CODE_SIZES.indexOf(key.length) !== -1) {
1589
+ if (consts_1.EMBER_INSTALL_CODE_SIZES.indexOf(key.length) !== -1) {
2262
1590
  // Reverse the bits in a byte (uint8_t)
2263
1591
  const reverse = (b) => {
2264
- return (((b * 0x0802 & 0x22110) | (b * 0x8020 & 0x88440)) * 0x10101 >> 16) & 0xFF;
1592
+ return (((((b * 0x0802) & 0x22110) | ((b * 0x8020) & 0x88440)) * 0x10101) >> 16) & 0xff;
2265
1593
  };
2266
- let crc = 0xFFFF; // uint16_t
1594
+ let crc = 0xffff; // uint16_t
2267
1595
  // Compute the CRC and verify that it matches.
2268
1596
  // The bit reversals, byte swap, and ones' complement are due to differences between halCommonCrc16 and the Smart Energy version.
2269
- for (let index = 0; index < (key.length - consts_2.EMBER_INSTALL_CODE_CRC_SIZE); index++) {
1597
+ for (let index = 0; index < key.length - consts_1.EMBER_INSTALL_CODE_CRC_SIZE; index++) {
2270
1598
  crc = (0, math_1.halCommonCrc16)(reverse(key[index]), crc);
2271
1599
  }
2272
- crc = (~(0, math_1.highLowToInt)(reverse((0, math_1.lowByte)(crc)), reverse((0, math_1.highByte)(crc)))) & 0xFFFF;
2273
- if (key[key.length - consts_2.EMBER_INSTALL_CODE_CRC_SIZE] !== (0, math_1.lowByte)(crc)
2274
- || key[key.length - consts_2.EMBER_INSTALL_CODE_CRC_SIZE + 1] !== (0, math_1.highByte)(crc)) {
1600
+ crc = ~(0, math_1.highLowToInt)(reverse((0, math_1.lowByte)(crc)), reverse((0, math_1.highByte)(crc))) & 0xffff;
1601
+ if (key[key.length - consts_1.EMBER_INSTALL_CODE_CRC_SIZE] !== (0, math_1.lowByte)(crc) ||
1602
+ key[key.length - consts_1.EMBER_INSTALL_CODE_CRC_SIZE + 1] !== (0, math_1.highByte)(crc)) {
2275
1603
  throw new Error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}'; invalid code CRC.`);
2276
1604
  }
2277
1605
  else {
2278
1606
  logger_1.logger.debug(`[ADD INSTALL CODE] CRC validated for '${ieeeAddress}'.`, NS);
2279
1607
  }
2280
1608
  }
2281
- return new Promise((resolve, reject) => {
2282
- this.requestQueue.enqueue(async () => {
2283
- // Compute the key from the install code and CRC.
2284
- const [aesStatus, keyContents] = (await this.emberAesHashSimple(key));
2285
- if (aesStatus !== enums_3.EmberStatus.SUCCESS) {
2286
- logger_1.logger.error(`[ADD INSTALL CODE] Failed AES hash for '${ieeeAddress}' with status=${enums_3.EmberStatus[aesStatus]}.`, NS);
2287
- return aesStatus;
2288
- }
2289
- // Add the key to the transient key table.
2290
- // This will be used while the DUT joins.
2291
- const impStatus = (await this.ezsp.ezspImportTransientKey(ieeeAddress, { contents: keyContents }, enums_3.SecManFlag.NONE));
2292
- if (impStatus == enums_3.SLStatus.OK) {
2293
- logger_1.logger.debug(`[ADD INSTALL CODE] Success for '${ieeeAddress}'.`, NS);
2294
- }
2295
- else {
2296
- logger_1.logger.error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${enums_3.SLStatus[impStatus]}.`, NS);
2297
- return enums_3.EmberStatus.ERR_FATAL;
2298
- }
2299
- resolve();
2300
- return enums_3.EmberStatus.SUCCESS;
2301
- }, reject);
1609
+ return this.queue.execute(async () => {
1610
+ // Compute the key from the install code and CRC.
1611
+ const [aesStatus, keyContents] = await this.emberAesHashSimple(key);
1612
+ if (aesStatus !== enums_1.SLStatus.OK) {
1613
+ throw new Error(`[ADD INSTALL CODE] Failed AES hash for '${ieeeAddress}' with status=${enums_1.SLStatus[aesStatus]}.`);
1614
+ }
1615
+ // Add the key to the transient key table.
1616
+ // This will be used while the DUT joins.
1617
+ const impStatus = await this.ezsp.ezspImportTransientKey(ieeeAddress, { contents: keyContents });
1618
+ if (impStatus == enums_1.SLStatus.OK) {
1619
+ logger_1.logger.debug(`[ADD INSTALL CODE] Success for '${ieeeAddress}'.`, NS);
1620
+ }
1621
+ else {
1622
+ throw new Error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${enums_1.SLStatus[impStatus]}.`);
1623
+ }
2302
1624
  });
2303
1625
  }
2304
1626
  /** WARNING: Adapter impl. Starts timer immediately upon returning */
@@ -2313,7 +1635,7 @@ class EmberAdapter extends __1.Adapter {
2313
1635
  sourceEndpoint: sourceEndpointInfo.endpoint,
2314
1636
  destinationEndpoint: endpoint,
2315
1637
  groupId: 0,
2316
- options: enums_3.EmberApsOption.NONE,
1638
+ options: enums_1.EmberApsOption.NONE,
2317
1639
  },
2318
1640
  zclSequence: transactionSequenceNumber,
2319
1641
  commandIdentifier,
@@ -2328,18 +1650,15 @@ class EmberAdapter extends __1.Adapter {
2328
1650
  async permitJoin(seconds, networkAddress) {
2329
1651
  const preJoining = async () => {
2330
1652
  if (seconds) {
2331
- const plaintextKey = { contents: Buffer.from(consts_2.ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY) };
2332
- const impKeyStatus = (await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey, enums_3.SecManFlag.NONE));
2333
- if (impKeyStatus !== enums_3.SLStatus.OK) {
2334
- logger_1.logger.error(`[ZDO] Failed import transient key with status=${enums_3.SLStatus[impKeyStatus]}.`, NS);
2335
- return enums_3.EmberStatus.ERR_FATAL;
1653
+ const plaintextKey = { contents: Buffer.from(consts_1.ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY) };
1654
+ const impKeyStatus = await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey);
1655
+ if (impKeyStatus !== enums_1.SLStatus.OK) {
1656
+ throw new Error(`[ZDO] Failed import transient key with status=${enums_1.SLStatus[impKeyStatus]}.`);
2336
1657
  }
2337
- const setJPstatus = (await this.emberSetJoinPolicy(enums_3.EmberJoinDecision.USE_PRECONFIGURED_KEY));
2338
- if (setJPstatus !== enums_3.EzspStatus.SUCCESS) {
2339
- logger_1.logger.error(`[ZDO] Failed set join policy with status=${enums_3.EzspStatus[setJPstatus]}.`, NS);
2340
- return enums_3.EmberStatus.ERR_FATAL;
1658
+ const setJPstatus = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY);
1659
+ if (setJPstatus !== enums_1.SLStatus.OK) {
1660
+ throw new Error(`[ZDO] Failed set join policy with status=${enums_1.SLStatus[setJPstatus]}.`);
2341
1661
  }
2342
- return enums_3.EmberStatus.SUCCESS;
2343
1662
  }
2344
1663
  else {
2345
1664
  if (this.manufacturerCode !== DEFAULT_MANUFACTURER_CODE) {
@@ -2348,308 +1667,243 @@ class EmberAdapter extends __1.Adapter {
2348
1667
  this.manufacturerCode = DEFAULT_MANUFACTURER_CODE;
2349
1668
  }
2350
1669
  await this.ezsp.ezspClearTransientLinkKeys();
2351
- const setJPstatus = (await this.emberSetJoinPolicy(enums_3.EmberJoinDecision.ALLOW_REJOINS_ONLY));
2352
- if (setJPstatus !== enums_3.EzspStatus.SUCCESS) {
2353
- logger_1.logger.error(`[ZDO] Failed set join policy for with status=${enums_3.EzspStatus[setJPstatus]}.`, NS);
2354
- return enums_3.EmberStatus.ERR_FATAL;
1670
+ const setJPstatus = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.ALLOW_REJOINS_ONLY);
1671
+ if (setJPstatus !== enums_1.SLStatus.OK) {
1672
+ throw new Error(`[ZDO] Failed set join policy for with status=${enums_1.SLStatus[setJPstatus]}.`);
2355
1673
  }
2356
- return enums_3.EmberStatus.SUCCESS;
2357
1674
  }
2358
1675
  };
2359
1676
  if (networkAddress) {
2360
1677
  // specific device that is not `Coordinator`
2361
- return new Promise((resolve, reject) => {
2362
- this.requestQueue.enqueue(async () => {
2363
- this.checkInterpanLock();
2364
- const pjStatus = (await preJoining());
2365
- if (pjStatus !== enums_3.EmberStatus.SUCCESS) {
2366
- logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${enums_3.EmberStatus[pjStatus]}.`, NS);
2367
- return pjStatus;
2368
- }
2369
- // `authentication`: TC significance always 1 (zb specs)
2370
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2371
- const [status, apsFrame, messageTag] = (await this.emberPermitJoiningRequest(networkAddress, seconds, 1, 0));
2372
- if (status !== enums_3.EmberStatus.SUCCESS) {
2373
- logger_1.logger.error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${enums_3.EmberStatus[status]}.`, NS);
2374
- return status;
2375
- }
2376
- (await this.oneWaitress.startWaitingFor({
2377
- target: networkAddress,
2378
- apsFrame,
2379
- responseClusterId: zdo_1.PERMIT_JOINING_RESPONSE,
2380
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2381
- resolve();
2382
- return enums_3.EmberStatus.SUCCESS;
2383
- }, reject);
1678
+ return this.queue.execute(async () => {
1679
+ this.checkInterpanLock();
1680
+ await preJoining();
1681
+ // `authentication`: TC significance always 1 (zb specs)
1682
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildPermitJoining(seconds, 1, []);
1683
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.PERMIT_JOINING_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1684
+ if (status !== enums_1.SLStatus.OK) {
1685
+ throw new Error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${enums_1.SLStatus[status]}.`);
1686
+ }
1687
+ await this.oneWaitress.startWaitingFor({
1688
+ target: networkAddress,
1689
+ apsFrame,
1690
+ responseClusterId: Zdo.ClusterId.PERMIT_JOINING_RESPONSE,
1691
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2384
1692
  });
2385
1693
  }
2386
1694
  else {
2387
1695
  // coordinator-only, or all
2388
- return new Promise((resolve, reject) => {
2389
- this.requestQueue.enqueue(async () => {
2390
- this.checkInterpanLock();
2391
- const pjStatus = (await preJoining());
2392
- if (pjStatus !== enums_3.EmberStatus.SUCCESS) {
2393
- logger_1.logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${enums_3.EmberStatus[pjStatus]}.`, NS);
2394
- return pjStatus;
2395
- }
2396
- // local permit join if `Coordinator`-only requested, else local + broadcast
2397
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2398
- const [status, apsFrame, messageTag] = (await this.emberPermitJoining(seconds, (networkAddress === ZSpec.COORDINATOR_ADDRESS) ? false : true));
2399
- if (status !== enums_3.EmberStatus.SUCCESS) {
2400
- logger_1.logger.error(`[ZDO] Failed permit joining request with status=${enums_3.EmberStatus[status]}.`, NS);
2401
- return status;
2402
- }
2403
- // NOTE: because Z2M is refreshing the permit join duration early to prevent it from closing
2404
- // (every 200sec, even if only opened for 254sec), we can't wait for the stack opened status,
2405
- // as it won't trigger again if already opened... so instead we assume it worked
2406
- // NOTE2: with EZSP, 255=forever, and 254=max, but since upstream logic uses fixed 254 with interval refresh,
2407
- // we can't simply bypass upstream calls if called for "forever" to prevent useless NCP calls (3-4 each time),
2408
- // until called with 0 (disable), since we don't know if it was requested for forever or not...
2409
- // TLDR: upstream logic change required to allow this
2410
- // if (seconds) {
2411
- // await this.oneWaitress.startWaitingForEvent(
2412
- // {eventName: OneWaitressEvents.STACK_STATUS_NETWORK_OPENED},
2413
- // DEFAULT_ZCL_REQUEST_TIMEOUT,
2414
- // '[ZDO] Permit Joining',
2415
- // );
2416
- // } else {
2417
- // // NOTE: CLOSED stack status is not triggered if the network was not OPENED in the first place, so don't wait for it
2418
- // // same kind of problem as described above (upstream always tries to close after start, but EZSP already is)
2419
- // }
2420
- resolve();
2421
- return enums_3.EmberStatus.SUCCESS;
2422
- }, reject);
1696
+ return this.queue.execute(async () => {
1697
+ this.checkInterpanLock();
1698
+ await preJoining();
1699
+ // local permit join if `Coordinator`-only requested, else local + broadcast
1700
+ const [status] = await this.emberPermitJoining(seconds, networkAddress === ZSpec.COORDINATOR_ADDRESS ? false : true);
1701
+ if (status !== enums_1.SLStatus.OK) {
1702
+ throw new Error(`[ZDO] Failed permit joining request with status=${enums_1.SLStatus[status]}.`);
1703
+ }
1704
+ // NOTE: because Z2M is refreshing the permit join duration early to prevent it from closing
1705
+ // (every 200sec, even if only opened for 254sec), we can't wait for the stack opened status,
1706
+ // as it won't trigger again if already opened... so instead we assume it worked
1707
+ // NOTE2: with EZSP, 255=forever, and 254=max, but since upstream logic uses fixed 254 with interval refresh,
1708
+ // we can't simply bypass upstream calls if called for "forever" to prevent useless NCP calls (3-4 each time),
1709
+ // until called with 0 (disable), since we don't know if it was requested for forever or not...
1710
+ // TLDR: upstream logic change required to allow this
1711
+ // if (seconds) {
1712
+ // await this.oneWaitress.startWaitingForEvent(
1713
+ // {eventName: OneWaitressEvents.STACK_STATUS_NETWORK_OPENED},
1714
+ // DEFAULT_ZCL_REQUEST_TIMEOUT,
1715
+ // '[ZDO] Permit Joining',
1716
+ // );
1717
+ // } else {
1718
+ // // NOTE: CLOSED stack status is not triggered if the network was not OPENED in the first place, so don't wait for it
1719
+ // // same kind of problem as described above (upstream always tries to close after start, but EZSP already is)
1720
+ // }
2423
1721
  });
2424
1722
  }
2425
1723
  }
2426
1724
  // queued, non-InterPAN
2427
1725
  async lqi(networkAddress) {
2428
- const neighbors = [];
2429
- const request = async (startIndex) => {
2430
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2431
- const [reqStatus, apsFrame, messageTag] = (await this.emberLqiTableRequest(networkAddress, startIndex, DEFAULT_APS_OPTIONS));
2432
- if (reqStatus !== enums_3.EmberStatus.SUCCESS) {
2433
- logger_1.logger.error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${enums_3.EmberStatus[reqStatus]}.`, NS);
2434
- return [reqStatus, null, null];
2435
- }
2436
- const result = (await this.oneWaitress.startWaitingFor({
2437
- target: networkAddress,
2438
- apsFrame,
2439
- responseClusterId: zdo_1.LQI_TABLE_RESPONSE,
2440
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2441
- for (const entry of result.entryList) {
2442
- neighbors.push({
2443
- ieeeAddr: entry.eui64,
2444
- networkAddress: entry.nodeId,
2445
- linkquality: entry.lqi,
2446
- relationship: entry.relationship,
2447
- depth: entry.depth,
2448
- });
2449
- }
2450
- return [enums_3.EmberStatus.SUCCESS, result.neighborTableEntries, result.entryList.length];
2451
- };
2452
- return new Promise((resolve, reject) => {
2453
- this.requestQueue.enqueue(async () => {
2454
- this.checkInterpanLock();
2455
- let [status, tableEntries, entryCount] = (await request(0));
2456
- if (status !== enums_3.EmberStatus.SUCCESS) {
2457
- return status;
1726
+ return this.queue.execute(async () => {
1727
+ this.checkInterpanLock();
1728
+ const neighbors = [];
1729
+ const request = async (startIndex) => {
1730
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildLqiTableRequest(startIndex);
1731
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LQI_TABLE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1732
+ if (status !== enums_1.SLStatus.OK) {
1733
+ throw new Error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${enums_1.SLStatus[status]}.`);
2458
1734
  }
2459
- const size = tableEntries;
2460
- let nextStartIndex = entryCount;
2461
- while (neighbors.length < size) {
2462
- [status, tableEntries, entryCount] = (await request(nextStartIndex));
2463
- if (status !== enums_3.EmberStatus.SUCCESS) {
2464
- return status;
2465
- }
2466
- nextStartIndex += entryCount;
1735
+ const result = await this.oneWaitress.startWaitingFor({
1736
+ target: networkAddress,
1737
+ apsFrame,
1738
+ responseClusterId: Zdo.ClusterId.LQI_TABLE_RESPONSE,
1739
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
1740
+ for (const entry of result.entryList) {
1741
+ neighbors.push({
1742
+ ieeeAddr: entry.eui64,
1743
+ networkAddress: entry.nwkAddress,
1744
+ linkquality: entry.lqi,
1745
+ relationship: entry.relationship,
1746
+ depth: entry.depth,
1747
+ });
2467
1748
  }
2468
- resolve({ neighbors });
2469
- return status;
2470
- }, reject);
1749
+ return [result.neighborTableEntries, result.entryList.length];
1750
+ };
1751
+ let [tableEntries, entryCount] = await request(0);
1752
+ const size = tableEntries;
1753
+ let nextStartIndex = entryCount;
1754
+ while (neighbors.length < size) {
1755
+ [tableEntries, entryCount] = await request(nextStartIndex);
1756
+ nextStartIndex += entryCount;
1757
+ }
1758
+ return { neighbors };
2471
1759
  });
2472
1760
  }
2473
1761
  // queued, non-InterPAN
2474
1762
  async routingTable(networkAddress) {
2475
- const table = [];
2476
- const request = async (startIndex) => {
2477
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2478
- const [reqStatus, apsFrame, messageTag] = (await this.emberRoutingTableRequest(networkAddress, startIndex, DEFAULT_APS_OPTIONS));
2479
- if (reqStatus !== enums_3.EmberStatus.SUCCESS) {
2480
- logger_1.logger.error(`[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${enums_3.EmberStatus[reqStatus]}.`, NS);
2481
- return [reqStatus, null, null];
2482
- }
2483
- const result = (await this.oneWaitress.startWaitingFor({
2484
- target: networkAddress,
2485
- apsFrame,
2486
- responseClusterId: zdo_1.ROUTING_TABLE_RESPONSE,
2487
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2488
- for (const entry of result.entryList) {
2489
- table.push({
2490
- destinationAddress: entry.destinationAddress,
2491
- status: RoutingTableStatus[entry.status], // get str value from enum to satisfy upstream's needs
2492
- nextHop: entry.nextHopAddress,
2493
- });
2494
- }
2495
- return [enums_3.EmberStatus.SUCCESS, result.routingTableEntries, result.entryList.length];
2496
- };
2497
- return new Promise((resolve, reject) => {
2498
- this.requestQueue.enqueue(async () => {
2499
- this.checkInterpanLock();
2500
- let [status, tableEntries, entryCount] = (await request(0));
2501
- if (status !== enums_3.EmberStatus.SUCCESS) {
2502
- return status;
1763
+ return this.queue.execute(async () => {
1764
+ this.checkInterpanLock();
1765
+ const table = [];
1766
+ const request = async (startIndex) => {
1767
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildRoutingTableRequest(startIndex);
1768
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ROUTING_TABLE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1769
+ if (status !== enums_1.SLStatus.OK) {
1770
+ throw new Error(`[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${enums_1.SLStatus[status]}.`);
2503
1771
  }
2504
- const size = tableEntries;
2505
- let nextStartIndex = entryCount;
2506
- while (table.length < size) {
2507
- [status, tableEntries, entryCount] = (await request(nextStartIndex));
2508
- if (status !== enums_3.EmberStatus.SUCCESS) {
2509
- return status;
2510
- }
2511
- nextStartIndex += entryCount;
1772
+ const result = await this.oneWaitress.startWaitingFor({
1773
+ target: networkAddress,
1774
+ apsFrame,
1775
+ responseClusterId: Zdo.ClusterId.ROUTING_TABLE_RESPONSE,
1776
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
1777
+ for (const entry of result.entryList) {
1778
+ table.push({
1779
+ destinationAddress: entry.destinationAddress,
1780
+ status: RoutingTableStatus[entry.status], // get str value from enum to satisfy upstream's needs
1781
+ nextHop: entry.nextHopAddress,
1782
+ });
2512
1783
  }
2513
- resolve({ table });
2514
- return enums_3.EmberStatus.SUCCESS;
2515
- }, reject);
1784
+ return [result.routingTableEntries, result.entryList.length];
1785
+ };
1786
+ let [tableEntries, entryCount] = await request(0);
1787
+ const size = tableEntries;
1788
+ let nextStartIndex = entryCount;
1789
+ while (table.length < size) {
1790
+ [tableEntries, entryCount] = await request(nextStartIndex);
1791
+ nextStartIndex += entryCount;
1792
+ }
1793
+ return { table };
2516
1794
  });
2517
1795
  }
2518
1796
  // queued, non-InterPAN
2519
1797
  async nodeDescriptor(networkAddress) {
2520
- return new Promise((resolve, reject) => {
2521
- this.requestQueue.enqueue(async () => {
2522
- this.checkInterpanLock();
2523
- /* eslint-disable @typescript-eslint/no-unused-vars */
2524
- const [status, apsFrame, messageTag] = (await this.emberNodeDescriptorRequest(networkAddress, DEFAULT_APS_OPTIONS));
2525
- if (status !== enums_3.EmberStatus.SUCCESS) {
2526
- logger_1.logger.error(`[ZDO] Failed node descriptor for "${networkAddress}" with status=${enums_3.EmberStatus[status]}.`, NS);
2527
- return status;
2528
- }
2529
- const result = (await this.oneWaitress.startWaitingFor({
2530
- target: networkAddress,
2531
- apsFrame,
2532
- responseClusterId: zdo_1.NODE_DESCRIPTOR_RESPONSE,
2533
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2534
- let type = 'Unknown';
2535
- switch (result.logicalType) {
2536
- case 0x0:
2537
- type = 'Coordinator';
2538
- break;
2539
- case 0x1:
2540
- type = 'Router';
2541
- break;
2542
- case 0x2:
2543
- type = 'EndDevice';
2544
- break;
2545
- }
2546
- // always 0 before rev. 21 where field was added
2547
- if (result.stackRevision < CURRENT_ZIGBEE_SPEC_REVISION) {
2548
- logger_1.logger.warning(`[ZDO] Node descriptor for "${networkAddress}" reports device is only compliant to revision `
2549
- + `"${(result.stackRevision < 21) ? 'pre-21' : result.stackRevision}" of the ZigBee specification `
2550
- + `(current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS);
2551
- }
2552
- resolve({ type, manufacturerCode: result.manufacturerCode });
2553
- return enums_3.EmberStatus.SUCCESS;
2554
- }, reject);
1798
+ return this.queue.execute(async () => {
1799
+ this.checkInterpanLock();
1800
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildNodeDescriptorRequest(networkAddress);
1801
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1802
+ if (status !== enums_1.SLStatus.OK) {
1803
+ throw new Error(`[ZDO] Failed node descriptor for "${networkAddress}" with status=${enums_1.SLStatus[status]}.`);
1804
+ }
1805
+ const result = await this.oneWaitress.startWaitingFor({
1806
+ target: networkAddress,
1807
+ apsFrame,
1808
+ responseClusterId: Zdo.ClusterId.NODE_DESCRIPTOR_RESPONSE,
1809
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
1810
+ let type = 'Unknown';
1811
+ switch (result.logicalType) {
1812
+ case 0x0:
1813
+ type = 'Coordinator';
1814
+ break;
1815
+ case 0x1:
1816
+ type = 'Router';
1817
+ break;
1818
+ case 0x2:
1819
+ type = 'EndDevice';
1820
+ break;
1821
+ }
1822
+ // always 0 before rev. 21 where field was added
1823
+ if (result.serverMask.stackComplianceResivion < CURRENT_ZIGBEE_SPEC_REVISION) {
1824
+ logger_1.logger.warning(`[ZDO] Node descriptor for '${networkAddress}' reports device is only compliant to revision ` +
1825
+ `'${result.serverMask.stackComplianceResivion < 21 ? 'pre-21' : result.serverMask.stackComplianceResivion}' ` +
1826
+ `of the ZigBee specification (current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS);
1827
+ }
1828
+ return { type, manufacturerCode: result.manufacturerCode };
2555
1829
  });
2556
1830
  }
2557
1831
  // queued, non-InterPAN
2558
1832
  async activeEndpoints(networkAddress) {
2559
- return new Promise((resolve, reject) => {
2560
- this.requestQueue.enqueue(async () => {
2561
- this.checkInterpanLock();
2562
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2563
- const [status, apsFrame, messageTag] = (await this.emberActiveEndpointsRequest(networkAddress, DEFAULT_APS_OPTIONS));
2564
- if (status !== enums_3.EmberStatus.SUCCESS) {
2565
- logger_1.logger.error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${enums_3.EmberStatus[status]}.`, NS);
2566
- return status;
2567
- }
2568
- const result = (await this.oneWaitress.startWaitingFor({
2569
- target: networkAddress,
2570
- apsFrame,
2571
- responseClusterId: zdo_1.ACTIVE_ENDPOINTS_RESPONSE,
2572
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2573
- resolve({ endpoints: result.endpointList });
2574
- return enums_3.EmberStatus.SUCCESS;
2575
- }, reject);
1833
+ return this.queue.execute(async () => {
1834
+ this.checkInterpanLock();
1835
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildActiveEndpointsRequest(networkAddress);
1836
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1837
+ if (status !== enums_1.SLStatus.OK) {
1838
+ throw new Error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${enums_1.SLStatus[status]}.`);
1839
+ }
1840
+ const result = await this.oneWaitress.startWaitingFor({
1841
+ target: networkAddress,
1842
+ apsFrame,
1843
+ responseClusterId: Zdo.ClusterId.ACTIVE_ENDPOINTS_RESPONSE,
1844
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
1845
+ return { endpoints: result.endpointList };
2576
1846
  });
2577
1847
  }
2578
1848
  // queued, non-InterPAN
2579
1849
  async simpleDescriptor(networkAddress, endpointID) {
2580
- return new Promise((resolve, reject) => {
2581
- this.requestQueue.enqueue(async () => {
2582
- this.checkInterpanLock();
2583
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2584
- const [status, apsFrame, messageTag] = (await this.emberSimpleDescriptorRequest(networkAddress, endpointID, DEFAULT_APS_OPTIONS));
2585
- if (status !== enums_3.EmberStatus.SUCCESS) {
2586
- logger_1.logger.error(`[ZDO] Failed simple descriptor request for "${networkAddress}" endpoint "${endpointID}" `
2587
- + `with status=${enums_3.EmberStatus[status]}.`, NS);
2588
- return status;
2589
- }
2590
- const result = (await this.oneWaitress.startWaitingFor({
2591
- target: networkAddress,
2592
- apsFrame,
2593
- responseClusterId: zdo_1.SIMPLE_DESCRIPTOR_RESPONSE,
2594
- }, DEFAULT_ZDO_REQUEST_TIMEOUT));
2595
- resolve({
2596
- profileID: result.profileId,
2597
- endpointID: result.endpoint,
2598
- deviceID: result.deviceId,
2599
- inputClusters: result.inClusterList,
2600
- outputClusters: result.outClusterList,
2601
- });
2602
- return enums_3.EmberStatus.SUCCESS;
2603
- }, reject);
1850
+ return this.queue.execute(async () => {
1851
+ this.checkInterpanLock();
1852
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildSimpleDescriptorRequest(networkAddress, endpointID);
1853
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1854
+ if (status !== enums_1.SLStatus.OK) {
1855
+ throw new Error(`[ZDO] Failed simple descriptor request for "${networkAddress}" endpoint "${endpointID}" ` + `with status=${enums_1.SLStatus[status]}.`);
1856
+ }
1857
+ const result = await this.oneWaitress.startWaitingFor({
1858
+ target: networkAddress,
1859
+ apsFrame,
1860
+ responseClusterId: Zdo.ClusterId.SIMPLE_DESCRIPTOR_RESPONSE,
1861
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
1862
+ return {
1863
+ profileID: result.profileId,
1864
+ endpointID: result.endpoint,
1865
+ deviceID: result.deviceId,
1866
+ inputClusters: result.inClusterList,
1867
+ outputClusters: result.outClusterList,
1868
+ };
2604
1869
  });
2605
1870
  }
2606
1871
  // queued, non-InterPAN
2607
1872
  async bind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
2608
1873
  if (typeof destinationAddressOrGroup === 'string' && type === 'endpoint') {
2609
1874
  // dest address is EUI64 (str), so type should always be endpoint (unicast)
2610
- return new Promise((resolve, reject) => {
2611
- this.requestQueue.enqueue(async () => {
2612
- this.checkInterpanLock();
2613
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2614
- const [status, apsFrame, messageTag] = (await this.emberBindRequest(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, zdo_1.UNICAST_BINDING, destinationAddressOrGroup, null, // doesn't matter
2615
- destinationEndpoint, DEFAULT_APS_OPTIONS));
2616
- if (status !== enums_3.EmberStatus.SUCCESS) {
2617
- logger_1.logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" `
2618
- + `endpoint "${destinationEndpoint}" with status=${enums_3.EmberStatus[status]}.`, NS);
2619
- return status;
2620
- }
2621
- await this.oneWaitress.startWaitingFor({
2622
- target: destinationNetworkAddress,
2623
- apsFrame,
2624
- responseClusterId: zdo_1.BIND_RESPONSE,
2625
- }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2626
- resolve();
2627
- return enums_3.EmberStatus.SUCCESS;
2628
- }, reject);
1875
+ return this.queue.execute(async () => {
1876
+ this.checkInterpanLock();
1877
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildBindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.UNICAST_BINDING, destinationAddressOrGroup, undefined, // not used with UNICAST_BINDING
1878
+ destinationEndpoint);
1879
+ const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.BIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1880
+ if (status !== enums_1.SLStatus.OK) {
1881
+ throw new Error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` +
1882
+ `endpoint "${destinationEndpoint}" with status=${enums_1.SLStatus[status]}.`);
1883
+ }
1884
+ await this.oneWaitress.startWaitingFor({
1885
+ target: destinationNetworkAddress,
1886
+ apsFrame,
1887
+ responseClusterId: Zdo.ClusterId.BIND_RESPONSE,
1888
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2629
1889
  });
2630
1890
  }
2631
1891
  else if (typeof destinationAddressOrGroup === 'number' && type === 'group') {
2632
1892
  // dest is group num, so type should always be group (multicast)
2633
- return new Promise((resolve, reject) => {
2634
- this.requestQueue.enqueue(async () => {
2635
- this.checkInterpanLock();
2636
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2637
- const [status, apsFrame, messageTag] = (await this.emberBindRequest(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, zdo_1.MULTICAST_BINDING, null, // doesn't matter
2638
- destinationAddressOrGroup, destinationEndpoint, // doesn't matter
2639
- DEFAULT_APS_OPTIONS));
2640
- if (status !== enums_3.EmberStatus.SUCCESS) {
2641
- logger_1.logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" `
2642
- + `with status=${enums_3.EmberStatus[status]}.`, NS);
2643
- return status;
2644
- }
2645
- await this.oneWaitress.startWaitingFor({
2646
- target: destinationNetworkAddress,
2647
- apsFrame,
2648
- responseClusterId: zdo_1.BIND_RESPONSE,
2649
- }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2650
- resolve();
2651
- return enums_3.EmberStatus.SUCCESS;
2652
- }, reject);
1893
+ return this.queue.execute(async () => {
1894
+ this.checkInterpanLock();
1895
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildBindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.MULTICAST_BINDING, undefined, // not used with MULTICAST_BINDING
1896
+ destinationAddressOrGroup, undefined);
1897
+ const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.BIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1898
+ if (status !== enums_1.SLStatus.OK) {
1899
+ throw new Error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` +
1900
+ `with status=${enums_1.SLStatus[status]}.`);
1901
+ }
1902
+ await this.oneWaitress.startWaitingFor({
1903
+ target: destinationNetworkAddress,
1904
+ apsFrame,
1905
+ responseClusterId: Zdo.ClusterId.BIND_RESPONSE,
1906
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2653
1907
  });
2654
1908
  }
2655
1909
  }
@@ -2657,79 +1911,61 @@ class EmberAdapter extends __1.Adapter {
2657
1911
  async unbind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
2658
1912
  if (typeof destinationAddressOrGroup === 'string' && type === 'endpoint') {
2659
1913
  // dest address is EUI64 (str), so type should always be endpoint (unicast)
2660
- return new Promise((resolve, reject) => {
2661
- this.requestQueue.enqueue(async () => {
2662
- this.checkInterpanLock();
2663
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2664
- const [status, apsFrame, messageTag] = (await this.emberUnbindRequest(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, zdo_1.UNICAST_BINDING, destinationAddressOrGroup, null, // doesn't matter
2665
- destinationEndpoint, DEFAULT_APS_OPTIONS));
2666
- if (status !== enums_3.EmberStatus.SUCCESS) {
2667
- logger_1.logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" `
2668
- + `endpoint "${destinationEndpoint}" with status=${enums_3.EmberStatus[status]}.`, NS);
2669
- return status;
2670
- }
2671
- await this.oneWaitress.startWaitingFor({
2672
- target: destinationNetworkAddress,
2673
- apsFrame,
2674
- responseClusterId: zdo_1.UNBIND_RESPONSE,
2675
- }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2676
- resolve();
2677
- return enums_3.EmberStatus.SUCCESS;
2678
- }, reject);
1914
+ return this.queue.execute(async () => {
1915
+ this.checkInterpanLock();
1916
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildUnbindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.UNICAST_BINDING, destinationAddressOrGroup, undefined, // not used with UNICAST_BINDING
1917
+ destinationEndpoint);
1918
+ const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.UNBIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1919
+ if (status !== enums_1.SLStatus.OK) {
1920
+ throw new Error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` +
1921
+ `endpoint "${destinationEndpoint}" with status=${enums_1.SLStatus[status]}.`);
1922
+ }
1923
+ await this.oneWaitress.startWaitingFor({
1924
+ target: destinationNetworkAddress,
1925
+ apsFrame,
1926
+ responseClusterId: Zdo.ClusterId.UNBIND_RESPONSE,
1927
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2679
1928
  });
2680
1929
  }
2681
1930
  else if (typeof destinationAddressOrGroup === 'number' && type === 'group') {
2682
1931
  // dest is group num, so type should always be group (multicast)
2683
- return new Promise((resolve, reject) => {
2684
- this.requestQueue.enqueue(async () => {
2685
- this.checkInterpanLock();
2686
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2687
- const [status, apsFrame, messageTag] = (await this.emberUnbindRequest(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, zdo_1.MULTICAST_BINDING, null, // doesn't matter
2688
- destinationAddressOrGroup, destinationEndpoint, // doesn't matter
2689
- DEFAULT_APS_OPTIONS));
2690
- if (status !== enums_3.EmberStatus.SUCCESS) {
2691
- logger_1.logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" `
2692
- + `with status=${enums_3.EmberStatus[status]}.`, NS);
2693
- return status;
2694
- }
2695
- await this.oneWaitress.startWaitingFor({
2696
- target: destinationNetworkAddress,
2697
- apsFrame,
2698
- responseClusterId: zdo_1.UNBIND_RESPONSE,
2699
- }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2700
- resolve();
2701
- return enums_3.EmberStatus.SUCCESS;
2702
- }, reject);
2703
- });
2704
- }
2705
- }
2706
- // queued, non-InterPAN
2707
- async removeDevice(networkAddress, ieeeAddr) {
2708
- return new Promise((resolve, reject) => {
2709
- this.requestQueue.enqueue(async () => {
1932
+ return new Promise(async () => {
2710
1933
  this.checkInterpanLock();
2711
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2712
- const [status, apsFrame, messageTag] = (await this.emberLeaveRequest(networkAddress, ieeeAddr, enums_3.EmberLeaveRequestFlags.WITHOUT_REJOIN, DEFAULT_APS_OPTIONS));
2713
- if (status !== enums_3.EmberStatus.SUCCESS) {
2714
- logger_1.logger.error(`[ZDO] Failed remove device request for "${networkAddress}" target "${ieeeAddr}" `
2715
- + `with status=${enums_3.EmberStatus[status]}.`, NS);
2716
- return status;
1934
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildUnbindRequest(sourceIeeeAddress, sourceEndpoint, clusterID, Zdo.MULTICAST_BINDING, undefined, // not used with MULTICAST_BINDING
1935
+ destinationAddressOrGroup, undefined);
1936
+ const [status, apsFrame] = await this.sendZDORequest(destinationNetworkAddress, Zdo.ClusterId.UNBIND_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1937
+ if (status !== enums_1.SLStatus.OK) {
1938
+ throw new Error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` +
1939
+ `with status=${enums_1.SLStatus[status]}.`);
2717
1940
  }
2718
1941
  await this.oneWaitress.startWaitingFor({
2719
- target: networkAddress,
1942
+ target: destinationNetworkAddress,
2720
1943
  apsFrame,
2721
- responseClusterId: zdo_1.LEAVE_RESPONSE,
1944
+ responseClusterId: Zdo.ClusterId.UNBIND_RESPONSE,
2722
1945
  }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2723
- resolve();
2724
- return enums_3.EmberStatus.SUCCESS;
2725
- }, reject);
1946
+ });
1947
+ }
1948
+ }
1949
+ // queued, non-InterPAN
1950
+ async removeDevice(networkAddress, ieeeAddr) {
1951
+ return this.queue.execute(async () => {
1952
+ this.checkInterpanLock();
1953
+ const zdoPayload = buffaloZdo_1.BuffaloZdo.buildLeaveRequest(ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
1954
+ const [status, apsFrame] = await this.sendZDORequest(networkAddress, Zdo.ClusterId.LEAVE_REQUEST, zdoPayload, DEFAULT_APS_OPTIONS);
1955
+ if (status !== enums_1.SLStatus.OK) {
1956
+ throw new Error(`[ZDO] Failed remove device request for "${networkAddress}" target "${ieeeAddr}" ` + `with status=${enums_1.SLStatus[status]}.`);
1957
+ }
1958
+ await this.oneWaitress.startWaitingFor({
1959
+ target: networkAddress,
1960
+ apsFrame,
1961
+ responseClusterId: Zdo.ClusterId.LEAVE_RESPONSE,
1962
+ }, DEFAULT_ZDO_REQUEST_TIMEOUT);
2726
1963
  });
2727
1964
  }
2728
1965
  //---- ZCL
2729
1966
  // queued, non-InterPAN
2730
1967
  async sendZclFrameToEndpoint(ieeeAddr, networkAddress, endpoint, zclFrame, timeout, disableResponse, disableRecovery, sourceEndpoint) {
2731
- const sourceEndpointInfo = typeof sourceEndpoint === 'number' ?
2732
- endpoints_1.FIXED_ENDPOINTS.find((epi) => (epi.endpoint === sourceEndpoint)) : endpoints_1.FIXED_ENDPOINTS[0];
1968
+ const sourceEndpointInfo = typeof sourceEndpoint === 'number' ? endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint) : endpoints_1.FIXED_ENDPOINTS[0];
2733
1969
  const command = zclFrame.command;
2734
1970
  let commandResponseId = null;
2735
1971
  if (command.hasOwnProperty('response') && disableResponse === false) {
@@ -2742,54 +1978,65 @@ class EmberAdapter extends __1.Adapter {
2742
1978
  profileId: sourceEndpointInfo.profileId,
2743
1979
  clusterId: zclFrame.cluster.ID,
2744
1980
  sourceEndpoint: sourceEndpointInfo.endpoint,
2745
- destinationEndpoint: (typeof endpoint === 'number') ? endpoint : endpoints_1.FIXED_ENDPOINTS[0].endpoint,
1981
+ destinationEndpoint: typeof endpoint === 'number' ? endpoint : endpoints_1.FIXED_ENDPOINTS[0].endpoint,
2746
1982
  options: DEFAULT_APS_OPTIONS,
2747
1983
  groupId: 0,
2748
1984
  sequence: 0, // set by stack
2749
1985
  };
2750
1986
  // don't RETRY if no response expected
2751
1987
  if (commandResponseId == null) {
2752
- apsFrame.options &= ~enums_3.EmberApsOption.RETRY;
1988
+ apsFrame.options &= ~enums_1.EmberApsOption.RETRY;
2753
1989
  }
2754
1990
  const data = zclFrame.toBuffer();
2755
- return new Promise((resolve, reject) => {
2756
- this.requestQueue.enqueue(async () => {
2757
- this.checkInterpanLock();
2758
- if (CHECK_APS_PAYLOAD_LENGTH) {
2759
- const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame));
2760
- if (data.length > maxPayloadLength) {
2761
- return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
1991
+ return this.queue.execute(async () => {
1992
+ this.checkInterpanLock();
1993
+ logger_1.logger.debug(`~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
1994
+ for (let i = 1; i <= QUEUE_MAX_SEND_ATTEMPTS; i++) {
1995
+ let status = enums_1.SLStatus.FAIL;
1996
+ try {
1997
+ [status] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, data, 0, // alias
1998
+ 0);
1999
+ }
2000
+ catch (error) {
2001
+ if (error instanceof ezspError_1.EzspError) {
2002
+ if (error.code === enums_1.EzspStatus.NO_TX_SPACE) {
2003
+ status === enums_1.SLStatus.BUSY;
2004
+ }
2005
+ else if (error.code === enums_1.EzspStatus.NOT_CONNECTED) {
2006
+ status === enums_1.SLStatus.NETWORK_DOWN;
2007
+ }
2762
2008
  }
2763
2009
  }
2764
- logger_1.logger.debug(`~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2765
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2766
- const [status, messageTag] = (await this.ezsp.send(enums_3.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, data, 0, // alias
2767
- 0));
2768
- if (status !== enums_3.EmberStatus.SUCCESS) {
2769
- logger_1.logger.error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${enums_3.EmberStatus[status]}.`, NS);
2770
- return status; // let queue handle retry based on status
2010
+ // `else if` order matters
2011
+ if (status === enums_1.SLStatus.OK) {
2012
+ break;
2771
2013
  }
2772
- if (commandResponseId != null) {
2773
- // NOTE: aps sequence number will have been set by send function
2774
- const result = (await this.oneWaitress.startWaitingFor({
2775
- target: networkAddress,
2776
- apsFrame,
2777
- zclSequence: zclFrame.header.transactionSequenceNumber,
2778
- commandIdentifier: commandResponseId,
2779
- }, timeout || DEFAULT_ZCL_REQUEST_TIMEOUT));
2780
- resolve(result);
2014
+ else if (disableRecovery || i == QUEUE_MAX_SEND_ATTEMPTS) {
2015
+ throw new Error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
2781
2016
  }
2782
- else {
2783
- resolve(null); // don't expect a response
2784
- return enums_3.EmberStatus.SUCCESS;
2017
+ else if (status === enums_1.SLStatus.ZIGBEE_MAX_MESSAGE_LIMIT_REACHED || status === enums_1.SLStatus.BUSY) {
2018
+ await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);
2785
2019
  }
2786
- }, reject);
2020
+ else if (status === enums_1.SLStatus.NETWORK_DOWN) {
2021
+ await (0, utils_1.Wait)(QUEUE_NETWORK_DOWN_DEFER_MSEC);
2022
+ }
2023
+ }
2024
+ if (commandResponseId != null) {
2025
+ // NOTE: aps sequence number will have been set by send function
2026
+ const result = await this.oneWaitress.startWaitingFor({
2027
+ target: networkAddress,
2028
+ apsFrame,
2029
+ zclSequence: zclFrame.header.transactionSequenceNumber,
2030
+ commandIdentifier: commandResponseId,
2031
+ }, timeout || DEFAULT_ZCL_REQUEST_TIMEOUT);
2032
+ return result;
2033
+ }
2034
+ return null;
2787
2035
  });
2788
2036
  }
2789
2037
  // queued, non-InterPAN
2790
2038
  async sendZclFrameToGroup(groupID, zclFrame, sourceEndpoint) {
2791
- const sourceEndpointInfo = typeof sourceEndpoint === 'number' ?
2792
- endpoints_1.FIXED_ENDPOINTS.find((epi) => (epi.endpoint === sourceEndpoint)) : endpoints_1.FIXED_ENDPOINTS[0];
2039
+ const sourceEndpointInfo = typeof sourceEndpoint === 'number' ? endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint) : endpoints_1.FIXED_ENDPOINTS[0];
2793
2040
  const apsFrame = {
2794
2041
  profileId: sourceEndpointInfo.profileId,
2795
2042
  clusterId: zclFrame.cluster.ID,
@@ -2800,65 +2047,44 @@ class EmberAdapter extends __1.Adapter {
2800
2047
  sequence: 0, // set by stack
2801
2048
  };
2802
2049
  const data = zclFrame.toBuffer();
2803
- return new Promise((resolve, reject) => {
2804
- this.requestQueue.enqueue(async () => {
2805
- this.checkInterpanLock();
2806
- if (CHECK_APS_PAYLOAD_LENGTH) {
2807
- const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.MULTICAST, groupID, apsFrame));
2808
- if (data.length > maxPayloadLength) {
2809
- return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
2810
- }
2811
- }
2812
- logger_1.logger.debug(`~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2813
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2814
- const [status, messageTag] = (await this.ezsp.send(enums_3.EmberOutgoingMessageType.MULTICAST, apsFrame.groupId, // not used for MC
2815
- apsFrame, data, 0, // alias
2816
- 0));
2817
- if (status !== enums_3.EmberStatus.SUCCESS) {
2818
- logger_1.logger.error(`~x~> [ZCL GROUP] Failed to send with status=${enums_3.EmberStatus[status]}.`, NS);
2819
- return status; // let queue handle retry based on status
2820
- }
2821
- // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2822
- resolve();
2823
- return enums_3.EmberStatus.SUCCESS;
2824
- }, reject);
2050
+ return this.queue.execute(async () => {
2051
+ this.checkInterpanLock();
2052
+ logger_1.logger.debug(`~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2053
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2054
+ const [status, messageTag] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.MULTICAST, apsFrame.groupId, // not used with MULTICAST
2055
+ apsFrame, data, 0, // alias
2056
+ 0);
2057
+ if (status !== enums_1.SLStatus.OK) {
2058
+ throw new Error(`~x~> [ZCL GROUP] Failed to send with status=${enums_1.SLStatus[status]}.`);
2059
+ }
2060
+ // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2061
+ await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);
2825
2062
  });
2826
2063
  }
2827
2064
  // queued, non-InterPAN
2828
2065
  async sendZclFrameToAll(endpoint, zclFrame, sourceEndpoint, destination) {
2829
- const sourceEndpointInfo = typeof sourceEndpoint === 'number' ?
2830
- endpoints_1.FIXED_ENDPOINTS.find((epi) => (epi.endpoint === sourceEndpoint)) : endpoints_1.FIXED_ENDPOINTS[0];
2066
+ const sourceEndpointInfo = typeof sourceEndpoint === 'number' ? endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint) : endpoints_1.FIXED_ENDPOINTS[0];
2831
2067
  const apsFrame = {
2832
2068
  profileId: sourceEndpointInfo.profileId,
2833
2069
  clusterId: zclFrame.cluster.ID,
2834
2070
  sourceEndpoint: sourceEndpointInfo.endpoint,
2835
- destinationEndpoint: (typeof endpoint === 'number') ? endpoint : endpoints_1.FIXED_ENDPOINTS[0].endpoint,
2071
+ destinationEndpoint: typeof endpoint === 'number' ? endpoint : endpoints_1.FIXED_ENDPOINTS[0].endpoint,
2836
2072
  options: DEFAULT_APS_OPTIONS,
2837
2073
  groupId: destination,
2838
2074
  sequence: 0, // set by stack
2839
2075
  };
2840
2076
  const data = zclFrame.toBuffer();
2841
- return new Promise((resolve, reject) => {
2842
- this.requestQueue.enqueue(async () => {
2843
- this.checkInterpanLock();
2844
- if (CHECK_APS_PAYLOAD_LENGTH) {
2845
- const maxPayloadLength = (await this.maximumApsPayloadLength(enums_3.EmberOutgoingMessageType.BROADCAST, destination, apsFrame));
2846
- if (data.length > maxPayloadLength) {
2847
- return enums_3.EmberStatus.MESSAGE_TOO_LONG; // queue will reject
2848
- }
2849
- }
2850
- logger_1.logger.debug(`~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2851
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2852
- const [status, messageTag] = (await this.ezsp.send(enums_3.EmberOutgoingMessageType.BROADCAST, destination, apsFrame, data, 0, // alias
2853
- 0));
2854
- if (status !== enums_3.EmberStatus.SUCCESS) {
2855
- logger_1.logger.error(`~x~> [ZCL BROADCAST] Failed to send with status=${enums_3.EmberStatus[status]}.`, NS);
2856
- return status; // let queue handle retry based on status
2857
- }
2858
- // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2859
- resolve();
2860
- return enums_3.EmberStatus.SUCCESS;
2861
- }, reject);
2077
+ return this.queue.execute(async () => {
2078
+ this.checkInterpanLock();
2079
+ logger_1.logger.debug(`~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
2080
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2081
+ const [status, messageTag] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.BROADCAST, destination, apsFrame, data, 0, // alias
2082
+ 0);
2083
+ if (status !== enums_1.SLStatus.OK) {
2084
+ throw new Error(`~x~> [ZCL BROADCAST] Failed to send with status=${enums_1.SLStatus[status]}.`);
2085
+ }
2086
+ // NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
2087
+ await (0, utils_1.Wait)(QUEUE_BUSY_DEFER_MSEC);
2862
2088
  });
2863
2089
  }
2864
2090
  //---- InterPAN for Touchlink
@@ -2870,48 +2096,38 @@ class EmberAdapter extends __1.Adapter {
2870
2096
  logger_1.logger.error(`Tried to set channel InterPAN to non-number. Channel ${channel} of type ${typeof channel}.`, NS);
2871
2097
  return;
2872
2098
  }
2873
- return new Promise((resolve, reject) => {
2874
- this.requestQueue.enqueue(async () => {
2875
- this.interpanLock = true;
2876
- const status = (await this.ezsp.ezspSetLogicalAndRadioChannel(channel));
2877
- if (status !== enums_3.EmberStatus.SUCCESS) {
2878
- this.interpanLock = false; // XXX: ok?
2879
- logger_1.logger.error(`Failed to set InterPAN channel to ${channel} with status=${enums_3.EmberStatus[status]}.`, NS);
2880
- return status;
2881
- }
2882
- resolve();
2883
- return status;
2884
- }, reject);
2099
+ return this.queue.execute(async () => {
2100
+ this.interpanLock = true;
2101
+ const status = await this.ezsp.ezspSetLogicalAndRadioChannel(channel);
2102
+ if (status !== enums_1.SLStatus.OK) {
2103
+ this.interpanLock = false; // XXX: ok?
2104
+ throw new Error(`Failed to set InterPAN channel to ${channel} with status=${enums_1.SLStatus[status]}.`);
2105
+ }
2885
2106
  });
2886
2107
  }
2887
2108
  // queued
2888
2109
  async sendZclFrameInterPANToIeeeAddr(zclFrame, ieeeAddress) {
2889
- return new Promise((resolve, reject) => {
2890
- this.requestQueue.enqueue(async () => {
2891
- const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_2.MAXIMUM_INTERPAN_LENGTH));
2892
- // cache-enabled getters
2893
- const sourcePanId = (await this.emberGetPanId());
2894
- const sourceEui64 = (await this.emberGetEui64());
2895
- msgBuffalo.writeUInt16((consts_2.LONG_DEST_FRAME_CONTROL | consts_2.MAC_ACK_REQUIRED)); // macFrameControl
2896
- msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2897
- msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2898
- msgBuffalo.writeIeeeAddr(ieeeAddress); // destAddress (longAddress)
2899
- msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2900
- msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2901
- msgBuffalo.writeUInt16(consts_2.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2902
- msgBuffalo.writeUInt8((enums_3.EmberInterpanMessageType.UNICAST | consts_2.INTERPAN_APS_FRAME_TYPE)); // apsFrameControl
2903
- msgBuffalo.writeUInt16(zclFrame.cluster.ID);
2904
- msgBuffalo.writeUInt16(ZSpec.TOUCHLINK_PROFILE_ID);
2905
- logger_1.logger.debug(`~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.header)}]`, NS);
2906
- const status = (await this.ezsp.ezspSendRawMessage(Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()])));
2907
- if (status !== enums_3.EmberStatus.SUCCESS) {
2908
- logger_1.logger.error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${enums_3.EmberStatus[status]}.`, NS);
2909
- return status;
2910
- }
2911
- // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2912
- resolve();
2913
- return status;
2914
- }, reject);
2110
+ return this.queue.execute(async () => {
2111
+ const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_1.MAXIMUM_INTERPAN_LENGTH));
2112
+ // cache-enabled getters
2113
+ const sourcePanId = await this.emberGetPanId();
2114
+ const sourceEui64 = await this.emberGetEui64();
2115
+ msgBuffalo.writeUInt16(consts_1.LONG_DEST_FRAME_CONTROL | consts_1.MAC_ACK_REQUIRED); // macFrameControl
2116
+ msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2117
+ msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2118
+ msgBuffalo.writeIeeeAddr(ieeeAddress); // destAddress (longAddress)
2119
+ msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2120
+ msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2121
+ msgBuffalo.writeUInt16(consts_1.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2122
+ msgBuffalo.writeUInt8(enums_1.EmberInterpanMessageType.UNICAST | consts_1.INTERPAN_APS_FRAME_TYPE); // apsFrameControl
2123
+ msgBuffalo.writeUInt16(zclFrame.cluster.ID);
2124
+ msgBuffalo.writeUInt16(ZSpec.TOUCHLINK_PROFILE_ID);
2125
+ logger_1.logger.debug(`~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.header)}]`, NS);
2126
+ const status = await this.ezsp.ezspSendRawMessage(Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]), enums_1.EmberTransmitPriority.NORMAL, true);
2127
+ if (status !== enums_1.SLStatus.OK) {
2128
+ throw new Error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${enums_1.SLStatus[status]}.`);
2129
+ }
2130
+ // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2915
2131
  });
2916
2132
  }
2917
2133
  // queued
@@ -2926,60 +2142,51 @@ class EmberAdapter extends __1.Adapter {
2926
2142
  clusterId: zclFrame.cluster.ID,
2927
2143
  sourceEndpoint: 0,
2928
2144
  destinationEndpoint: 0,
2929
- options: enums_3.EmberApsOption.NONE,
2930
- groupId: enums_1.BroadcastAddress.SLEEPY,
2145
+ options: enums_1.EmberApsOption.NONE,
2146
+ groupId: ZSpec.BroadcastAddress.SLEEPY,
2931
2147
  sequence: 0, // set by stack
2932
2148
  };
2933
- return new Promise((resolve, reject) => {
2934
- this.requestQueue.enqueue(async () => {
2935
- const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_2.MAXIMUM_INTERPAN_LENGTH));
2936
- // cache-enabled getters
2937
- const sourcePanId = (await this.emberGetPanId());
2938
- const sourceEui64 = (await this.emberGetEui64());
2939
- msgBuffalo.writeUInt16(consts_2.SHORT_DEST_FRAME_CONTROL); // macFrameControl
2940
- msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2941
- msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2942
- msgBuffalo.writeUInt16(apsFrame.groupId); // destAddress (longAddress)
2943
- msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2944
- msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2945
- msgBuffalo.writeUInt16(consts_2.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2946
- msgBuffalo.writeUInt8((enums_3.EmberInterpanMessageType.BROADCAST | consts_2.INTERPAN_APS_FRAME_TYPE)); // apsFrameControl
2947
- msgBuffalo.writeUInt16(apsFrame.clusterId);
2948
- msgBuffalo.writeUInt16(apsFrame.profileId);
2949
- const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]);
2950
- logger_1.logger.debug(`~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.header)}]`, NS);
2951
- const status = (await this.ezsp.ezspSendRawMessage(data));
2952
- if (status !== enums_3.EmberStatus.SUCCESS) {
2953
- logger_1.logger.error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${enums_3.EmberStatus[status]}.`, NS);
2954
- return status;
2955
- }
2956
- // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2957
- const result = (await this.oneWaitress.startWaitingFor({
2958
- target: null,
2959
- apsFrame: apsFrame,
2960
- zclSequence: zclFrame.header.transactionSequenceNumber,
2961
- commandIdentifier: command.response,
2962
- }, timeout || DEFAULT_ZCL_REQUEST_TIMEOUT * 2)); // XXX: touchlink timeout?
2963
- resolve(result);
2964
- return enums_3.EmberStatus.SUCCESS;
2965
- }, reject);
2149
+ return this.queue.execute(async () => {
2150
+ const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_1.MAXIMUM_INTERPAN_LENGTH));
2151
+ // cache-enabled getters
2152
+ const sourcePanId = await this.emberGetPanId();
2153
+ const sourceEui64 = await this.emberGetEui64();
2154
+ msgBuffalo.writeUInt16(consts_1.SHORT_DEST_FRAME_CONTROL); // macFrameControl
2155
+ msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
2156
+ msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
2157
+ msgBuffalo.writeUInt16(apsFrame.groupId); // destAddress (longAddress)
2158
+ msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
2159
+ msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
2160
+ msgBuffalo.writeUInt16(consts_1.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
2161
+ msgBuffalo.writeUInt8(enums_1.EmberInterpanMessageType.BROADCAST | consts_1.INTERPAN_APS_FRAME_TYPE); // apsFrameControl
2162
+ msgBuffalo.writeUInt16(apsFrame.clusterId);
2163
+ msgBuffalo.writeUInt16(apsFrame.profileId);
2164
+ const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]);
2165
+ logger_1.logger.debug(`~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.header)}]`, NS);
2166
+ const status = await this.ezsp.ezspSendRawMessage(data, enums_1.EmberTransmitPriority.NORMAL, true);
2167
+ if (status !== enums_1.SLStatus.OK) {
2168
+ throw new Error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${enums_1.SLStatus[status]}.`);
2169
+ }
2170
+ // NOTE: can use ezspRawTransmitCompleteHandler if needed here
2171
+ const result = await this.oneWaitress.startWaitingFor({
2172
+ target: null,
2173
+ apsFrame: apsFrame,
2174
+ zclSequence: zclFrame.header.transactionSequenceNumber,
2175
+ commandIdentifier: command.response,
2176
+ }, timeout || DEFAULT_ZCL_REQUEST_TIMEOUT * 2); // XXX: touchlink timeout?
2177
+ return result;
2966
2178
  });
2967
2179
  }
2968
2180
  // queued
2969
2181
  async restoreChannelInterPAN() {
2970
- return new Promise((resolve, reject) => {
2971
- this.requestQueue.enqueue(async () => {
2972
- const status = (await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0]));
2973
- if (status !== enums_3.EmberStatus.SUCCESS) {
2974
- logger_1.logger.error(`Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${enums_3.EmberStatus[status]}.`, NS);
2975
- return status;
2976
- }
2977
- // let adapter settle down
2978
- await (0, utils_1.Wait)(3000);
2979
- this.interpanLock = false;
2980
- resolve();
2981
- return status;
2982
- }, reject);
2182
+ return this.queue.execute(async () => {
2183
+ const status = await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0]);
2184
+ if (status !== enums_1.SLStatus.OK) {
2185
+ throw new Error(`Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${enums_1.SLStatus[status]}.`);
2186
+ }
2187
+ // let adapter settle down
2188
+ await (0, utils_1.Wait)(QUEUE_NETWORK_DOWN_DEFER_MSEC);
2189
+ this.interpanLock = false;
2983
2190
  });
2984
2191
  }
2985
2192
  //-- END Adapter implementation
@@ -2987,7 +2194,7 @@ class EmberAdapter extends __1.Adapter {
2987
2194
  if (this.interpanLock) {
2988
2195
  logger_1.logger.error(`[INTERPAN MODE] Cannot execute non-InterPAN commands.`, NS);
2989
2196
  // will be caught by request queue and rejected internally.
2990
- throw new Error(enums_3.EzspStatus[enums_3.EzspStatus.ERROR_INVALID_CALL]);
2197
+ throw new ezspError_1.EzspError(enums_1.EzspStatus.ERROR_INVALID_CALL);
2991
2198
  }
2992
2199
  }
2993
2200
  }