@matter/protocol 0.16.0-alpha.0-20251213-e83db3732 → 0.16.0-alpha.0-20251217-038f88085

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 (309) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cjs/action/client/ClientInteraction.d.ts +12 -5
  3. package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
  4. package/dist/cjs/action/client/ClientInteraction.js +39 -15
  5. package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
  6. package/dist/cjs/action/client/ClientRead.d.ts +10 -0
  7. package/dist/cjs/action/client/ClientRead.d.ts.map +1 -0
  8. package/dist/cjs/action/client/ClientRead.js +22 -0
  9. package/dist/cjs/action/client/ClientRead.js.map +6 -0
  10. package/dist/cjs/action/client/ClientRequest.d.ts +20 -0
  11. package/dist/cjs/action/client/ClientRequest.d.ts.map +1 -0
  12. package/dist/cjs/action/client/ClientRequest.js +22 -0
  13. package/dist/cjs/action/client/ClientRequest.js.map +6 -0
  14. package/dist/cjs/action/client/ClientWrite.d.ts +10 -0
  15. package/dist/cjs/action/client/ClientWrite.d.ts.map +1 -0
  16. package/dist/cjs/action/client/ClientWrite.js +22 -0
  17. package/dist/cjs/action/client/ClientWrite.js.map +6 -0
  18. package/dist/cjs/action/client/QueuedClientInteraction.d.ts +49 -0
  19. package/dist/cjs/action/client/QueuedClientInteraction.d.ts.map +1 -0
  20. package/dist/cjs/action/client/QueuedClientInteraction.js +160 -0
  21. package/dist/cjs/action/client/QueuedClientInteraction.js.map +6 -0
  22. package/dist/cjs/action/client/index.d.ts +4 -0
  23. package/dist/cjs/action/client/index.d.ts.map +1 -1
  24. package/dist/cjs/action/client/index.js +4 -0
  25. package/dist/cjs/action/client/index.js.map +1 -1
  26. package/dist/cjs/action/client/subscription/ClientSubscribe.d.ts +2 -1
  27. package/dist/cjs/action/client/subscription/ClientSubscribe.d.ts.map +1 -1
  28. package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.d.ts.map +1 -1
  29. package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js +14 -3
  30. package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
  31. package/dist/cjs/action/client/subscription/SustainedSubscription.d.ts +1 -1
  32. package/dist/cjs/action/client/subscription/SustainedSubscription.d.ts.map +1 -1
  33. package/dist/cjs/action/client/subscription/SustainedSubscription.js +1 -4
  34. package/dist/cjs/action/client/subscription/SustainedSubscription.js.map +1 -1
  35. package/dist/cjs/action/request/Invoke.d.ts +7 -1
  36. package/dist/cjs/action/request/Invoke.d.ts.map +1 -1
  37. package/dist/cjs/action/request/Invoke.js +0 -3
  38. package/dist/cjs/action/request/Invoke.js.map +1 -1
  39. package/dist/cjs/action/request/Read.d.ts.map +1 -1
  40. package/dist/cjs/action/request/Read.js +3 -2
  41. package/dist/cjs/action/request/Read.js.map +1 -1
  42. package/dist/cjs/action/request/Specifier.d.ts +1 -1
  43. package/dist/cjs/action/request/Specifier.d.ts.map +1 -1
  44. package/dist/cjs/action/request/Specifier.js +3 -0
  45. package/dist/cjs/action/request/Specifier.js.map +1 -1
  46. package/dist/cjs/action/request/Write.d.ts +1 -0
  47. package/dist/cjs/action/request/Write.d.ts.map +1 -1
  48. package/dist/cjs/action/request/Write.js +10 -2
  49. package/dist/cjs/action/request/Write.js.map +1 -1
  50. package/dist/cjs/action/response/ReadResult.d.ts +1 -1
  51. package/dist/cjs/action/response/ReadResult.d.ts.map +1 -1
  52. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +37 -8
  53. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  54. package/dist/cjs/cluster/client/index.d.ts +0 -3
  55. package/dist/cjs/cluster/client/index.d.ts.map +1 -1
  56. package/dist/cjs/cluster/client/index.js +0 -3
  57. package/dist/cjs/cluster/client/index.js.map +1 -1
  58. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  59. package/dist/cjs/interaction/InteractionMessenger.js +3 -2
  60. package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
  61. package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -1
  62. package/dist/cjs/interaction/SubscriptionClient.js +2 -1
  63. package/dist/cjs/interaction/SubscriptionClient.js.map +1 -1
  64. package/dist/cjs/interaction/index.d.ts +1 -1
  65. package/dist/cjs/interaction/index.d.ts.map +1 -1
  66. package/dist/cjs/interaction/index.js +1 -1
  67. package/dist/cjs/interaction/index.js.map +1 -1
  68. package/dist/cjs/peer/CommissioningError.d.ts +13 -0
  69. package/dist/cjs/peer/CommissioningError.d.ts.map +1 -0
  70. package/dist/cjs/peer/CommissioningError.js +32 -0
  71. package/dist/cjs/peer/CommissioningError.js.map +6 -0
  72. package/dist/cjs/peer/ControllerCommissioner.d.ts +2 -3
  73. package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
  74. package/dist/cjs/peer/ControllerCommissioner.js +20 -13
  75. package/dist/cjs/peer/ControllerCommissioner.js.map +2 -2
  76. package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +7 -16
  77. package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
  78. package/dist/cjs/peer/ControllerCommissioningFlow.js +395 -178
  79. package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
  80. package/dist/cjs/peer/ControllerDiscovery.d.ts +4 -0
  81. package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
  82. package/dist/cjs/peer/ControllerDiscovery.js +6 -3
  83. package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
  84. package/dist/cjs/peer/InteractionQueue.d.ts +2 -2
  85. package/dist/cjs/peer/InteractionQueue.d.ts.map +1 -1
  86. package/dist/cjs/peer/InteractionQueue.js +1 -1
  87. package/dist/cjs/peer/InteractionQueue.js.map +1 -1
  88. package/dist/cjs/peer/PeerAddressStore.d.ts +0 -9
  89. package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
  90. package/dist/cjs/peer/PeerAddressStore.js.map +1 -1
  91. package/dist/cjs/peer/PeerSet.d.ts +0 -2
  92. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  93. package/dist/cjs/peer/PeerSet.js +32 -18
  94. package/dist/cjs/peer/PeerSet.js.map +1 -1
  95. package/dist/cjs/peer/PhysicalDeviceProperties.js +1 -1
  96. package/dist/cjs/peer/PhysicalDeviceProperties.js.map +1 -1
  97. package/dist/cjs/peer/index.d.ts +1 -0
  98. package/dist/cjs/peer/index.d.ts.map +1 -1
  99. package/dist/cjs/peer/index.js +1 -0
  100. package/dist/cjs/peer/index.js.map +1 -1
  101. package/dist/cjs/protocol/DeviceCommissioner.d.ts.map +1 -1
  102. package/dist/cjs/protocol/DeviceCommissioner.js.map +1 -1
  103. package/dist/cjs/protocol/ExchangeManager.js +2 -2
  104. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  105. package/dist/cjs/protocol/ExchangeProvider.d.ts +13 -4
  106. package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
  107. package/dist/cjs/protocol/ExchangeProvider.js +5 -3
  108. package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
  109. package/dist/cjs/session/NodeSession.d.ts +5 -2
  110. package/dist/cjs/session/NodeSession.d.ts.map +1 -1
  111. package/dist/cjs/session/NodeSession.js +5 -4
  112. package/dist/cjs/session/NodeSession.js.map +1 -1
  113. package/dist/cjs/session/Session.d.ts +5 -3
  114. package/dist/cjs/session/Session.d.ts.map +1 -1
  115. package/dist/cjs/session/Session.js +8 -4
  116. package/dist/cjs/session/Session.js.map +1 -1
  117. package/dist/cjs/session/SessionManager.d.ts +8 -0
  118. package/dist/cjs/session/SessionManager.d.ts.map +1 -1
  119. package/dist/cjs/session/SessionManager.js +16 -2
  120. package/dist/cjs/session/SessionManager.js.map +1 -1
  121. package/dist/esm/action/client/ClientInteraction.d.ts +12 -5
  122. package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
  123. package/dist/esm/action/client/ClientInteraction.js +42 -16
  124. package/dist/esm/action/client/ClientInteraction.js.map +1 -1
  125. package/dist/esm/action/client/ClientRead.d.ts +10 -0
  126. package/dist/esm/action/client/ClientRead.d.ts.map +1 -0
  127. package/dist/esm/action/client/ClientRead.js +6 -0
  128. package/dist/esm/action/client/ClientRead.js.map +6 -0
  129. package/dist/esm/action/client/ClientRequest.d.ts +20 -0
  130. package/dist/esm/action/client/ClientRequest.d.ts.map +1 -0
  131. package/dist/esm/action/client/ClientRequest.js +6 -0
  132. package/dist/esm/action/client/ClientRequest.js.map +6 -0
  133. package/dist/esm/action/client/ClientWrite.d.ts +10 -0
  134. package/dist/esm/action/client/ClientWrite.d.ts.map +1 -0
  135. package/dist/esm/action/client/ClientWrite.js +6 -0
  136. package/dist/esm/action/client/ClientWrite.js.map +6 -0
  137. package/dist/esm/action/client/QueuedClientInteraction.d.ts +49 -0
  138. package/dist/esm/action/client/QueuedClientInteraction.d.ts.map +1 -0
  139. package/dist/esm/action/client/QueuedClientInteraction.js +140 -0
  140. package/dist/esm/action/client/QueuedClientInteraction.js.map +6 -0
  141. package/dist/esm/action/client/index.d.ts +4 -0
  142. package/dist/esm/action/client/index.d.ts.map +1 -1
  143. package/dist/esm/action/client/index.js +4 -0
  144. package/dist/esm/action/client/index.js.map +1 -1
  145. package/dist/esm/action/client/subscription/ClientSubscribe.d.ts +2 -1
  146. package/dist/esm/action/client/subscription/ClientSubscribe.d.ts.map +1 -1
  147. package/dist/esm/action/client/subscription/ClientSubscriptionHandler.d.ts.map +1 -1
  148. package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js +14 -3
  149. package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
  150. package/dist/esm/action/client/subscription/SustainedSubscription.d.ts +1 -1
  151. package/dist/esm/action/client/subscription/SustainedSubscription.d.ts.map +1 -1
  152. package/dist/esm/action/client/subscription/SustainedSubscription.js +1 -4
  153. package/dist/esm/action/client/subscription/SustainedSubscription.js.map +1 -1
  154. package/dist/esm/action/request/Invoke.d.ts +7 -1
  155. package/dist/esm/action/request/Invoke.d.ts.map +1 -1
  156. package/dist/esm/action/request/Invoke.js +0 -3
  157. package/dist/esm/action/request/Invoke.js.map +1 -1
  158. package/dist/esm/action/request/Read.d.ts.map +1 -1
  159. package/dist/esm/action/request/Read.js +3 -2
  160. package/dist/esm/action/request/Read.js.map +1 -1
  161. package/dist/esm/action/request/Specifier.d.ts +1 -1
  162. package/dist/esm/action/request/Specifier.d.ts.map +1 -1
  163. package/dist/esm/action/request/Specifier.js +3 -0
  164. package/dist/esm/action/request/Specifier.js.map +1 -1
  165. package/dist/esm/action/request/Write.d.ts +1 -0
  166. package/dist/esm/action/request/Write.d.ts.map +1 -1
  167. package/dist/esm/action/request/Write.js +10 -2
  168. package/dist/esm/action/request/Write.js.map +1 -1
  169. package/dist/esm/action/response/ReadResult.d.ts +1 -1
  170. package/dist/esm/action/response/ReadResult.d.ts.map +1 -1
  171. package/dist/esm/cluster/client/ClusterClientTypes.d.ts +37 -8
  172. package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  173. package/dist/esm/cluster/client/index.d.ts +0 -3
  174. package/dist/esm/cluster/client/index.d.ts.map +1 -1
  175. package/dist/esm/cluster/client/index.js +0 -3
  176. package/dist/esm/cluster/client/index.js.map +1 -1
  177. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  178. package/dist/esm/interaction/InteractionMessenger.js +4 -3
  179. package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
  180. package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -1
  181. package/dist/esm/interaction/SubscriptionClient.js +2 -1
  182. package/dist/esm/interaction/SubscriptionClient.js.map +1 -1
  183. package/dist/esm/interaction/index.d.ts +1 -1
  184. package/dist/esm/interaction/index.d.ts.map +1 -1
  185. package/dist/esm/interaction/index.js +1 -1
  186. package/dist/esm/peer/CommissioningError.d.ts +13 -0
  187. package/dist/esm/peer/CommissioningError.d.ts.map +1 -0
  188. package/dist/esm/peer/CommissioningError.js +12 -0
  189. package/dist/esm/peer/CommissioningError.js.map +6 -0
  190. package/dist/esm/peer/ControllerCommissioner.d.ts +2 -3
  191. package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
  192. package/dist/esm/peer/ControllerCommissioner.js +19 -13
  193. package/dist/esm/peer/ControllerCommissioner.js.map +2 -2
  194. package/dist/esm/peer/ControllerCommissioningFlow.d.ts +7 -16
  195. package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
  196. package/dist/esm/peer/ControllerCommissioningFlow.js +380 -162
  197. package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
  198. package/dist/esm/peer/ControllerDiscovery.d.ts +4 -0
  199. package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
  200. package/dist/esm/peer/ControllerDiscovery.js +4 -1
  201. package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
  202. package/dist/esm/peer/InteractionQueue.d.ts +2 -2
  203. package/dist/esm/peer/InteractionQueue.d.ts.map +1 -1
  204. package/dist/esm/peer/InteractionQueue.js +2 -2
  205. package/dist/esm/peer/InteractionQueue.js.map +1 -1
  206. package/dist/esm/peer/PeerAddressStore.d.ts +0 -9
  207. package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
  208. package/dist/esm/peer/PeerAddressStore.js.map +1 -1
  209. package/dist/esm/peer/PeerSet.d.ts +0 -2
  210. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  211. package/dist/esm/peer/PeerSet.js +32 -18
  212. package/dist/esm/peer/PeerSet.js.map +1 -1
  213. package/dist/esm/peer/PhysicalDeviceProperties.js +1 -1
  214. package/dist/esm/peer/PhysicalDeviceProperties.js.map +1 -1
  215. package/dist/esm/peer/index.d.ts +1 -0
  216. package/dist/esm/peer/index.d.ts.map +1 -1
  217. package/dist/esm/peer/index.js +1 -0
  218. package/dist/esm/peer/index.js.map +1 -1
  219. package/dist/esm/protocol/DeviceCommissioner.d.ts.map +1 -1
  220. package/dist/esm/protocol/DeviceCommissioner.js.map +1 -1
  221. package/dist/esm/protocol/ExchangeManager.js +2 -2
  222. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  223. package/dist/esm/protocol/ExchangeProvider.d.ts +13 -4
  224. package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
  225. package/dist/esm/protocol/ExchangeProvider.js +5 -3
  226. package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
  227. package/dist/esm/session/NodeSession.d.ts +5 -2
  228. package/dist/esm/session/NodeSession.d.ts.map +1 -1
  229. package/dist/esm/session/NodeSession.js +5 -4
  230. package/dist/esm/session/NodeSession.js.map +1 -1
  231. package/dist/esm/session/Session.d.ts +5 -3
  232. package/dist/esm/session/Session.d.ts.map +1 -1
  233. package/dist/esm/session/Session.js +8 -4
  234. package/dist/esm/session/Session.js.map +1 -1
  235. package/dist/esm/session/SessionManager.d.ts +8 -0
  236. package/dist/esm/session/SessionManager.d.ts.map +1 -1
  237. package/dist/esm/session/SessionManager.js +17 -2
  238. package/dist/esm/session/SessionManager.js.map +1 -1
  239. package/package.json +6 -6
  240. package/src/action/client/ClientInteraction.ts +58 -19
  241. package/src/action/client/ClientRead.ts +10 -0
  242. package/src/action/client/ClientRequest.ts +20 -0
  243. package/src/action/client/ClientWrite.ts +10 -0
  244. package/src/action/client/QueuedClientInteraction.ts +91 -0
  245. package/src/action/client/index.ts +4 -0
  246. package/src/action/client/subscription/ClientSubscribe.ts +2 -1
  247. package/src/action/client/subscription/ClientSubscriptionHandler.ts +14 -3
  248. package/src/action/client/subscription/SustainedSubscription.ts +6 -9
  249. package/src/action/request/Invoke.ts +11 -4
  250. package/src/action/request/Read.ts +3 -2
  251. package/src/action/request/Specifier.ts +4 -1
  252. package/src/action/request/Write.ts +11 -2
  253. package/src/action/response/ReadResult.ts +1 -1
  254. package/src/cluster/client/ClusterClientTypes.ts +47 -7
  255. package/src/cluster/client/index.ts +0 -3
  256. package/src/interaction/InteractionMessenger.ts +5 -4
  257. package/src/interaction/SubscriptionClient.ts +2 -1
  258. package/src/interaction/index.ts +1 -1
  259. package/src/peer/CommissioningError.ts +13 -0
  260. package/src/peer/ControllerCommissioner.ts +21 -13
  261. package/src/peer/ControllerCommissioningFlow.ts +418 -186
  262. package/src/peer/ControllerDiscovery.ts +4 -1
  263. package/src/peer/InteractionQueue.ts +2 -2
  264. package/src/peer/PeerAddressStore.ts +0 -9
  265. package/src/peer/PeerSet.ts +56 -23
  266. package/src/peer/PhysicalDeviceProperties.ts +1 -1
  267. package/src/peer/index.ts +1 -0
  268. package/src/protocol/DeviceCommissioner.ts +0 -1
  269. package/src/protocol/ExchangeManager.ts +2 -2
  270. package/src/protocol/ExchangeProvider.ts +9 -7
  271. package/src/session/NodeSession.ts +5 -4
  272. package/src/session/Session.ts +8 -4
  273. package/src/session/SessionManager.ts +19 -2
  274. package/dist/cjs/cluster/client/AttributeClient.d.ts +0 -75
  275. package/dist/cjs/cluster/client/AttributeClient.d.ts.map +0 -1
  276. package/dist/cjs/cluster/client/AttributeClient.js +0 -209
  277. package/dist/cjs/cluster/client/AttributeClient.js.map +0 -6
  278. package/dist/cjs/cluster/client/ClusterClient.d.ts +0 -11
  279. package/dist/cjs/cluster/client/ClusterClient.d.ts.map +0 -1
  280. package/dist/cjs/cluster/client/ClusterClient.js +0 -335
  281. package/dist/cjs/cluster/client/ClusterClient.js.map +0 -6
  282. package/dist/cjs/cluster/client/EventClient.d.ts +0 -33
  283. package/dist/cjs/cluster/client/EventClient.d.ts.map +0 -1
  284. package/dist/cjs/cluster/client/EventClient.js +0 -89
  285. package/dist/cjs/cluster/client/EventClient.js.map +0 -6
  286. package/dist/cjs/interaction/InteractionClient.d.ts +0 -375
  287. package/dist/cjs/interaction/InteractionClient.d.ts.map +0 -1
  288. package/dist/cjs/interaction/InteractionClient.js +0 -1046
  289. package/dist/cjs/interaction/InteractionClient.js.map +0 -6
  290. package/dist/esm/cluster/client/AttributeClient.d.ts +0 -75
  291. package/dist/esm/cluster/client/AttributeClient.d.ts.map +0 -1
  292. package/dist/esm/cluster/client/AttributeClient.js +0 -189
  293. package/dist/esm/cluster/client/AttributeClient.js.map +0 -6
  294. package/dist/esm/cluster/client/ClusterClient.d.ts +0 -11
  295. package/dist/esm/cluster/client/ClusterClient.d.ts.map +0 -1
  296. package/dist/esm/cluster/client/ClusterClient.js +0 -320
  297. package/dist/esm/cluster/client/ClusterClient.js.map +0 -6
  298. package/dist/esm/cluster/client/EventClient.d.ts +0 -33
  299. package/dist/esm/cluster/client/EventClient.d.ts.map +0 -1
  300. package/dist/esm/cluster/client/EventClient.js +0 -69
  301. package/dist/esm/cluster/client/EventClient.js.map +0 -6
  302. package/dist/esm/interaction/InteractionClient.d.ts +0 -375
  303. package/dist/esm/interaction/InteractionClient.d.ts.map +0 -1
  304. package/dist/esm/interaction/InteractionClient.js +0 -1047
  305. package/dist/esm/interaction/InteractionClient.js.map +0 -6
  306. package/src/cluster/client/AttributeClient.ts +0 -230
  307. package/src/cluster/client/ClusterClient.ts +0 -433
  308. package/src/cluster/client/EventClient.ts +0 -99
  309. package/src/interaction/InteractionClient.ts +0 -1614
