@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,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { ClientRead } from "#action/client/ClientRead.js";
7
8
  import { Interactable, InteractionSession } from "#action/Interactable.js";
8
9
  import { ClientInvoke, Invoke } from "#action/request/Invoke.js";
9
10
  import { Read } from "#action/request/Read.js";
@@ -28,6 +29,8 @@ import {
28
29
  Minutes,
29
30
  RetrySchedule,
30
31
  Seconds,
32
+ Time,
33
+ TimeoutError,
31
34
  } from "#general";
32
35
  import { InteractionClientMessenger, MessageType } from "#interaction/InteractionMessenger.js";
33
36
  import { Subscription } from "#interaction/Subscription.js";
@@ -35,6 +38,7 @@ import { PeerAddress } from "#peer/index.js";
35
38
  import { ExchangeProvider } from "#protocol/ExchangeProvider.js";
36
39
  import { SecureSession } from "#session/SecureSession.js";
37
40
  import { Status, TlvAttributeReport, TlvNoResponse, TlvSubscribeResponse, TypeFromSchema } from "#types";
41
+ import { ClientWrite } from "./ClientWrite.js";
38
42
  import { InputChunk } from "./InputChunk.js";
39
43
  import { ClientSubscribe } from "./subscription/ClientSubscribe.js";
40
44
  import { ClientSubscription } from "./subscription/ClientSubscription.js";
@@ -53,6 +57,7 @@ export interface ClientInteractionContext {
53
57
  abort?: Abort.Signal;
54
58
  sustainRetries?: RetrySchedule.Configuration;
55
59
  exchangeProvider?: ExchangeProvider;
60
+ address?: PeerAddress;
56
61
  }
57
62
 
58
63
  export const DEFAULT_MIN_INTERVAL_FLOOR = Seconds(1);
@@ -74,16 +79,17 @@ const DEFAULT_MINIMUM_RESPONSE_TIMEOUT_WITH_FAILSAFE = Seconds(30);
74
79
  export class ClientInteraction<
75
80
  SessionT extends InteractionSession = InteractionSession,
76
81
  > implements Interactable<SessionT> {
77
- readonly #environment: Environment;
82
+ protected readonly environment: Environment;
78
83
  readonly #lifetime: Lifetime;
79
84
  readonly #exchanges: ExchangeProvider;
80
85
  readonly #interactions = new BasicSet<Read | Write | Invoke | Subscribe>();
81
86
  #subscriptions?: ClientSubscriptions;
82
87
  readonly #abort: Abort;
83
88
  readonly #sustainRetries: RetrySchedule;
89
+ readonly #address?: PeerAddress;
84
90
 
85
- constructor({ environment, abort, sustainRetries, exchangeProvider }: ClientInteractionContext) {
86
- this.#environment = environment;
91
+ constructor({ environment, abort, sustainRetries, exchangeProvider, address }: ClientInteractionContext) {
92
+ this.environment = environment;
87
93
  this.#exchanges = exchangeProvider ?? environment.get(ExchangeProvider);
88
94
  if (environment.has(ClientSubscriptions)) {
89
95
  this.#subscriptions = environment.get(ClientSubscriptions);
@@ -93,6 +99,7 @@ export class ClientInteraction<
93
99
  environment.get(Entropy),
94
100
  RetrySchedule.Configuration(SustainedSubscription.DefaultRetrySchedule, sustainRetries),
95
101
  );
102
+ this.#address = address;
96
103
 
97
104
  this.#lifetime = environment.join("interactions");
98
105
  Object.defineProperties(this.#lifetime.details, {
@@ -126,7 +133,7 @@ export class ClientInteraction<
126
133
 
127
134
  get subscriptions() {
128
135
  if (this.#subscriptions === undefined) {
129
- this.#subscriptions = this.#environment.get(ClientSubscriptions);
136
+ this.#subscriptions = this.environment.get(ClientSubscriptions);
130
137
  }
131
138
  return this.#subscriptions;
132
139
  }
@@ -134,7 +141,7 @@ export class ClientInteraction<
134
141
  /**
135
142
  * Read attributes and events.
136
143
  */
137
- async *read(request: Read, session?: SessionT): ReadResult {
144
+ async *read(request: ClientRead, session?: SessionT): ReadResult {
138
145
  const readPathsCount = (request.attributeRequests?.length ?? 0) + (request.eventRequests?.length ?? 0);
139
146
  if (readPathsCount === 0) {
140
147
  throw new ImplementationError("When reading attributes and events, at least one must be specified.");
@@ -182,7 +189,7 @@ export class ClientInteraction<
182
189
  * Writes with the Matter protocol are generally not atomic, so this method only throws if the entire action fails.
183
190
  * You must check each {@link WriteResult.AttributeStatus} to determine whether individual updates failed.
184
191
  */
185
- async write<T extends Write>(request: T, session?: SessionT): WriteResult<T> {
192
+ async write<T extends ClientWrite>(request: T, session?: SessionT): WriteResult<T> {
186
193
  await using context = await this.#begin("writing", request, session);
187
194
  const { checkAbort, messenger } = context;
188
195
 
@@ -419,16 +426,6 @@ export class ClientInteraction<
419
426
  const responseMessage = await messenger.nextMessage(MessageType.SubscribeResponse);
420
427
  const response = TlvSubscribeResponse.decode(responseMessage.payload);
421
428
 
422
- logger.info(
423
- "Subscription successful",
424
- Mark.INBOUND,
425
- messenger.exchange.via,
426
- Diagnostic.dict({
427
- id: response.subscriptionId,
428
- interval: Duration.format(Seconds(response.maxInterval)),
429
- }),
430
- );
431
-
432
429
  const subscription = new PeerSubscription({
433
430
  lifetime: this.subscriptions,
434
431
  request,
@@ -440,6 +437,17 @@ export class ClientInteraction<
440
437
  });
441
438
  this.subscriptions.addPeer(subscription);
442
439
 
440
+ logger.info(
441
+ "Subscription successful",
442
+ Mark.INBOUND,
443
+ messenger.exchange.via,
444
+ Diagnostic.dict({
445
+ id: Subscription.idStrOf(response.subscriptionId),
446
+ interval: Duration.format(Seconds(response.maxInterval)),
447
+ timeout: Duration.format(subscription.timeout),
448
+ }),
449
+ );
450
+
443
451
  return subscription;
444
452
  };
445
453
 
@@ -482,13 +490,28 @@ export class ClientInteraction<
482
490
  if (this.#abort.aborted) {
483
491
  throw new ImplementationError("Client interaction unavailable after close");
484
492
  }
485
- this.#interactions.add(request);
486
493
 
487
494
  const checkAbort = Abort.checkerFor(session);
488
495
 
489
- const messenger = await InteractionClientMessenger.create(this.#exchanges);
496
+ const now = Time.nowMs;
497
+ let messenger: InteractionClientMessenger;
498
+ try {
499
+ messenger = await InteractionClientMessenger.create(this.#exchanges);
500
+ } catch (error) {
501
+ TimeoutError.accept(error);
502
+
503
+ // This logic implements a very basic automatic reconnection mechanism which is a bit like PairedNode
504
+ // The exchange creation fails only when the node is considered to be unavailable, so in this case we
505
+ // either try the last addresses again (if existing), or do a short-timed re-discovery. This would block
506
+ // the execution max 10s. What's missing is that one layer (like Sustained Subscription) would trigger a
507
+ // FullDiscovery instead of just a timed one, but for the tests and currently this should be enough.
508
+ await this.exchanges.reconnectChannel({ asOf: now, resetInitialState: true });
509
+ messenger = await InteractionClientMessenger.create(this.#exchanges);
510
+ }
511
+
512
+ this.#interactions.add(request);
490
513
 
491
- // Provide via dynamically so is up-to-date if exchange changes due to retry
514
+ // Provide via dynamically so is up to date if exchange changes due to retry
492
515
  Object.defineProperty(lifetime.details, "via", {
493
516
  get() {
494
517
  return messenger.exchange.via;
@@ -513,6 +536,22 @@ export class ClientInteraction<
513
536
 
514
537
  return context;
515
538
  }
539
+
540
+ get channelType() {
541
+ return this.#exchanges.channelType;
542
+ }
543
+
544
+ /** Calculates the current maximum response time for a message use in additional logic like timers. */
545
+ maximumPeerResponseTime(expectedProcessingTime?: Duration) {
546
+ return this.#exchanges.maximumPeerResponseTime(expectedProcessingTime);
547
+ }
548
+
549
+ get address() {
550
+ if (this.#address === undefined) {
551
+ throw new ImplementationError("This InteractionClient is not bound to a specific peer.");
552
+ }
553
+ return this.#address;
554
+ }
516
555
  }
517
556
 
518
557
  interface RequestContext {
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Read } from "#action/request/Read.js";
8
+ import { ClientRequest } from "./ClientRequest.js";
9
+
10
+ export interface ClientRead extends Read, ClientRequest {}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * Represents a client request with customizable transmission behavior.
9
+ */
10
+ export interface ClientRequest {
11
+ /**
12
+ * If true, the request will be queued over all peers of the node.
13
+ * If false, the request will be sent directly.
14
+ * If undefined, the request will be queued if the physical device is thread connected.
15
+ * TODO Adjust this to be owned by some internal network layer that maintains automatic limits per connection type
16
+ * or such
17
+ * @deprecated
18
+ */
19
+ queued?: boolean;
20
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Write } from "#action/request/Write.js";
8
+ import { ClientRequest } from "./ClientRequest.js";
9
+
10
+ export interface ClientWrite extends Write, ClientRequest {}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import {
7
+ ClientInvoke,
8
+ ClientSubscribe,
9
+ ClientWrite,
10
+ DecodedInvokeResult,
11
+ InteractionSession,
12
+ ReadResult,
13
+ SubscriptionResult,
14
+ WriteResult,
15
+ } from "#action/index.js";
16
+ import { InteractionQueue } from "#peer/index.js";
17
+ import { ClientInteraction, ClientInteractionContext } from "./ClientInteraction.js";
18
+ import { ClientRead } from "./ClientRead.js";
19
+
20
+ export interface QueuedClientInteractionContext extends ClientInteractionContext {
21
+ queue: InteractionQueue;
22
+ }
23
+
24
+ export class QueuedClientInteraction<
25
+ SessionT extends InteractionSession = InteractionSession,
26
+ > extends ClientInteraction<SessionT> {
27
+ #queue?: InteractionQueue;
28
+
29
+ constructor(options: QueuedClientInteractionContext) {
30
+ super(options);
31
+ this.#queue = options.queue;
32
+ }
33
+
34
+ protected get queue() {
35
+ if (this.#queue === undefined) {
36
+ this.#queue = this.environment.get(InteractionQueue);
37
+ }
38
+ return this.#queue;
39
+ }
40
+
41
+ /**
42
+ * Read chosen attributes remotely from the node. Known data versions are automatically injected into the request to
43
+ * optimize the read.
44
+ * Therefore, the returned data only contains attributes that have changed since the last read or subscription.
45
+ * TODO: Allow control of data version injection and enrich response with attribute data missing in response due to data versioning?
46
+ */
47
+ override async *read(request: ClientRead, session?: SessionT): ReadResult {
48
+ using _slot = await this.queue.obtainSlot();
49
+
50
+ yield* super.read(request, session);
51
+ }
52
+
53
+ /**
54
+ * Subscribe to remote events and attributes as defined by {@link request}.
55
+ *
56
+ * matter.js updates local state
57
+ *
58
+ * By default, matter.js subscribes to all attributes and events of the peer and updates {@link ClientNode} state
59
+ * automatically. So you normally do not need to subscribe manually.
60
+ *
61
+ * When providing the "sustain" flag, a SustainedSubscription is returned immediately. You need to use the events to
62
+ * know when/if a subscription could be established. This class handles reconnections automatically.
63
+ * When not providing the "sustain" flag, a PeerSubscription is returned after a subscription have been successfully
64
+ * established; or an error is returned if this was not possible.
65
+ */
66
+ override async subscribe<T extends ClientSubscribe>(request: T, session?: SessionT): SubscriptionResult<T> {
67
+ using _slot = await this.queue.obtainSlot();
68
+
69
+ return super.subscribe(request, session);
70
+ }
71
+
72
+ /**
73
+ * Write chosen attributes remotely to the node.
74
+ * The returned attribute writing status information is returned.
75
+ */
76
+ override async write<T extends ClientWrite>(request: T, session?: SessionT): WriteResult<T> {
77
+ using _slot = await this.queue.obtainSlot();
78
+
79
+ return super.write(request, session);
80
+ }
81
+
82
+ /**
83
+ * Invoke a command remotely on the node.
84
+ * The returned command response is returned as response chunks
85
+ */
86
+ override async *invoke(request: ClientInvoke, session?: SessionT): DecodedInvokeResult {
87
+ using _slot = await this.queue.obtainSlot();
88
+
89
+ yield* super.invoke(request, session);
90
+ }
91
+ }
@@ -5,6 +5,10 @@
5
5
  */
6
6
 
7
7
  export * from "./ClientInteraction.js";
8
+ export * from "./ClientRead.js";
9
+ export * from "./ClientRequest.js";
10
+ export * from "./ClientWrite.js";
8
11
  export * from "./InputChunk.js";
12
+ export * from "./QueuedClientInteraction.js";
9
13
  export * from "./ReadScope.js";
10
14
  export * from "./subscription/index.js";
@@ -1,6 +1,7 @@
1
1
  import { Subscribe } from "#action/request/Subscribe.js";
2
+ import { ClientRequest } from "../ClientRequest.js";
2
3
 
3
- export interface ClientSubscribe extends Subscribe {
4
+ export interface ClientSubscribe extends Subscribe, ClientRequest {
4
5
  /**
5
6
  * If true the subscription is virtualized and the underlying subscription is reestablished when lost.
6
7
  */
@@ -54,7 +54,10 @@ export class ClientSubscriptionHandler implements ProtocolHandler {
54
54
  SecureSession.assert(session);
55
55
  const subscription = this.#subscriptions.getPeer(session.peerAddress, subscriptionId);
56
56
  if (subscription === undefined) {
57
- logger.info("Ignoring data report for unknown subscription ID", Diagnostic.strong(subscriptionId));
57
+ logger.info(
58
+ "Ignoring data report for unknown subscription ID",
59
+ Diagnostic.strong(Subscription.idStrOf(subscriptionId)),
60
+ );
58
61
  await sendInvalid(messenger, subscriptionId);
59
62
  return;
60
63
  }
@@ -68,7 +71,10 @@ export class ClientSubscriptionHandler implements ProtocolHandler {
68
71
  // Read the next report to trigger success message sent out
69
72
  const ending = await reports.next();
70
73
  if (!ending.done) {
71
- logger.warn("Unexpected data reports after empty report", Diagnostic.strong(subscriptionId));
74
+ logger.warn(
75
+ "Unexpected data reports after empty report",
76
+ Diagnostic.strong(Subscription.idStrOf(subscriptionId)),
77
+ );
72
78
  for await (const _chunk of reports); // Read over these extraneous reports
73
79
  }
74
80
  } else {
@@ -125,7 +131,12 @@ async function* processReports(
125
131
  }
126
132
 
127
133
  if (reportSubscriptionId !== subscriptionId) {
128
- logger.debug("Ignoring data report for incorrect subscription id", Diagnostic.strong(reportSubscriptionId));
134
+ logger.debug(
135
+ "Ignoring data report for incorrect subscription id",
136
+ Diagnostic.strong(Subscription.idStrOf(reportSubscriptionId)),
137
+ "expected",
138
+ Subscription.idStrOf(subscriptionId),
139
+ );
129
140
  await sendInvalid(messenger, reportSubscriptionId);
130
141
  continue;
131
142
  }
@@ -56,7 +56,7 @@ export class SustainedSubscription extends ClientSubscription {
56
56
  }
57
57
 
58
58
  /**
59
- * Emits when active state changes.
59
+ * Emits when the active state changes.
60
60
  */
61
61
  get active() {
62
62
  return this.#active;
@@ -73,7 +73,7 @@ export class SustainedSubscription extends ClientSubscription {
73
73
  const updated = this.#request.updated?.bind(this.#request);
74
74
 
75
75
  while (true) {
76
- // Create request and promise that will inform us when the underlying subscription closes
76
+ // Create a request and promise that will inform us when the underlying subscription closes
77
77
  const request = { ...this.#request, updated };
78
78
  if (this.#request.updated) {
79
79
  request.updated = this.#request.updated.bind(request);
@@ -111,7 +111,7 @@ export class SustainedSubscription extends ClientSubscription {
111
111
  }
112
112
  }
113
113
 
114
- // Notify listeners of active subscription
114
+ // Notify listeners of an active subscription
115
115
  await this.#inactive.emit(false);
116
116
  await this.#active.emit(true);
117
117
  if (this.abort.aborted) {
@@ -121,19 +121,16 @@ export class SustainedSubscription extends ClientSubscription {
121
121
  // Wait for the subscription to close
122
122
  await closed;
123
123
 
124
- // Notify listeners of inactive subscription
124
+ // Notify listeners of an inactive subscription
125
125
  await this.#active.emit(false);
126
126
  await this.#inactive.emit(true);
127
- if (this.abort.aborted) {
128
- break;
129
- }
130
127
 
131
- // If aborted then we're done
128
+ // If aborted, then we're done
132
129
  if (this.abort.aborted) {
133
130
  break;
134
131
  }
135
132
 
136
- // If we aren't aborted then we are here due to timeout
133
+ // If we aren't aborted, then we are here due to timeout
137
134
  logger.error(`Replacing subscription to ${this.peer} due to timeout`);
138
135
  }
139
136
 
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { ClientRequest } from "#action/client/ClientRequest.js";
7
8
  import { Diagnostic, Duration, isObject } from "#general";
8
9
  import { SessionParameters } from "#session/SessionParameters.js";
9
10
  import { ClusterType, CommandData, FabricIndex, InvokeRequest, ObjectSchema, TlvSchema, TypeFromSchema } from "#types";
@@ -17,11 +18,20 @@ export interface InvokeCommandData extends CommandData {
17
18
  export interface Invoke extends InvokeRequest {
18
19
  /** Timeout only relevant for Client Interactions */
19
20
  timeout?: Duration;
21
+
22
+ /** Expected processing time of the command on the server side to calculated response timeout */
20
23
  expectedProcessingTime?: Duration;
24
+
25
+ /** Whether to use extended timeout for fail-safe messages. Overwrites the expectedProcessingTime if both are set */
21
26
  useExtendedFailSafeMessageResponseTimeout?: boolean;
22
27
  }
23
28
 
24
- export interface ClientInvoke extends Invoke {
29
+ export interface CommandDecodeDetails {
30
+ responseSchema: TlvSchema<any>;
31
+ [Diagnostic.value]: () => unknown;
32
+ }
33
+
34
+ export interface ClientInvoke extends Invoke, ClientRequest {
25
35
  commands: Map<number | undefined, Invoke.CommandRequest<any>>;
26
36
  }
27
37
 
@@ -234,9 +244,6 @@ export namespace Invoke {
234
244
  export function commandOf<const R extends CommandRequest>(request: R): ClusterType.Command {
235
245
  if (typeof request.command === "string") {
236
246
  const cluster = Specifier.clusterFor(request.cluster);
237
- if (cluster === undefined) {
238
- throw new MalformedRequestError(`Cannot designate command "${request.command}" without cluster`);
239
- }
240
247
  const command = cluster.commands[request.command];
241
248
  if (command === undefined) {
242
249
  throw new MalformedRequestError(`Cluster ${cluster.name} does not define command ${request.command}`);
@@ -45,11 +45,12 @@ export function Read(optionsOrSelector: Read.Options | Read.Selector, ...selecto
45
45
  } else {
46
46
  options = optionsOrSelector;
47
47
  }
48
+ const { fabricFilter = true, interactionModelRevision = Specification.INTERACTION_MODEL_REVISION } = options;
48
49
  let { attributes: attributeRequests, versionFilters, events: eventRequests, eventFilters } = options;
49
50
 
50
51
  const result = {
51
- isFabricFiltered: options.fabricFilter ?? true,
52
- interactionModelRevision: options.interactionModelRevision ?? Specification.INTERACTION_MODEL_REVISION,
52
+ isFabricFiltered: fabricFilter,
53
+ interactionModelRevision,
53
54
  [Diagnostic.value]: () =>
54
55
  Diagnostic.dict({
55
56
  attributes: attributeRequests?.length
@@ -57,7 +57,10 @@ export namespace Specifier {
57
57
  /**
58
58
  * Extract a cluster type from a cluster specifier.
59
59
  */
60
- export function clusterFor<const T extends Cluster>(specifier: T) {
60
+ export function clusterFor<const T extends Cluster>(specifier?: T) {
61
+ if (specifier === undefined) {
62
+ throw new MalformedRequestError(`Cannot designate command "${specifier}" without a cluster`);
63
+ }
61
64
  if ("cluster" in specifier) {
62
65
  return specifier["cluster"] as ClusterFor<T>;
63
66
  }
@@ -52,14 +52,22 @@ export function Write(optionsOrData: Write.Options | Write.Attribute, ...data: W
52
52
  } else {
53
53
  options = optionsOrData;
54
54
  }
55
- const { writes: writeRequests = [], timed, timeout, chunkLists } = options;
55
+ const {
56
+ writes: writeRequests = [],
57
+ timed,
58
+ timeout,
59
+ chunkLists,
60
+ suppressResponse,
61
+ interactionModelRevision = Specification.INTERACTION_MODEL_REVISION,
62
+ } = options;
56
63
 
57
64
  const result = {
58
65
  timedRequest: !!timed || !!timeout,
59
66
  timeout,
60
67
  writeRequests,
61
68
  moreChunkedMessages: false,
62
- interactionModelRevision: options.interactionModelRevision ?? Specification.INTERACTION_MODEL_REVISION,
69
+ suppressResponse,
70
+ interactionModelRevision,
63
71
 
64
72
  [Diagnostic.value]: () =>
65
73
  Diagnostic.list(
@@ -158,6 +166,7 @@ export namespace Write {
158
166
  timeout?: Duration;
159
167
  interactionModelRevision?: number;
160
168
  chunkLists?: boolean;
169
+ suppressResponse?: boolean;
161
170
  }
162
171
 
163
172
  /**
@@ -28,7 +28,7 @@ import type {
28
28
  * Iteration occurs in chunks for performance reasons. A chunk is an iterable of reports, one per output attribute or
29
29
  * event.
30
30
  */
31
- export interface ReadResult<Chunk = ReadResult.Chunk> extends AsyncIterableIterator<Chunk> {}
31
+ export interface ReadResult<Chunk = ReadResult.Chunk> extends AsyncIterable<Chunk> {}
32
32
 
33
33
  export namespace ReadResult {
34
34
  export type Chunk = Iterable<Report>;
@@ -16,7 +16,9 @@ import {
16
16
  CommandId,
17
17
  Commands,
18
18
  EndpointNumber,
19
+ Event,
19
20
  EventId,
21
+ EventNumber,
20
22
  EventType,
21
23
  Events,
22
24
  GlobalAttributeNames,
@@ -35,15 +37,53 @@ import {
35
37
  WritableAttribute,
36
38
  } from "#types";
37
39
  import { DecodedEventData } from "../../interaction/EventDataDecoder.js";
38
- import { AttributeClient } from "./AttributeClient.js";
39
- import { EventClient } from "./EventClient.js";
40
+
41
+ export interface AttributeClientObj<T = any> {
42
+ readonly id: AttributeId;
43
+ readonly attribute: Attribute<T, any>;
44
+ readonly name: string;
45
+ readonly endpointId: EndpointNumber | undefined;
46
+ readonly clusterId: ClusterId;
47
+ readonly fabricScoped: boolean;
48
+ set(value: T, dataVersion?: number): Promise<void>;
49
+ getLocal(): T | undefined;
50
+ get(requestFromRemote?: boolean, isFabricFiltered?: boolean): Promise<T | undefined>;
51
+ subscribe(
52
+ minIntervalFloorSeconds: number,
53
+ maxIntervalCeilingSeconds: number,
54
+ knownDataVersion?: number,
55
+ isFabricFiltered?: boolean,
56
+ ): Promise<{ maxInterval: number }>;
57
+ update(value: T): void;
58
+ addListener(listener: (newValue: T) => void): void;
59
+ removeListener(listener: (newValue: T) => void): void;
60
+ }
61
+
62
+ export interface EventClientObj<T> {
63
+ readonly id: EventId;
64
+ readonly event: Event<T, any>;
65
+ readonly name: string;
66
+ readonly endpointId: EndpointNumber | undefined;
67
+ readonly clusterId: ClusterId;
68
+ get(minimumEventNumber?: EventNumber, isFabricFiltered?: boolean): Promise<DecodedEventData<T>[] | undefined>;
69
+ subscribe(
70
+ minIntervalFloorSeconds: Duration,
71
+ maxIntervalCeilingSeconds: Duration,
72
+ isUrgent?: boolean,
73
+ minimumEventNumber?: EventNumber,
74
+ isFabricFiltered?: boolean,
75
+ ): Promise<{ maxInterval: number }>;
76
+ update(newEvent: DecodedEventData<T>): void;
77
+ addListener(listener: (newValue: DecodedEventData<T>) => void): void;
78
+ removeListener(listener: (newValue: DecodedEventData<T>) => void): void;
79
+ }
40
80
 
41
81
  export type AttributeClients<F extends BitSchema, A extends Attributes> = Merge<
42
82
  Merge<
43
- { [P in MandatoryAttributeNames<A>]: AttributeClient<AttributeJsType<A[P]>> },
44
- { [P in OptionalAttributeNames<A>]: AttributeClient<AttributeJsType<A[P]> | undefined> }
83
+ { [P in MandatoryAttributeNames<A>]: AttributeClientObj<AttributeJsType<A[P]>> },
84
+ { [P in OptionalAttributeNames<A>]: AttributeClientObj<AttributeJsType<A[P]> | undefined> }
45
85
  >,
46
- { [P in GlobalAttributeNames<F>]: AttributeClient<AttributeJsType<GlobalAttributes<F>[P]>> }
86
+ { [P in GlobalAttributeNames<F>]: AttributeClientObj<AttributeJsType<GlobalAttributes<F>[P]>> }
47
87
  >;
48
88
 
49
89
  export type AttributeClientValues<A extends Attributes> = Merge<
@@ -52,8 +92,8 @@ export type AttributeClientValues<A extends Attributes> = Merge<
52
92
  >;
53
93
 
54
94
  export type EventClients<E extends Events> = Merge<
55
- { [P in MandatoryEventNames<E>]: EventClient<EventType<E[P]>> },
56
- { [P in OptionalEventNames<E>]: EventClient<EventType<E[P]> | undefined> }
95
+ { [P in MandatoryEventNames<E>]: EventClientObj<EventType<E[P]>> },
96
+ { [P in OptionalEventNames<E>]: EventClientObj<EventType<E[P]> | undefined> }
57
97
  >;
58
98
 
59
99
  export type SignatureFromCommandSpec<C extends Command<any, any, any>> = (
@@ -4,7 +4,4 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- export * from "./AttributeClient.js";
8
- export * from "./ClusterClient.js";
9
7
  export * from "./ClusterClientTypes.js";
10
- export * from "./EventClient.js";
@@ -10,12 +10,12 @@ import {
10
10
  Bytes,
11
11
  Diagnostic,
12
12
  Duration,
13
- hex,
14
13
  InternalError,
15
14
  Logger,
16
15
  MatterFlowError,
17
16
  Millis,
18
17
  NoResponseTimeoutError,
18
+ Time,
19
19
  UnexpectedDataError,
20
20
  } from "#general";
21
21
  import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
@@ -1014,7 +1014,7 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
1014
1014
 
1015
1015
  #logContextOf(report: DataReport) {
1016
1016
  return {
1017
- subId: report.subscriptionId === undefined ? undefined : hex.fixed(report.subscriptionId, 8),
1017
+ subId: report.subscriptionId === undefined ? undefined : Subscription.idStrOf(report.subscriptionId),
1018
1018
  dataReportFlags: Diagnostic.asFlags({
1019
1019
  empty: !report.attributeReports?.length && !report.eventReports?.length,
1020
1020
  suppressResponse: report.suppressResponse,
@@ -1041,6 +1041,7 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
1041
1041
 
1042
1042
  /** Implements a send method with an automatic reconnection mechanism */
1043
1043
  override async send(messageType: number, payload: Bytes, options?: ExchangeSendOptions) {
1044
+ const now = Time.nowMs;
1044
1045
  try {
1045
1046
  if (this.exchange.channel.closed) {
1046
1047
  throw new SessionClosedError("The exchange channel is closed. Please connect the device first.");
@@ -1054,12 +1055,12 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
1054
1055
  !options?.multipleMessageInteraction
1055
1056
  ) {
1056
1057
  // When retransmission failed (most likely due to a lost connection or invalid session),
1057
- // try to reconnect if possible and resend the message once
1058
+ // try to reconnect if possible and resend the message one more time
1058
1059
  logger.debug(
1059
1060
  `${error instanceof RetransmissionLimitReachedError ? "Retransmission limit reached" : "Channel not connected"}, trying to reconnect and resend the message.`,
1060
1061
  );
1061
1062
  await this.exchange.close();
1062
- if (await this.#exchangeProvider.reconnectChannel()) {
1063
+ if (await this.#exchangeProvider.reconnectChannel({ asOf: now })) {
1063
1064
  this.exchange = await this.#exchangeProvider.initiateExchange();
1064
1065
  return await this.exchange.send(messageType, payload, options);
1065
1066
  }