@@ -4,6 +4,10 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { ClientInteraction } from "#action/client/ClientInteraction.js";
8
+ import { ClientRead } from "#action/client/ClientRead.js";
9
+ import { Invoke } from "#action/request/Invoke.js";
10
+ import { Read } from "#action/request/Read.js";
7
11
  import { Certificate } from "#certificate/kinds/Certificate.js";
8
12
  import { BasicInformation } from "#clusters/basic-information";
9
13
  import { Descriptor } from "#clusters/descriptor";
@@ -16,9 +20,9 @@ import {
16
20
  ChannelType,
17
21
  Diagnostic,
18
22
  Duration,
23
+ ImplementationError,
19
24
  Instant,
20
25
  Logger,
21
- MatterError,
22
26
  Millis,
23
27
  Minutes,
24
28
  repackErrorAs,
@@ -33,17 +37,17 @@ import {
33
37
  ClusterType,
34
38
  EndpointNumber,
35
39
  FabricIndex,
40
+ Status,
36
41
  StatusResponseError,
37
42
  TypeFromPartialBitSchema,
38
43
  TypeFromSchema,
39
44
  VendorId,
40
45
  } from "#types";
41
46
  import { CertificateAuthority } from "../certificate/CertificateAuthority.js";
42
- import { ClusterClient } from "../cluster/client/ClusterClient.js";
43
47
  import { ClusterClientObj } from "../cluster/client/ClusterClientTypes.js";
44
48
  import { TlvCertSigningRequest } from "../common/OperationalCredentialsTypes.js";
45
49
  import { Fabric } from "../fabric/Fabric.js";
46
- import { InteractionClient } from "../interaction/InteractionClient.js";
50
+ import { CommissioningError } from "./CommissioningError.js";
47
51
  import { PeerAddress } from "./PeerAddress.js";
48
52
 
49
53
  const logger = Logger.get("ControllerCommissioner");
@@ -146,12 +150,6 @@ type CollectedCommissioningData = {
146
150
  fabricIndex?: FabricIndex;
147
151
  };
148
152
 
149
- /**
150
- * Error that throws when Commissioning fails and a process cannot be continued, and no more specific error
151
- * information is available.
152
- */
153
- export class CommissioningError extends MatterError {}
154
-
155
153
  /** The number of fabrics that can be commissioned is already reached. */
156
154
  export class MaximumCommissionedFabricsReachedError extends CommissioningError {}
157
155
 
@@ -176,9 +174,6 @@ export class ThreadNetworkSetupFailedError extends CommissioningError {}
176
174
  /** Error that throws when the NodeId is already used in the fabric. */
177
175
  export class NodeIdConflictError extends CommissioningError {}
178
176
 
179
- /** Error that throws when the device could not be discovered using the provided details. */
180
- export class CommissionableDeviceDiscoveryFailedError extends CommissioningError {}
181
-
182
177
  /** Error that throws when the device could not be connected using the operational discovery and no session could be created. */
183
178
  export class OperativeConnectionFailedError extends CommissioningError {}
184
179
 
@@ -187,17 +182,19 @@ class RecoverableCommissioningError extends CommissioningError {}
187
182
 
188
183
  const DEFAULT_FAILSAFE_TIME = Minutes.one;
189
184
 
185
+ const RootEndpointNumber = EndpointNumber(0);
186
+
190
187
  /**
191
188
  * Class to abstract the Device commission flow in a step wise way as defined in Specs. The specs are not 100%
192
189
  */
193
190
  export class ControllerCommissioningFlow {
194
- protected interactionClient: InteractionClient;
191
+ protected interaction: ClientInteraction;
195
192
  protected readonly ca: CertificateAuthority;
196
193
  protected readonly fabric: Fabric;
197
194
  protected readonly transitionToCase: (
198
195
  peerAddress: PeerAddress,
199
196
  supportsConcurrentConnections: boolean,
200
- ) => Promise<InteractionClient | undefined>;
197
+ ) => Promise<ClientInteraction | undefined>;
201
198
  protected readonly commissioningOptions: ControllerCommissioningFlowOptions;
202
199
  protected readonly commissioningSteps = new Array<CommissioningStep>();
203
200
  protected readonly commissioningStepResults = new Map<string, CommissioningStepResult>();
@@ -210,8 +207,8 @@ export class ControllerCommissioningFlow {
210
207
  #defaultFailSafeTime = DEFAULT_FAILSAFE_TIME;
211
208
 
212
209
  constructor(
213
- /** InteractionClient for the initiated PASE session */
214
- interactionClient: InteractionClient,
210
+ /** ClientInteraction for the initiated PASE session */
211
+ interaction: ClientInteraction,
215
212
 
216
213
  /** CertificateAuthority of the controller. */
217
214
  ca: CertificateAuthority,
@@ -226,9 +223,9 @@ export class ControllerCommissioningFlow {
226
223
  transitionToCase: (
227
224
  peerAddress: PeerAddress,
228
225
  supportsConcurrentConnections: boolean,
229
- ) => Promise<InteractionClient | undefined>,
226
+ ) => Promise<ClientInteraction | undefined>,
230
227
  ) {
231
- this.interactionClient = interactionClient;
228
+ this.interaction = interaction;
232
229
  this.ca = ca;
233
230
  this.fabric = fabric;
234
231
  this.transitionToCase = transitionToCase;
@@ -327,28 +324,65 @@ export class ControllerCommissioningFlow {
327
324
  }
328
325
 
329
326
  /**
330
- * Helper method to create ClusterClients. If not feature specific and for the Root Endpoint they are also reused.
327
+ * Convenience method to get a number of attributes in a read and return exactly these values in the order as
328
+ * defined in the request
331
329
  */
332
- #getClusterClient<const T extends ClusterType>(
333
- cluster: T,
334
- endpointId = EndpointNumber(0),
335
- isFeatureSpecific = false,
336
- ): ClusterClientObj<T> {
337
- if (!isFeatureSpecific && endpointId === 0) {
338
- const clusterClient = this.#clusterClients.get(cluster.id);
339
- if (clusterClient !== undefined) {
340
- logger.debug(
341
- `Returning existing cluster client for cluster ${cluster.name} (endpoint ${endpointId}, isFeatureSpecific ${isFeatureSpecific})`,
342
- );
343
- return clusterClient as ClusterClientObj<T>;
330
+ async #readConcreteAttributeValues(request: ClientRead) {
331
+ const attributeMap = new Map<string, any>();
332
+ if (request.attributeRequests === undefined) {
333
+ throw new ImplementationError("Can only handle Attribute reads");
334
+ }
335
+
336
+ for (const { endpointId, clusterId, attributeId } of request.attributeRequests) {
337
+ if (endpointId === undefined || clusterId === undefined) {
338
+ continue;
339
+ }
340
+ attributeMap.set(`${endpointId}-${clusterId}-${attributeId}`, undefined);
341
+ }
342
+ for await (const data of this.interaction.read(request)) {
343
+ for (const entry of data) {
344
+ if (entry.kind !== "attr-value") {
345
+ continue;
346
+ }
347
+ const {
348
+ path: { endpointId, clusterId, attributeId },
349
+ value,
350
+ } = entry;
351
+ const key = `${endpointId}-${clusterId}-${attributeId}`;
352
+ if (!attributeMap.has(key)) {
353
+ continue;
354
+ }
355
+ attributeMap.set(key, value);
356
+ }
357
+ }
358
+ return [...attributeMap.values()];
359
+ }
360
+
361
+ // TODO improve response typing
362
+ async #invokeCommand<const C extends ClusterType>(
363
+ request: Invoke.ConcreteCommandRequest<C>,
364
+ options: Omit<Invoke.Definition, "commands"> = {},
365
+ ) {
366
+ for await (const data of this.interaction.invoke(
367
+ Invoke({
368
+ commands: [request],
369
+ ...options,
370
+ }),
371
+ )) {
372
+ for (const entry of data) {
373
+ // We send only one command, so we only get one response back
374
+ switch (entry.kind) {
375
+ case "cmd-status":
376
+ if (entry.status !== Status.Success) {
377
+ throw StatusResponseError.create(entry.status, undefined, entry.clusterStatus);
378
+ }
379
+ return;
380
+
381
+ case "cmd-response":
382
+ return entry.data;
383
+ }
344
384
  }
345
385
  }
346
- logger.debug(
347
- `Creating new cluster client for cluster ${cluster.name} (endpoint ${endpointId}, isFeatureSpecific ${isFeatureSpecific})`,
348
- );
349
- const client = ClusterClient(cluster, endpointId, this.interactionClient);
350
- this.#clusterClients.set(cluster.id, client);
351
- return client;
352
386
  }
353
387
 
354
388
  /**
@@ -415,7 +449,7 @@ export class ControllerCommissioningFlow {
415
449
  });
416
450
 
417
451
  // Care about Network commissioning only when we are on BLE, because else we are already on IP network
418
- if (this.interactionClient.channelType === ChannelType.BLE) {
452
+ if (this.interaction.channelType === ChannelType.BLE) {
419
453
  this.commissioningSteps.push({
420
454
  stepNumber: 16,
421
455
  subStepNumber: 1,
@@ -442,7 +476,7 @@ export class ControllerCommissioningFlow {
442
476
  }
443
477
  } else {
444
478
  logger.info(
445
- `Skipping NetworkCommissioning steps because the device is already on IP network (${this.interactionClient.channelType})`,
479
+ `Skipping NetworkCommissioning steps because the device is already on IP network (${this.interaction.channelType})`,
446
480
  );
447
481
  }
448
482
 
@@ -533,31 +567,62 @@ export class ControllerCommissioningFlow {
533
567
  * Initial Step to receive some common data used by other steps
534
568
  */
535
569
  async #getInitialData() {
536
- const operationalCredentialsClient = this.#getClusterClient(OperationalCredentials.Cluster);
537
- const supportedFabrics = await operationalCredentialsClient.getSupportedFabricsAttribute();
538
- const commissionedFabrics = await operationalCredentialsClient.getCommissionedFabricsAttribute();
570
+ const [
571
+ supportedFabrics,
572
+ commissionedFabrics,
573
+ rootPartsList,
574
+ rootServerList,
575
+ vendorId,
576
+ productId,
577
+ productName,
578
+ supportsConcurrentConnection,
579
+ ] = await this.#readConcreteAttributeValues(
580
+ Read(
581
+ Read.Attribute({
582
+ endpoint: RootEndpointNumber,
583
+ cluster: OperationalCredentials.Complete,
584
+ attributes: ["supportedFabrics", "commissionedFabrics"],
585
+ }),
586
+ Read.Attribute({
587
+ endpoint: RootEndpointNumber,
588
+ cluster: Descriptor.Complete,
589
+ attributes: ["partsList", "serverList"],
590
+ }),
591
+ Read.Attribute({
592
+ endpoint: RootEndpointNumber,
593
+ cluster: BasicInformation.Complete,
594
+ attributes: ["vendorId", "productId", "productName"],
595
+ }),
596
+ Read.Attribute({
597
+ endpoint: RootEndpointNumber,
598
+ cluster: GeneralCommissioning.Complete,
599
+ attributes: ["supportsConcurrentConnection"],
600
+ }),
601
+ ),
602
+ );
603
+
539
604
  if (commissionedFabrics >= supportedFabrics) {
540
605
  throw new MaximumCommissionedFabricsReachedError(
541
606
  `Commissioned fabrics (${commissionedFabrics}) exceed supported fabrics (${supportedFabrics}). Please remove some fabrics before commissioning.`,
542
607
  );
543
608
  }
544
609
 
545
- const descriptorClient = this.#getClusterClient(Descriptor.Cluster);
546
- this.collectedCommissioningData.rootPartsList = await descriptorClient.getPartsListAttribute();
547
- this.collectedCommissioningData.rootServerList = await descriptorClient.getServerListAttribute();
610
+ this.collectedCommissioningData.rootPartsList = rootPartsList;
611
+ this.collectedCommissioningData.rootServerList = rootServerList;
548
612
 
549
- const networkData = await this.interactionClient.getMultipleAttributes({
550
- attributes: [
551
- {
552
- clusterId: NetworkCommissioning.Complete.id,
553
- attributeId: NetworkCommissioning.Complete.attributes.featureMap.id,
554
- },
555
- {
556
- clusterId: NetworkCommissioning.Complete.id,
557
- attributeId: NetworkCommissioning.Complete.attributes.networks.id,
558
- },
559
- ],
560
- });
613
+ this.collectedCommissioningData.vendorId = vendorId;
614
+ this.collectedCommissioningData.productId = productId;
615
+ this.collectedCommissioningData.productName = productName;
616
+ this.collectedCommissioningData.supportsConcurrentConnection = supportsConcurrentConnection;
617
+
618
+ const networkData = this.interaction.read(
619
+ Read(
620
+ Read.Attribute({
621
+ cluster: NetworkCommissioning.Complete,
622
+ attributes: ["featureMap", "networks"],
623
+ }),
624
+ ),
625
+ );
561
626
  const networkFeatures = new Array<{
562
627
  endpointId: number;
563
628
  value: TypeFromPartialBitSchema<typeof NetworkCommissioning.Complete.features>;
@@ -566,28 +631,33 @@ export class ControllerCommissioningFlow {
566
631
  endpointId: number;
567
632
  value: TypeFromSchema<typeof NetworkCommissioning.TlvNetworkInfo>[];
568
633
  }>();
569
- for (const {
570
- path: { endpointId, attributeId },
571
- value,
572
- } of networkData) {
573
- if (attributeId === NetworkCommissioning.Complete.attributes.featureMap.id) {
574
- networkFeatures.push({ endpointId, value });
575
- } else if (attributeId === NetworkCommissioning.Complete.attributes.networks.id) {
576
- networkStatus.push({ endpointId, value });
634
+
635
+ for await (const data of networkData) {
636
+ for (const entry of data) {
637
+ if (entry.kind !== "attr-value") {
638
+ continue;
639
+ }
640
+ const {
641
+ path: { endpointId, attributeId },
642
+ value,
643
+ } = entry;
644
+ if (attributeId === NetworkCommissioning.Complete.attributes.featureMap.id) {
645
+ networkFeatures.push({
646
+ endpointId,
647
+ value: value as TypeFromPartialBitSchema<typeof NetworkCommissioning.Complete.features>,
648
+ });
649
+ } else if (attributeId === NetworkCommissioning.Complete.attributes.networks.id) {
650
+ networkStatus.push({
651
+ endpointId,
652
+ value: value as TypeFromSchema<typeof NetworkCommissioning.TlvNetworkInfo>[],
653
+ });
654
+ }
577
655
  }
578
656
  }
657
+
579
658
  this.collectedCommissioningData.networkFeatures = networkFeatures;
580
659
  this.collectedCommissioningData.networkStatus = networkStatus;
581
660
 
582
- const basicInfoClient = this.#getClusterClient(BasicInformation.Cluster);
583
- this.collectedCommissioningData.vendorId = await basicInfoClient.getVendorIdAttribute();
584
- this.collectedCommissioningData.productId = await basicInfoClient.getProductIdAttribute();
585
- this.collectedCommissioningData.productName = await basicInfoClient.getProductNameAttribute();
586
-
587
- const generalCommissioningClient = this.#getClusterClient(GeneralCommissioning.Cluster);
588
- this.collectedCommissioningData.supportsConcurrentConnection =
589
- await generalCommissioningClient.getSupportsConcurrentConnectionAttribute();
590
-
591
661
  return {
592
662
  code: CommissioningStepResultCode.Success,
593
663
  breadcrumb: this.lastBreadcrumb,
@@ -604,9 +674,17 @@ export class ControllerCommissioningFlow {
604
674
  * Attribute”) prior to invoking the ArmFailSafe command.
605
675
  */
606
676
  async #armFailsafe(time?: Duration) {
607
- const client = this.#getClusterClient(GeneralCommissioning.Cluster);
608
677
  if (this.collectedCommissioningData.basicCommissioningInfo === undefined) {
609
- const basicCommissioningInfo = await client.getBasicCommissioningInfoAttribute();
678
+ const [basicCommissioningInfo] = await this.#readConcreteAttributeValues(
679
+ Read(
680
+ Read.Attribute({
681
+ endpoint: RootEndpointNumber,
682
+ cluster: GeneralCommissioning.Complete,
683
+ attributes: ["basicCommissioningInfo"],
684
+ }),
685
+ ),
686
+ );
687
+
610
688
  this.collectedCommissioningData.basicCommissioningInfo = basicCommissioningInfo;
611
689
  this.#defaultFailSafeTime = Seconds(basicCommissioningInfo.failSafeExpiryLengthSeconds);
612
690
  this.#commissioningStartedTime = Time.nowMs;
@@ -617,9 +695,14 @@ export class ControllerCommissioningFlow {
617
695
  const expiryLength = time ?? this.#defaultFailSafeTime;
618
696
  this.#ensureGeneralCommissioningSuccess(
619
697
  "armFailSafe",
620
- await client.armFailSafe({
621
- breadcrumb: this.lastBreadcrumb,
622
- expiryLengthSeconds: Seconds.of(expiryLength),
698
+ await this.#invokeCommand({
699
+ endpoint: RootEndpointNumber,
700
+ cluster: GeneralCommissioning.Complete,
701
+ command: "armFailSafe",
702
+ fields: {
703
+ breadcrumb: this.lastBreadcrumb,
704
+ expiryLengthSeconds: Seconds.of(expiryLength),
705
+ },
623
706
  }),
624
707
  );
625
708
  this.#currentFailSafeEndTime = Timestamp(Time.nowMs + expiryLength);
@@ -637,24 +720,28 @@ export class ControllerCommissioningFlow {
637
720
  }
638
721
 
639
722
  async #ensureFailsafeTimerFor(maxProcessingTime: Duration) {
640
- const minFailsafeTime = this.interactionClient.maximumPeerResponseTime(maxProcessingTime);
723
+ const minFailsafeTime = this.interaction.maximumPeerResponseTime(maxProcessingTime);
641
724
 
642
725
  const timeLeft = this.#failSafeTimeLeft;
643
726
  if (timeLeft < minFailsafeTime) {
644
727
  logger.debug(`Failsafe timer has only ${timeLeft}s left, re-arming for at least ${minFailsafeTime}`);
645
728
  await this.#armFailsafe(Duration.max(minFailsafeTime, this.#defaultFailSafeTime));
646
729
  } else {
647
- logger.debug(`Failsafe timer is already set for at least ${timeLeft}s`);
730
+ logger.debug(`Failsafe timer is already set for at least ${Seconds.of(timeLeft)}s`);
648
731
  }
649
732
  }
650
733
 
651
734
  async #resetFailsafeTimer() {
652
735
  if (this.#currentFailSafeEndTime === undefined) return;
653
736
  try {
654
- const client = this.#getClusterClient(GeneralCommissioning.Cluster);
655
- await client.armFailSafe({
656
- breadcrumb: this.lastBreadcrumb,
657
- expiryLengthSeconds: 0,
737
+ await this.#invokeCommand({
738
+ endpoint: RootEndpointNumber,
739
+ cluster: GeneralCommissioning.Complete,
740
+ command: "armFailSafe",
741
+ fields: {
742
+ breadcrumb: this.lastBreadcrumb,
743
+ expiryLengthSeconds: 0,
744
+ },
658
745
  });
659
746
  this.#currentFailSafeEndTime = undefined; // No failsafe active anymore
660
747
  } catch (error) {
@@ -682,8 +769,16 @@ export class ControllerCommissioningFlow {
682
769
  );
683
770
 
684
771
  if (hasRadioNetwork) {
685
- const client = this.#getClusterClient(GeneralCommissioning.Cluster);
686
- let locationCapability = await client.getLocationCapabilityAttribute();
772
+ let [locationCapability] = await this.#readConcreteAttributeValues(
773
+ Read(
774
+ Read.Attribute({
775
+ endpoint: RootEndpointNumber,
776
+ cluster: GeneralCommissioning.Complete,
777
+ attributes: ["locationCapability"],
778
+ }),
779
+ ),
780
+ );
781
+
687
782
  if (locationCapability === GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor) {
688
783
  locationCapability = this.commissioningOptions.regulatoryLocation;
689
784
  } else {
@@ -694,13 +789,20 @@ export class ControllerCommissioningFlow {
694
789
  );
695
790
  }
696
791
  let countryCode = this.commissioningOptions.regulatoryCountryCode;
697
- const regulatoryResult = await client.setRegulatoryConfig(
792
+ const regulatoryResult = await this.#invokeCommand(
698
793
  {
699
- breadcrumb: this.lastBreadcrumb++,
700
- newRegulatoryConfig: locationCapability,
701
- countryCode,
794
+ endpoint: RootEndpointNumber,
795
+ cluster: GeneralCommissioning.Complete,
796
+ command: "setRegulatoryConfig",
797
+ fields: {
798
+ breadcrumb: this.lastBreadcrumb++,
799
+ newRegulatoryConfig: locationCapability,
800
+ countryCode,
801
+ },
802
+ },
803
+ {
804
+ useExtendedFailSafeMessageResponseTimeout: true,
702
805
  },
703
- { useExtendedFailSafeMessageResponseTimeout: true },
704
806
  );
705
807
  if (
706
808
  regulatoryResult.errorCode === GeneralCommissioning.CommissioningError.ValueOutsideRange &&
@@ -712,13 +814,20 @@ export class ControllerCommissioningFlow {
712
814
  countryCode = "XX";
713
815
  this.#ensureGeneralCommissioningSuccess(
714
816
  "setRegulatoryConfig",
715
- await client.setRegulatoryConfig(
817
+ await this.#invokeCommand(
716
818
  {
717
- breadcrumb: this.lastBreadcrumb,
718
- newRegulatoryConfig: locationCapability,
719
- countryCode,
819
+ endpoint: RootEndpointNumber,
820
+ cluster: GeneralCommissioning.Complete,
821
+ command: "setRegulatoryConfig",
822
+ fields: {
823
+ breadcrumb: this.lastBreadcrumb,
824
+ newRegulatoryConfig: locationCapability,
825
+ countryCode,
826
+ },
827
+ },
828
+ {
829
+ useExtendedFailSafeMessageResponseTimeout: true,
720
830
  },
721
- { useExtendedFailSafeMessageResponseTimeout: true },
722
831
  ),
723
832
  );
724
833
  } else {
@@ -766,28 +875,50 @@ export class ControllerCommissioningFlow {
766
875
  * (see Section 6.2.3, “Device Attestation Procedure”).
767
876
  */
768
877
  async #deviceAttestation() {
769
- const operationalCredentialsClusterClient = this.#getClusterClient(OperationalCredentials.Cluster);
770
- const { certificate: deviceAttestation } = await operationalCredentialsClusterClient.certificateChainRequest(
878
+ const { certificate: deviceAttestation } = await this.#invokeCommand(
771
879
  {
772
- certificateType: OperationalCredentials.CertificateChainType.DacCertificate,
880
+ endpoint: RootEndpointNumber,
881
+ cluster: OperationalCredentials.Complete,
882
+ command: "certificateChainRequest",
883
+ fields: {
884
+ certificateType: OperationalCredentials.CertificateChainType.DacCertificate,
885
+ },
886
+ },
887
+ {
888
+ useExtendedFailSafeMessageResponseTimeout: true,
773
889
  },
774
- { useExtendedFailSafeMessageResponseTimeout: true },
775
890
  );
891
+
776
892
  // TODO: extract device public key from deviceAttestation
777
- const { certificate: productAttestation } = await operationalCredentialsClusterClient.certificateChainRequest(
893
+ const { certificate: productAttestation } = await this.#invokeCommand(
778
894
  {
779
- certificateType: OperationalCredentials.CertificateChainType.PaiCertificate,
895
+ endpoint: RootEndpointNumber,
896
+ cluster: OperationalCredentials.Complete,
897
+ command: "certificateChainRequest",
898
+ fields: {
899
+ certificateType: OperationalCredentials.CertificateChainType.PaiCertificate,
900
+ },
901
+ },
902
+ {
903
+ useExtendedFailSafeMessageResponseTimeout: true,
780
904
  },
781
- { useExtendedFailSafeMessageResponseTimeout: true },
782
905
  );
906
+
783
907
  // TODO: validate deviceAttestation and productAttestation
784
- const { attestationElements, attestationSignature } =
785
- await operationalCredentialsClusterClient.attestationRequest(
786
- {
908
+ const { attestationElements, attestationSignature } = await this.#invokeCommand(
909
+ {
910
+ endpoint: RootEndpointNumber,
911
+ cluster: OperationalCredentials.Complete,
912
+ command: "attestationRequest",
913
+ fields: {
787
914
  attestationNonce: this.fabric.crypto.randomBytes(32),
788
915
  },
789
- { useExtendedFailSafeMessageResponseTimeout: true },
790
- );
916
+ },
917
+ {
918
+ useExtendedFailSafeMessageResponseTimeout: true,
919
+ },
920
+ );
921
+
791
922
  // TODO: validate attestationSignature using device public key
792
923
  if (
793
924
  deviceAttestation.byteLength === 0 ||
@@ -823,12 +954,18 @@ export class ControllerCommissioningFlow {
823
954
  * DCL contains the name and other information of the Commissioner’s manufacturer.
824
955
  */
825
956
  async #certificates() {
826
- const operationalCredentialsClusterClient = this.#getClusterClient(OperationalCredentials.Cluster);
827
- const { nocsrElements, attestationSignature: csrSignature } =
828
- await operationalCredentialsClusterClient.csrRequest(
829
- { csrNonce: this.fabric.crypto.randomBytes(32) },
830
- { useExtendedFailSafeMessageResponseTimeout: true },
831
- );
957
+ const { nocsrElements, attestationSignature: csrSignature } = await this.#invokeCommand(
958
+ {
959
+ endpoint: RootEndpointNumber,
960
+ cluster: OperationalCredentials.Complete,
961
+ command: "csrRequest",
962
+ fields: { csrNonce: this.fabric.crypto.randomBytes(32) },
963
+ },
964
+ {
965
+ useExtendedFailSafeMessageResponseTimeout: true,
966
+ },
967
+ );
968
+
832
969
  if (nocsrElements.byteLength === 0 || csrSignature.byteLength === 0) {
833
970
  // TODO: validate the data really
834
971
  throw new UnexpectedDataError("Invalid response from device");
@@ -837,27 +974,42 @@ export class ControllerCommissioningFlow {
837
974
  const { certSigningRequest } = TlvCertSigningRequest.decode(nocsrElements);
838
975
  const operationalPublicKey = await Certificate.getPublicKeyFromCsr(this.ca.crypto, certSigningRequest);
839
976
 
840
- await operationalCredentialsClusterClient.addTrustedRootCertificate(
977
+ await this.#invokeCommand(
841
978
  {
842
- rootCaCertificate: this.ca.rootCert,
979
+ endpoint: RootEndpointNumber,
980
+ cluster: OperationalCredentials.Complete,
981
+ command: "addTrustedRootCertificate",
982
+ fields: {
983
+ rootCaCertificate: this.ca.rootCert,
984
+ },
985
+ },
986
+ {
987
+ useExtendedFailSafeMessageResponseTimeout: true,
843
988
  },
844
- { useExtendedFailSafeMessageResponseTimeout: true },
845
989
  );
990
+
846
991
  const peerOperationalCert = await this.ca.generateNoc(
847
992
  operationalPublicKey,
848
993
  this.fabric.fabricId,
849
- this.interactionClient.address.nodeId,
994
+ this.interaction.address.nodeId,
850
995
  );
851
996
 
852
- const addNocResponse = await operationalCredentialsClusterClient.addNoc(
997
+ const addNocResponse = await this.#invokeCommand(
853
998
  {
854
- nocValue: peerOperationalCert,
855
- icacValue: this.ca.icacCert ?? new Uint8Array(0),
856
- ipkValue: this.fabric.identityProtectionKey,
857
- adminVendorId: this.fabric.rootVendorId,
858
- caseAdminSubject: this.fabric.rootNodeId,
999
+ endpoint: RootEndpointNumber,
1000
+ cluster: OperationalCredentials.Complete,
1001
+ command: "addNoc",
1002
+ fields: {
1003
+ nocValue: peerOperationalCert,
1004
+ icacValue: this.ca.icacCert ?? new Uint8Array(0),
1005
+ ipkValue: this.fabric.identityProtectionKey,
1006
+ adminVendorId: this.fabric.rootVendorId,
1007
+ caseAdminSubject: this.fabric.rootNodeId,
1008
+ },
1009
+ },
1010
+ {
1011
+ useExtendedFailSafeMessageResponseTimeout: true,
859
1012
  },
860
- { useExtendedFailSafeMessageResponseTimeout: true },
861
1013
  );
862
1014
 
863
1015
  this.#ensureOperationalCredentialsSuccess("addNoc", addNocResponse);
@@ -887,13 +1039,17 @@ export class ControllerCommissioningFlow {
887
1039
  breadcrumb: this.lastBreadcrumb,
888
1040
  };
889
1041
  }
890
- const operationalCredentialCluster = this.#getClusterClient(OperationalCredentials.Cluster);
891
1042
  try {
892
1043
  this.#ensureOperationalCredentialsSuccess(
893
1044
  "updateFabricLabel",
894
- await operationalCredentialCluster.updateFabricLabel({
895
- label: this.fabric.label,
896
- fabricIndex,
1045
+ await this.#invokeCommand({
1046
+ endpoint: RootEndpointNumber,
1047
+ cluster: OperationalCredentials.Complete,
1048
+ command: "updateFabricLabel",
1049
+ fields: {
1050
+ label: this.fabric.label,
1051
+ fabricIndex,
1052
+ },
897
1053
  }),
898
1054
  );
899
1055
  } catch (error) {
@@ -915,7 +1071,7 @@ export class ControllerCommissioningFlow {
915
1071
  * its desired access control policies.
916
1072
  */
917
1073
  async #configureAccessControlLists() {
918
- // Standard entry is sufficient in our case
1074
+ // Standard entry is enough in our case
919
1075
 
920
1076
  return {
921
1077
  code: CommissioningStepResultCode.Skipped,
@@ -1018,27 +1174,39 @@ export class ControllerCommissioningFlow {
1018
1174
  }
1019
1175
 
1020
1176
  logger.debug("Configuring WiFi network ...");
1021
- const networkCommissioningClusterClient = this.#getClusterClient(
1022
- NetworkCommissioning.Cluster.with("WiFiNetworkInterface"),
1023
- EndpointNumber(0),
1024
- true,
1025
- );
1026
1177
  const ssid = Bytes.fromString(this.commissioningOptions.wifiNetwork.wifiSsid);
1027
1178
  const credentials = Bytes.fromString(this.commissioningOptions.wifiNetwork.wifiCredentials);
1028
1179
 
1180
+ const [scanMaxTimeSeconds, connectMaxTimeSeconds] = await this.#readConcreteAttributeValues(
1181
+ Read(
1182
+ Read.Attribute({
1183
+ endpoint: RootEndpointNumber,
1184
+ cluster: NetworkCommissioning.Complete,
1185
+ attributes: ["scanMaxTimeSeconds", "connectMaxTimeSeconds"],
1186
+ }),
1187
+ ),
1188
+ );
1189
+
1029
1190
  // Only Scan when the device supports concurrent connections
1030
1191
  if (this.collectedCommissioningData.supportsConcurrentConnection !== false) {
1031
- const scanMaxTime = Seconds(await networkCommissioningClusterClient.getScanMaxTimeSecondsAttribute());
1032
- await this.#ensureFailsafeTimerFor(scanMaxTime);
1192
+ // TODO add message transmission time
1193
+ await this.#ensureFailsafeTimerFor(Seconds(scanMaxTimeSeconds));
1033
1194
 
1034
- const { networkingStatus, wiFiScanResults, debugText } =
1035
- await networkCommissioningClusterClient.scanNetworks(
1036
- {
1195
+ const { networkingStatus, wiFiScanResults, debugText } = await this.#invokeCommand(
1196
+ {
1197
+ endpoint: RootEndpointNumber,
1198
+ cluster: NetworkCommissioning.Complete,
1199
+ command: "scanNetworks",
1200
+ fields: {
1037
1201
  ssid,
1038
1202
  breadcrumb: this.lastBreadcrumb++,
1039
1203
  },
1040
- { expectedProcessingTime: scanMaxTime },
1041
- );
1204
+ },
1205
+ {
1206
+ expectedProcessingTime: Seconds(scanMaxTimeSeconds),
1207
+ },
1208
+ );
1209
+
1042
1210
  if (networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
1043
1211
  throw new WifiNetworkSetupFailedError(`Commissionee failed to scan for WiFi networks: ${debugText}`);
1044
1212
  }
@@ -1053,14 +1221,22 @@ export class ControllerCommissioningFlow {
1053
1221
  networkingStatus: addNetworkingStatus,
1054
1222
  debugText: addDebugText,
1055
1223
  networkIndex,
1056
- } = await networkCommissioningClusterClient.addOrUpdateWiFiNetwork(
1224
+ } = await this.#invokeCommand(
1225
+ {
1226
+ endpoint: RootEndpointNumber,
1227
+ cluster: NetworkCommissioning.Complete,
1228
+ command: "addOrUpdateWiFiNetwork",
1229
+ fields: {
1230
+ ssid,
1231
+ credentials,
1232
+ breadcrumb: this.lastBreadcrumb++,
1233
+ },
1234
+ },
1057
1235
  {
1058
- ssid,
1059
- credentials,
1060
- breadcrumb: this.lastBreadcrumb++,
1236
+ useExtendedFailSafeMessageResponseTimeout: true,
1061
1237
  },
1062
- { useExtendedFailSafeMessageResponseTimeout: true },
1063
1238
  );
1239
+
1064
1240
  if (addNetworkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
1065
1241
  throw new WifiNetworkSetupFailedError(`Commissionee failed to add WiFi network: ${addDebugText}`);
1066
1242
  }
@@ -1071,7 +1247,15 @@ export class ControllerCommissioningFlow {
1071
1247
  `Commissionee added WiFi network ${this.commissioningOptions.wifiNetwork.wifiSsid} with network index ${networkIndex}`,
1072
1248
  );
1073
1249
 
1074
- const updatedNetworks = await networkCommissioningClusterClient.getNetworksAttribute();
1250
+ const [updatedNetworks] = await this.#readConcreteAttributeValues(
1251
+ Read(
1252
+ Read.Attribute({
1253
+ endpoint: RootEndpointNumber,
1254
+ cluster: NetworkCommissioning.Complete,
1255
+ attributes: ["networks"],
1256
+ }),
1257
+ ),
1258
+ );
1075
1259
  if (updatedNetworks[networkIndex] === undefined) {
1076
1260
  throw new WifiNetworkSetupFailedError(`Commissionee did not return network with index ${networkIndex}`);
1077
1261
  }
@@ -1089,15 +1273,22 @@ export class ControllerCommissioningFlow {
1089
1273
  };
1090
1274
  }
1091
1275
 
1092
- const connectMaxTime = Seconds(await networkCommissioningClusterClient.getConnectMaxTimeSecondsAttribute());
1093
- await this.#ensureFailsafeTimerFor(connectMaxTime);
1276
+ // TODO Add retransmission time
1277
+ await this.#ensureFailsafeTimerFor(Seconds(connectMaxTimeSeconds));
1094
1278
 
1095
- const connectResult = await networkCommissioningClusterClient.connectNetwork(
1279
+ const connectResult = await this.#invokeCommand(
1096
1280
  {
1097
- networkId: networkId,
1098
- breadcrumb: this.lastBreadcrumb++,
1281
+ endpoint: RootEndpointNumber,
1282
+ cluster: NetworkCommissioning.Complete,
1283
+ command: "connectNetwork",
1284
+ fields: {
1285
+ networkId: networkId,
1286
+ breadcrumb: this.lastBreadcrumb++,
1287
+ },
1288
+ },
1289
+ {
1290
+ expectedProcessingTime: Seconds(connectMaxTimeSeconds),
1099
1291
  },
1100
- { expectedProcessingTime: connectMaxTime },
1101
1292
  );
1102
1293
 
1103
1294
  if (connectResult.networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
@@ -1165,22 +1356,34 @@ export class ControllerCommissioningFlow {
1165
1356
  }
1166
1357
 
1167
1358
  logger.debug("Configuring Thread network ...");
1168
- const networkCommissioningClusterClient = this.#getClusterClient(
1169
- NetworkCommissioning.Cluster.with("ThreadNetworkInterface"),
1170
- EndpointNumber(0),
1171
- true,
1359
+ const [scanMaxTimeSeconds, connectMaxTimeSeconds] = await this.#readConcreteAttributeValues(
1360
+ Read(
1361
+ Read.Attribute({
1362
+ endpoint: RootEndpointNumber,
1363
+ cluster: NetworkCommissioning.Complete,
1364
+ attributes: ["scanMaxTimeSeconds", "connectMaxTimeSeconds"],
1365
+ }),
1366
+ ),
1172
1367
  );
1173
1368
 
1174
- // Only Scan when the device supports concurrent connections
1175
- if (this.collectedCommissioningData.supportsConcurrentConnection !== false) {
1176
- const scanMaxTime = Seconds(await networkCommissioningClusterClient.getScanMaxTimeSecondsAttribute());
1177
- await this.#ensureFailsafeTimerFor(scanMaxTime);
1369
+ if (!this.commissioningOptions.threadNetwork?.networkName) {
1370
+ logger.info("Thread network name is not configured. Skip scanning for it.");
1371
+ } else if (this.collectedCommissioningData.supportsConcurrentConnection !== false) {
1372
+ // Only Scan when the device supports concurrent connections
1373
+ await this.#ensureFailsafeTimerFor(Seconds(scanMaxTimeSeconds));
1374
+
1375
+ const { networkingStatus, threadScanResults, debugText } = (await this.#invokeCommand(
1376
+ {
1377
+ endpoint: RootEndpointNumber,
1378
+ cluster: NetworkCommissioning.Complete,
1379
+ command: "scanNetworks",
1380
+ fields: { breadcrumb: this.lastBreadcrumb++ },
1381
+ },
1382
+ {
1383
+ expectedProcessingTime: Seconds(scanMaxTimeSeconds),
1384
+ },
1385
+ )) as NetworkCommissioning.ScanNetworksResponse;
1178
1386
 
1179
- const { networkingStatus, threadScanResults, debugText } =
1180
- await networkCommissioningClusterClient.scanNetworks(
1181
- { breadcrumb: this.lastBreadcrumb++ },
1182
- { expectedProcessingTime: scanMaxTime },
1183
- );
1184
1387
  if (networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
1185
1388
  throw new ThreadNetworkSetupFailedError(
1186
1389
  `Commissionee failed to scan for Thread networks: ${debugText}`,
@@ -1212,13 +1415,21 @@ export class ControllerCommissioningFlow {
1212
1415
  networkingStatus: addNetworkingStatus,
1213
1416
  debugText: addDebugText,
1214
1417
  networkIndex,
1215
- } = await networkCommissioningClusterClient.addOrUpdateThreadNetwork(
1418
+ } = await this.#invokeCommand(
1216
1419
  {
1217
- operationalDataset: Bytes.fromHex(this.commissioningOptions.threadNetwork.operationalDataset),
1218
- breadcrumb: this.lastBreadcrumb++,
1420
+ endpoint: RootEndpointNumber,
1421
+ cluster: NetworkCommissioning.Complete,
1422
+ command: "addOrUpdateThreadNetwork",
1423
+ fields: {
1424
+ operationalDataset: Bytes.fromHex(this.commissioningOptions.threadNetwork.operationalDataset),
1425
+ breadcrumb: this.lastBreadcrumb++,
1426
+ },
1427
+ },
1428
+ {
1429
+ useExtendedFailSafeMessageResponseTimeout: true,
1219
1430
  },
1220
- { useExtendedFailSafeMessageResponseTimeout: true },
1221
1431
  );
1432
+
1222
1433
  if (addNetworkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
1223
1434
  throw new ThreadNetworkSetupFailedError(`Commissionee failed to add Thread network: ${addDebugText}`);
1224
1435
  }
@@ -1229,7 +1440,16 @@ export class ControllerCommissioningFlow {
1229
1440
  `Commissionee added Thread network ${this.commissioningOptions.threadNetwork.networkName} with network index ${networkIndex}`,
1230
1441
  );
1231
1442
 
1232
- const updatedNetworks = await networkCommissioningClusterClient.getNetworksAttribute();
1443
+ const updatedNetworks = await this.#readConcreteAttributeValues(
1444
+ Read(
1445
+ Read.Attribute({
1446
+ endpoint: RootEndpointNumber,
1447
+ cluster: NetworkCommissioning.Complete,
1448
+ attributes: ["networks"],
1449
+ }),
1450
+ ),
1451
+ );
1452
+
1233
1453
  if (updatedNetworks[networkIndex] === undefined) {
1234
1454
  throw new ThreadNetworkSetupFailedError(`Commissionee did not return network with index ${networkIndex}`);
1235
1455
  }
@@ -1246,15 +1466,21 @@ export class ControllerCommissioningFlow {
1246
1466
  };
1247
1467
  }
1248
1468
 
1249
- const connectMaxTime = Seconds(await networkCommissioningClusterClient.getConnectMaxTimeSecondsAttribute());
1250
- await this.#ensureFailsafeTimerFor(connectMaxTime);
1469
+ await this.#ensureFailsafeTimerFor(Seconds(connectMaxTimeSeconds));
1251
1470
 
1252
- const connectResult = await networkCommissioningClusterClient.connectNetwork(
1471
+ const connectResult = await this.#invokeCommand(
1472
+ {
1473
+ endpoint: RootEndpointNumber,
1474
+ cluster: NetworkCommissioning.Complete,
1475
+ command: "connectNetwork",
1476
+ fields: {
1477
+ networkId: networkId,
1478
+ breadcrumb: this.lastBreadcrumb++,
1479
+ },
1480
+ },
1253
1481
  {
1254
- networkId: networkId,
1255
- breadcrumb: this.lastBreadcrumb++,
1482
+ expectedProcessingTime: Seconds(connectMaxTimeSeconds),
1256
1483
  },
1257
- { expectedProcessingTime: connectMaxTime },
1258
1484
  );
1259
1485
 
1260
1486
  if (connectResult.networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
@@ -1314,10 +1540,10 @@ export class ControllerCommissioningFlow {
1314
1540
  reArmFailsafeInterval.start();
1315
1541
  }
1316
1542
 
1317
- let transitionResult: InteractionClient | undefined;
1543
+ let transitionResult: ClientInteraction | undefined;
1318
1544
  try {
1319
1545
  transitionResult = await this.transitionToCase(
1320
- this.interactionClient.address,
1546
+ this.interaction.address,
1321
1547
  // Assume concurrent connections are supported if not know (which should not be the case when we came here)
1322
1548
  isConcurrentFlow,
1323
1549
  );
@@ -1335,7 +1561,7 @@ export class ControllerCommissioningFlow {
1335
1561
  };
1336
1562
  }
1337
1563
 
1338
- this.interactionClient = transitionResult;
1564
+ this.interaction = transitionResult;
1339
1565
  this.#clusterClients.clear();
1340
1566
 
1341
1567
  logger.debug("Successfully reconnected with device ...");
@@ -1354,12 +1580,18 @@ export class ControllerCommissioningFlow {
1354
1580
  * the commissioning process.
1355
1581
  */
1356
1582
  async #completeCommissioning() {
1357
- const generalCommissioningClusterClient = this.#getClusterClient(GeneralCommissioning.Cluster);
1358
1583
  this.#ensureGeneralCommissioningSuccess(
1359
1584
  "commissioningComplete",
1360
- await generalCommissioningClusterClient.commissioningComplete(undefined, {
1361
- useExtendedFailSafeMessageResponseTimeout: true,
1362
- }),
1585
+ await this.#invokeCommand(
1586
+ {
1587
+ endpoint: RootEndpointNumber,
1588
+ cluster: GeneralCommissioning.Complete,
1589
+ command: "commissioningComplete",
1590
+ },
1591
+ {
1592
+ useExtendedFailSafeMessageResponseTimeout: true,
1593
+ },
1594
+ ),
1363
1595
  );
1364
1596
  this.#currentFailSafeEndTime = undefined; // gets deactivated when successful
1365
1597