@matter/node 0.16.0-alpha.0-20250819-0a388db8b → 0.16.0-alpha.0-20250821-dd03e1003

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 (195) hide show
  1. package/dist/cjs/behavior/Events.d.ts +5 -0
  2. package/dist/cjs/behavior/Events.d.ts.map +1 -1
  3. package/dist/cjs/behavior/Events.js +7 -4
  4. package/dist/cjs/behavior/Events.js.map +1 -1
  5. package/dist/cjs/behavior/Transitions.d.ts.map +1 -1
  6. package/dist/cjs/behavior/Transitions.js +2 -2
  7. package/dist/cjs/behavior/Transitions.js.map +1 -1
  8. package/dist/cjs/behavior/context/ActionContext.d.ts +0 -7
  9. package/dist/cjs/behavior/context/ActionContext.d.ts.map +1 -1
  10. package/dist/cjs/behavior/context/server/ContextAgents.d.ts +4 -5
  11. package/dist/cjs/behavior/context/server/ContextAgents.d.ts.map +1 -1
  12. package/dist/cjs/behavior/context/server/ContextAgents.js +9 -0
  13. package/dist/cjs/behavior/context/server/ContextAgents.js.map +1 -1
  14. package/dist/cjs/behavior/context/server/OfflineContext.d.ts.map +1 -1
  15. package/dist/cjs/behavior/context/server/OfflineContext.js +0 -8
  16. package/dist/cjs/behavior/context/server/OfflineContext.js.map +1 -1
  17. package/dist/cjs/behavior/context/server/OnlineContext.d.ts.map +1 -1
  18. package/dist/cjs/behavior/context/server/OnlineContext.js +0 -8
  19. package/dist/cjs/behavior/context/server/OnlineContext.js.map +1 -1
  20. package/dist/cjs/behavior/internal/Reactors.js +1 -1
  21. package/dist/cjs/behavior/internal/Reactors.js.map +1 -1
  22. package/dist/cjs/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  23. package/dist/cjs/behavior/system/commissioning/CommissioningClient.js +58 -58
  24. package/dist/cjs/behavior/system/commissioning/CommissioningClient.js.map +1 -1
  25. package/dist/cjs/behavior/system/network/ClientNetworkRuntime.d.ts +1 -0
  26. package/dist/cjs/behavior/system/network/ClientNetworkRuntime.d.ts.map +1 -1
  27. package/dist/cjs/behavior/system/network/ClientNetworkRuntime.js +40 -4
  28. package/dist/cjs/behavior/system/network/ClientNetworkRuntime.js.map +2 -2
  29. package/dist/cjs/behavior/system/network/NetworkBehavior.d.ts +5 -0
  30. package/dist/cjs/behavior/system/network/NetworkBehavior.d.ts.map +1 -1
  31. package/dist/cjs/behavior/system/network/NetworkBehavior.js +5 -0
  32. package/dist/cjs/behavior/system/network/NetworkBehavior.js.map +1 -1
  33. package/dist/cjs/behavior/system/network/NetworkClient.d.ts +7 -4
  34. package/dist/cjs/behavior/system/network/NetworkClient.d.ts.map +1 -1
  35. package/dist/cjs/behavior/system/network/NetworkClient.js +14 -7
  36. package/dist/cjs/behavior/system/network/NetworkClient.js.map +1 -1
  37. package/dist/cjs/behavior/system/network/NetworkRuntime.d.ts.map +1 -1
  38. package/dist/cjs/behavior/system/network/NetworkRuntime.js +0 -1
  39. package/dist/cjs/behavior/system/network/NetworkRuntime.js.map +1 -1
  40. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.d.ts.map +1 -1
  41. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.js +1 -0
  42. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.js.map +1 -1
  43. package/dist/cjs/behavior/system/parts/PartsBehavior.js +1 -1
  44. package/dist/cjs/behavior/system/parts/PartsBehavior.js.map +1 -1
  45. package/dist/cjs/behavior/system/product-description/ProductDescriptionServer.js +1 -1
  46. package/dist/cjs/behavior/system/product-description/ProductDescriptionServer.js.map +1 -1
  47. package/dist/cjs/behaviors/general-commissioning/ServerNodeFailsafeContext.js +1 -1
  48. package/dist/cjs/behaviors/general-commissioning/ServerNodeFailsafeContext.js.map +1 -1
  49. package/dist/cjs/behaviors/groups/GroupsServer.js +4 -4
  50. package/dist/cjs/behaviors/groups/GroupsServer.js.map +1 -1
  51. package/dist/cjs/endpoint/Agent.js +1 -1
  52. package/dist/cjs/endpoint/Agent.js.map +1 -1
  53. package/dist/cjs/endpoint/Endpoint.d.ts +9 -0
  54. package/dist/cjs/endpoint/Endpoint.d.ts.map +1 -1
  55. package/dist/cjs/endpoint/Endpoint.js +12 -1
  56. package/dist/cjs/endpoint/Endpoint.js.map +1 -1
  57. package/dist/cjs/endpoint/properties/Behaviors.js +3 -3
  58. package/dist/cjs/endpoint/properties/Behaviors.js.map +1 -1
  59. package/dist/cjs/endpoint/properties/Commands.js +1 -1
  60. package/dist/cjs/endpoint/properties/Commands.js.map +1 -1
  61. package/dist/cjs/node/ClientNode.d.ts +12 -0
  62. package/dist/cjs/node/ClientNode.d.ts.map +1 -1
  63. package/dist/cjs/node/ClientNode.js +28 -0
  64. package/dist/cjs/node/ClientNode.js.map +1 -1
  65. package/dist/cjs/node/Node.d.ts.map +1 -1
  66. package/dist/cjs/node/Node.js +2 -0
  67. package/dist/cjs/node/Node.js.map +1 -1
  68. package/dist/cjs/node/client/ClientBehavior.js +11 -4
  69. package/dist/cjs/node/client/ClientBehavior.js.map +1 -1
  70. package/dist/cjs/node/client/ClientEventEmitter.d.ts +19 -0
  71. package/dist/cjs/node/client/ClientEventEmitter.d.ts.map +1 -0
  72. package/dist/cjs/node/client/ClientEventEmitter.js +97 -0
  73. package/dist/cjs/node/client/ClientEventEmitter.js.map +6 -0
  74. package/dist/cjs/node/client/ClientStructure.d.ts +7 -3
  75. package/dist/cjs/node/client/ClientStructure.d.ts.map +1 -1
  76. package/dist/cjs/node/client/ClientStructure.js +42 -22
  77. package/dist/cjs/node/client/ClientStructure.js.map +1 -1
  78. package/dist/cjs/node/client/NodePeerAddressStore.d.ts +4 -1
  79. package/dist/cjs/node/client/NodePeerAddressStore.d.ts.map +1 -1
  80. package/dist/cjs/node/server/IdentityService.js +1 -1
  81. package/dist/cjs/node/server/IdentityService.js.map +1 -1
  82. package/dist/cjs/node/server/ProtocolService.js +1 -1
  83. package/dist/cjs/node/server/ProtocolService.js.map +1 -1
  84. package/dist/esm/behavior/Events.d.ts +5 -0
  85. package/dist/esm/behavior/Events.d.ts.map +1 -1
  86. package/dist/esm/behavior/Events.js +8 -4
  87. package/dist/esm/behavior/Events.js.map +1 -1
  88. package/dist/esm/behavior/Transitions.d.ts.map +1 -1
  89. package/dist/esm/behavior/Transitions.js +2 -2
  90. package/dist/esm/behavior/Transitions.js.map +1 -1
  91. package/dist/esm/behavior/context/ActionContext.d.ts +0 -7
  92. package/dist/esm/behavior/context/ActionContext.d.ts.map +1 -1
  93. package/dist/esm/behavior/context/server/ContextAgents.d.ts +4 -5
  94. package/dist/esm/behavior/context/server/ContextAgents.d.ts.map +1 -1
  95. package/dist/esm/behavior/context/server/ContextAgents.js +9 -0
  96. package/dist/esm/behavior/context/server/ContextAgents.js.map +1 -1
  97. package/dist/esm/behavior/context/server/OfflineContext.d.ts.map +1 -1
  98. package/dist/esm/behavior/context/server/OfflineContext.js +0 -8
  99. package/dist/esm/behavior/context/server/OfflineContext.js.map +1 -1
  100. package/dist/esm/behavior/context/server/OnlineContext.d.ts.map +1 -1
  101. package/dist/esm/behavior/context/server/OnlineContext.js +0 -8
  102. package/dist/esm/behavior/context/server/OnlineContext.js.map +1 -1
  103. package/dist/esm/behavior/internal/Reactors.js +1 -1
  104. package/dist/esm/behavior/internal/Reactors.js.map +1 -1
  105. package/dist/esm/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  106. package/dist/esm/behavior/system/commissioning/CommissioningClient.js +58 -58
  107. package/dist/esm/behavior/system/commissioning/CommissioningClient.js.map +1 -1
  108. package/dist/esm/behavior/system/network/ClientNetworkRuntime.d.ts +1 -0
  109. package/dist/esm/behavior/system/network/ClientNetworkRuntime.d.ts.map +1 -1
  110. package/dist/esm/behavior/system/network/ClientNetworkRuntime.js +42 -6
  111. package/dist/esm/behavior/system/network/ClientNetworkRuntime.js.map +2 -2
  112. package/dist/esm/behavior/system/network/NetworkBehavior.d.ts +5 -0
  113. package/dist/esm/behavior/system/network/NetworkBehavior.d.ts.map +1 -1
  114. package/dist/esm/behavior/system/network/NetworkBehavior.js +5 -0
  115. package/dist/esm/behavior/system/network/NetworkBehavior.js.map +1 -1
  116. package/dist/esm/behavior/system/network/NetworkClient.d.ts +7 -4
  117. package/dist/esm/behavior/system/network/NetworkClient.d.ts.map +1 -1
  118. package/dist/esm/behavior/system/network/NetworkClient.js +14 -7
  119. package/dist/esm/behavior/system/network/NetworkClient.js.map +1 -1
  120. package/dist/esm/behavior/system/network/NetworkRuntime.d.ts.map +1 -1
  121. package/dist/esm/behavior/system/network/NetworkRuntime.js +0 -1
  122. package/dist/esm/behavior/system/network/NetworkRuntime.js.map +1 -1
  123. package/dist/esm/behavior/system/network/ServerNetworkRuntime.d.ts.map +1 -1
  124. package/dist/esm/behavior/system/network/ServerNetworkRuntime.js +1 -0
  125. package/dist/esm/behavior/system/network/ServerNetworkRuntime.js.map +1 -1
  126. package/dist/esm/behavior/system/parts/PartsBehavior.js +1 -1
  127. package/dist/esm/behavior/system/parts/PartsBehavior.js.map +1 -1
  128. package/dist/esm/behavior/system/product-description/ProductDescriptionServer.js +1 -1
  129. package/dist/esm/behavior/system/product-description/ProductDescriptionServer.js.map +1 -1
  130. package/dist/esm/behaviors/general-commissioning/ServerNodeFailsafeContext.js +1 -1
  131. package/dist/esm/behaviors/general-commissioning/ServerNodeFailsafeContext.js.map +1 -1
  132. package/dist/esm/behaviors/groups/GroupsServer.js +4 -4
  133. package/dist/esm/behaviors/groups/GroupsServer.js.map +1 -1
  134. package/dist/esm/endpoint/Agent.js +1 -1
  135. package/dist/esm/endpoint/Agent.js.map +1 -1
  136. package/dist/esm/endpoint/Endpoint.d.ts +9 -0
  137. package/dist/esm/endpoint/Endpoint.d.ts.map +1 -1
  138. package/dist/esm/endpoint/Endpoint.js +12 -1
  139. package/dist/esm/endpoint/Endpoint.js.map +1 -1
  140. package/dist/esm/endpoint/properties/Behaviors.js +3 -3
  141. package/dist/esm/endpoint/properties/Behaviors.js.map +1 -1
  142. package/dist/esm/endpoint/properties/Commands.js +1 -1
  143. package/dist/esm/endpoint/properties/Commands.js.map +1 -1
  144. package/dist/esm/node/ClientNode.d.ts +12 -0
  145. package/dist/esm/node/ClientNode.d.ts.map +1 -1
  146. package/dist/esm/node/ClientNode.js +28 -0
  147. package/dist/esm/node/ClientNode.js.map +1 -1
  148. package/dist/esm/node/Node.d.ts.map +1 -1
  149. package/dist/esm/node/Node.js +2 -0
  150. package/dist/esm/node/Node.js.map +1 -1
  151. package/dist/esm/node/client/ClientBehavior.js +11 -4
  152. package/dist/esm/node/client/ClientBehavior.js.map +1 -1
  153. package/dist/esm/node/client/ClientEventEmitter.d.ts +19 -0
  154. package/dist/esm/node/client/ClientEventEmitter.d.ts.map +1 -0
  155. package/dist/esm/node/client/ClientEventEmitter.js +77 -0
  156. package/dist/esm/node/client/ClientEventEmitter.js.map +6 -0
  157. package/dist/esm/node/client/ClientStructure.d.ts +7 -3
  158. package/dist/esm/node/client/ClientStructure.d.ts.map +1 -1
  159. package/dist/esm/node/client/ClientStructure.js +42 -22
  160. package/dist/esm/node/client/ClientStructure.js.map +1 -1
  161. package/dist/esm/node/client/NodePeerAddressStore.d.ts +4 -1
  162. package/dist/esm/node/client/NodePeerAddressStore.d.ts.map +1 -1
  163. package/dist/esm/node/server/IdentityService.js +1 -1
  164. package/dist/esm/node/server/IdentityService.js.map +1 -1
  165. package/dist/esm/node/server/ProtocolService.js +1 -1
  166. package/dist/esm/node/server/ProtocolService.js.map +1 -1
  167. package/package.json +7 -7
  168. package/src/behavior/Events.ts +19 -6
  169. package/src/behavior/Transitions.ts +7 -6
  170. package/src/behavior/context/ActionContext.ts +0 -6
  171. package/src/behavior/context/server/ContextAgents.ts +17 -1
  172. package/src/behavior/context/server/OfflineContext.ts +0 -11
  173. package/src/behavior/context/server/OnlineContext.ts +0 -12
  174. package/src/behavior/internal/Reactors.ts +1 -1
  175. package/src/behavior/system/commissioning/CommissioningClient.ts +61 -59
  176. package/src/behavior/system/network/ClientNetworkRuntime.ts +59 -6
  177. package/src/behavior/system/network/NetworkBehavior.ts +6 -1
  178. package/src/behavior/system/network/NetworkClient.ts +17 -9
  179. package/src/behavior/system/network/NetworkRuntime.ts +0 -1
  180. package/src/behavior/system/network/ServerNetworkRuntime.ts +2 -0
  181. package/src/behavior/system/parts/PartsBehavior.ts +1 -1
  182. package/src/behavior/system/product-description/ProductDescriptionServer.ts +1 -1
  183. package/src/behaviors/general-commissioning/ServerNodeFailsafeContext.ts +1 -1
  184. package/src/behaviors/groups/GroupsServer.ts +4 -4
  185. package/src/endpoint/Agent.ts +1 -1
  186. package/src/endpoint/Endpoint.ts +14 -1
  187. package/src/endpoint/properties/Behaviors.ts +3 -3
  188. package/src/endpoint/properties/Commands.ts +1 -1
  189. package/src/node/ClientNode.ts +34 -1
  190. package/src/node/Node.ts +2 -0
  191. package/src/node/client/ClientBehavior.ts +12 -5
  192. package/src/node/client/ClientEventEmitter.ts +115 -0
  193. package/src/node/client/ClientStructure.ts +58 -34
  194. package/src/node/server/IdentityService.ts +1 -1
  195. package/src/node/server/ProtocolService.ts +1 -1
@@ -5,15 +5,12 @@
5
5
  */
6
6
 
7
7
  import type { Agent } from "#endpoint/Agent.js";
8
- import type { Endpoint } from "#endpoint/Endpoint.js";
9
- import type { EndpointType } from "#endpoint/type/EndpointType.js";
10
8
  import { Diagnostic, InternalError, MaybePromise, Transaction } from "#general";
11
9
  import { AccessLevel } from "#model";
12
10
  import { AccessControl } from "#protocol";
13
11
  import type { ActionContext } from "../ActionContext.js";
14
12
  import { Contextual } from "../Contextual.js";
15
13
  import type { NodeActivity } from "../NodeActivity.js";
16
- import { ContextAgents } from "./ContextAgents.js";
17
14
 
18
15
  export let nextInternalId = 1;
19
16
 
@@ -70,7 +67,6 @@ export const OfflineContext = {
70
67
 
71
68
  try {
72
69
  frame = options?.activity?.begin(via);
73
- let agents: undefined | ContextAgents;
74
70
 
75
71
  transaction = Transaction.open(via, options?.isolation);
76
72
 
@@ -94,13 +90,6 @@ export const OfflineContext = {
94
90
  : AccessControl.Authority.Unauthorized;
95
91
  },
96
92
 
97
- agentFor<const T extends EndpointType>(endpoint: Endpoint<T>): Agent.Instance<T> {
98
- if (!agents) {
99
- agents = ContextAgents(context);
100
- }
101
- return agents?.agentFor(endpoint);
102
- },
103
-
104
93
  get [Contextual.context]() {
105
94
  return this;
106
95
  },
@@ -4,9 +4,6 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Agent } from "#endpoint/Agent.js";
8
- import { Endpoint } from "#endpoint/Endpoint.js";
9
- import { EndpointType } from "#endpoint/type/EndpointType.js";
10
7
  import { AsyncObservable, Diagnostic, ImplementationError, InternalError, MaybePromise, Transaction } from "#general";
11
8
  import { AccessLevel } from "#model";
12
9
  import type { Node } from "#node/Node.js";
@@ -23,7 +20,6 @@ import { FabricIndex, NodeId } from "#types";
23
20
  import { ActionContext } from "../ActionContext.js";
24
21
  import { Contextual } from "../Contextual.js";
25
22
  import { NodeActivity } from "../NodeActivity.js";
26
- import { ContextAgents } from "./ContextAgents.js";
27
23
 
28
24
  /**
29
25
  * Caches completion events per exchange. Uses if multiple OnlineContext instances are created for an exchange.
@@ -150,7 +146,6 @@ export function OnlineContext(options: OnlineContext.Options) {
150
146
  if (session) {
151
147
  SecureSession.assert(session);
152
148
  }
153
- let agents: undefined | ContextAgents;
154
149
  let interactionComplete: AsyncObservable<[session?: ActionContext | undefined]> | undefined;
155
150
  if (exchange !== undefined) {
156
151
  interactionComplete = exchangeCompleteEvents.get(exchange);
@@ -211,13 +206,6 @@ export function OnlineContext(options: OnlineContext.Options) {
211
206
  : AccessControl.Authority.Unauthorized;
212
207
  },
213
208
 
214
- agentFor<T extends EndpointType>(endpoint: Endpoint<T>): Agent.Instance<T> {
215
- if (!agents) {
216
- agents = ContextAgents(context);
217
- }
218
- return agents.agentFor(endpoint);
219
- },
220
-
221
209
  get [Contextual.context](): ActionContext {
222
210
  return this;
223
211
  },
@@ -411,7 +411,7 @@ class ReactorBacking<T extends any[], R> {
411
411
  * Bind the reactor to a behavior instance once locks are held.
412
412
  */
413
413
  #bindReactor(context: ActionContext, backing: BehaviorBacking): Reactor<T, Awaited<R>> {
414
- const agent = context.agentFor(this.#endpoint);
414
+ const agent = this.#endpoint.agentFor(context);
415
415
 
416
416
  // Do not use Agent.get because it will throw during initialization
417
417
  const behavior = backing.createBehavior(agent, backing.type);
@@ -217,65 +217,67 @@ export class CommissioningClient extends Behavior {
217
217
  /**
218
218
  * Define logical schema. This enables runtime validation, make fields persistent and makes subfields editable.
219
219
  */
220
- static override readonly schema = new DatatypeModel({
221
- name: "CommissioningState",
222
- type: "struct",
223
-
224
- children: [
225
- FieldElement({
226
- name: "peerAddress",
227
- type: "struct",
228
- quality: "N",
229
- children: [
230
- FieldElement({ name: "fabricIndex", type: "fabric-id" }),
231
- FieldElement({ name: "nodeId", type: "node-id" }),
232
- ],
233
- }),
234
- FieldElement({
235
- name: "addresses",
236
- type: "list",
237
- quality: "N",
238
- children: [
239
- FieldElement({
240
- name: "entry",
241
- type: "struct",
242
- children: [
243
- FieldElement({ name: "type", type: "string" }),
244
- FieldElement({ name: "ip", type: "string" }),
245
- FieldElement({ name: "port", type: "uint16" }),
246
- FieldElement({ name: "peripheralAddress", type: "string" }),
247
- ],
248
- }),
249
- ],
250
- }),
251
- FieldElement({ name: "discoveredAt", type: "systime-ms", quality: "N", conformance: "M" }),
252
- FieldElement({ name: "onlineAt", type: "systime-ms" }),
253
- FieldElement({ name: "offlineAt", type: "systime-ms" }),
254
- FieldElement({ name: "ttl", type: "uint32", quality: "N" }),
255
- FieldElement({ name: "deviceIdentifier", type: "string", quality: "N" }),
256
- FieldElement({ name: "discriminator", type: "uint16", quality: "N" }),
257
- FieldElement({ name: "commissioningMode", type: "uint8", quality: "N" }),
258
- FieldElement({ name: "vendorId", type: "vendor-id", quality: "N" }),
259
- FieldElement({ name: "productId", type: "uint16", quality: "N" }),
260
- FieldElement({ name: "deviceType", type: "uint16", quality: "N" }),
261
- FieldElement({ name: "deviceName", type: "string", quality: "N" }),
262
- FieldElement({ name: "rotatingIdentifier", type: "string", quality: "N" }),
263
- FieldElement({ name: "pairingHint", type: "uint32", quality: "N" }),
264
- FieldElement({ name: "pairingInstructions", type: "string", quality: "N" }),
265
- FieldElement({
266
- name: "sessionParameters",
267
- type: "struct",
268
- quality: "N",
269
- children: [
270
- FieldElement({ name: "idleInterval", type: "duration", constraint: "max 3600000" }),
271
- FieldElement({ name: "activeInterval", type: "duration", constraint: "max 3600000" }),
272
- FieldElement({ name: "activeThreshold", type: "duration", constraint: "max 65535" }),
273
- ],
274
- }),
275
- FieldElement({ name: "tcpSupport", type: "uint8", quality: "N" }),
276
- FieldElement({ name: "longIdleOperatingMode", type: "bool", quality: "N" }),
277
- ],
278
- });
220
+ static override readonly schema = new DatatypeModel(
221
+ {
222
+ name: "CommissioningState",
223
+ type: "struct",
224
+ },
225
+
226
+ FieldElement({
227
+ name: "peerAddress",
228
+ type: "struct",
229
+ quality: "N",
230
+ children: [
231
+ FieldElement({ name: "fabricIndex", type: "fabric-id" }),
232
+ FieldElement({ name: "nodeId", type: "node-id" }),
233
+ ],
234
+ }),
235
+
236
+ FieldElement({
237
+ name: "addresses",
238
+ type: "list",
239
+ quality: "N",
240
+ children: [
241
+ FieldElement({
242
+ name: "entry",
243
+ type: "struct",
244
+ children: [
245
+ FieldElement({ name: "type", type: "string" }),
246
+ FieldElement({ name: "ip", type: "string" }),
247
+ FieldElement({ name: "port", type: "uint16" }),
248
+ FieldElement({ name: "peripheralAddress", type: "string" }),
249
+ ],
250
+ }),
251
+ ],
252
+ }),
253
+
254
+ FieldElement({ name: "discoveredAt", type: "systime-ms", quality: "N", conformance: "M" }),
255
+ FieldElement({ name: "onlineAt", type: "systime-ms" }),
256
+ FieldElement({ name: "offlineAt", type: "systime-ms" }),
257
+ FieldElement({ name: "ttl", type: "uint32", quality: "N" }),
258
+ FieldElement({ name: "deviceIdentifier", type: "string", quality: "N" }),
259
+ FieldElement({ name: "discriminator", type: "uint16", quality: "N" }),
260
+ FieldElement({ name: "commissioningMode", type: "uint8", quality: "N" }),
261
+ FieldElement({ name: "vendorId", type: "vendor-id", quality: "N" }),
262
+ FieldElement({ name: "productId", type: "uint16", quality: "N" }),
263
+ FieldElement({ name: "deviceType", type: "uint16", quality: "N" }),
264
+ FieldElement({ name: "deviceName", type: "string", quality: "N" }),
265
+ FieldElement({ name: "rotatingIdentifier", type: "string", quality: "N" }),
266
+ FieldElement({ name: "pairingHint", type: "uint32", quality: "N" }),
267
+ FieldElement({ name: "pairingInstructions", type: "string", quality: "N" }),
268
+ FieldElement({
269
+ name: "sessionParameters",
270
+ type: "struct",
271
+ quality: "N",
272
+ children: [
273
+ FieldElement({ name: "idleInterval", type: "duration", constraint: "max 3600000" }),
274
+ FieldElement({ name: "activeInterval", type: "duration", constraint: "max 3600000" }),
275
+ FieldElement({ name: "activeThreshold", type: "duration", constraint: "max 65535" }),
276
+ ],
277
+ }),
278
+ FieldElement({ name: "tcpSupport", type: "uint8", quality: "N" }),
279
+ FieldElement({ name: "longIdleOperatingMode", type: "bool", quality: "N" }),
280
+ );
279
281
  }
280
282
 
281
283
  export namespace CommissioningClient {
@@ -4,9 +4,9 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { InternalError, Logger, MatterError } from "#general";
7
+ import { InternalError, Logger, MatterError, ObserverGroup } from "#general";
8
8
  import type { ClientNode } from "#node/ClientNode.js";
9
- import { ClientInteraction, ExchangeProvider, PeerSet } from "#protocol";
9
+ import { ClientInteraction, ExchangeProvider, PeerAddress, PeerSet, SessionManager } from "#protocol";
10
10
  import { CommissioningClient } from "../commissioning/CommissioningClient.js";
11
11
  import { RemoteDescriptor } from "../commissioning/RemoteDescriptor.js";
12
12
  import { NetworkRuntime } from "./NetworkRuntime.js";
@@ -21,30 +21,81 @@ const logger = Logger.get("ClientNetworkRuntime");
21
21
  */
22
22
  export class ClientNetworkRuntime extends NetworkRuntime {
23
23
  #client?: ClientInteraction;
24
+ #observers = new ObserverGroup();
24
25
 
25
26
  constructor(owner: ClientNode) {
26
27
  super(owner);
27
28
  }
28
29
 
30
+ override get owner() {
31
+ return super.owner as ClientNode;
32
+ }
33
+
29
34
  protected async start() {
35
+ // Ensure we can connect to the node
30
36
  if (!this.owner.lifecycle.isCommissioned) {
31
37
  throw new UncommissionedError(`Cannot interact with ${this.owner} because it is uncommissioned`);
32
38
  }
33
39
 
34
- const commissioningState = this.owner.stateOf(CommissioningClient);
40
+ if (this.owner.state.network.isDisabled) {
41
+ throw new UncommissionedError(`Cannot interact with ${this.owner} because it is disabled`);
42
+ }
43
+
35
44
  const address = this.owner.stateOf(CommissioningClient).peerAddress;
36
- const peers = this.owner.env.get(PeerSet);
37
45
 
38
46
  if (address === undefined) {
39
47
  throw new InternalError(`Commissioned node ${this.owner} has no peer address`);
40
48
  }
41
49
 
50
+ // Install the exchange provider for the node
51
+ const { env, lifecycle } = this.owner;
52
+ const peers = env.get(PeerSet);
53
+ const commissioningState = this.owner.stateOf(CommissioningClient);
54
+
42
55
  const exchangeProvider = await peers.exchangeProviderFor(address, {
43
56
  discoveryData: RemoteDescriptor.fromLongForm(commissioningState),
44
57
  });
45
- this.owner.env.set(ExchangeProvider, exchangeProvider);
58
+ env.set(ExchangeProvider, exchangeProvider);
59
+
60
+ // Monitor sessions to maintain online state. We consider the node "online" if there is an active session. If
61
+ // not, we consider the node offline. This is the only real way we have of determining whether the node is
62
+ // healthy without actively polling
63
+ this.#client = env.get(ClientInteraction);
64
+ const { sessions } = env.get(SessionManager);
65
+
66
+ if (sessions.find(session => session.peerIs(address))) {
67
+ this.owner.act(({ context }) => lifecycle.online.emit(context));
68
+ }
46
69
 
47
- this.#client = this.owner.env.get(ClientInteraction);
70
+ this.#observers.on(sessions.added, session => {
71
+ if (lifecycle.isOnline) {
72
+ return;
73
+ }
74
+
75
+ const address = PeerAddress(commissioningState.peerAddress);
76
+ if (!address || session.peerAddress !== address) {
77
+ return;
78
+ }
79
+
80
+ this.owner.act(({ context }) => lifecycle.online.emit(context));
81
+ });
82
+
83
+ this.#observers.on(sessions.deleted, session => {
84
+ if (!lifecycle.isOnline) {
85
+ return;
86
+ }
87
+
88
+ const address = PeerAddress(commissioningState.peerAddress);
89
+ if (session.peerAddress !== address) {
90
+ return;
91
+ }
92
+
93
+ if (address && sessions.find(({ peerAddress }) => peerAddress === address)) {
94
+ return;
95
+ }
96
+
97
+ this.owner.act(({ context }) => lifecycle.offline.emit(context));
98
+ });
48
99
  }
49
100
 
50
101
  protected async stop() {
@@ -55,6 +106,8 @@ export class ClientNetworkRuntime extends NetworkRuntime {
55
106
  } catch (e) {
56
107
  logger.error(`Error closing connection to ${this.owner}`, e);
57
108
  }
109
+
110
+ this.#observers.close();
58
111
  }
59
112
 
60
113
  blockNewActivity() {
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { STANDARD_MATTER_PORT } from "#general";
7
+ import { MaybePromise, STANDARD_MATTER_PORT } from "#general";
8
8
  import { Behavior } from "../../Behavior.js";
9
9
  import type { NetworkRuntime } from "./NetworkRuntime.js";
10
10
 
@@ -24,6 +24,11 @@ export class NetworkBehavior extends Behavior {
24
24
  override [Symbol.asyncDispose]() {
25
25
  return this.internal.runtime?.close();
26
26
  }
27
+
28
+ /**
29
+ * Invoked by node when networking is ready.
30
+ */
31
+ startup(): MaybePromise {}
27
32
  }
28
33
 
29
34
  export namespace NetworkBehavior {
@@ -14,14 +14,10 @@ export class NetworkClient extends NetworkBehavior {
14
14
  declare internal: NetworkClient.Internal;
15
15
  declare state: NetworkClient.State;
16
16
 
17
- override initialize() {
18
- this.reactTo(this.#node.lifecycle.online, this.startup);
19
- }
20
-
21
- protected async startup() {
22
- const { startupSubscription } = this.state;
17
+ override async startup() {
18
+ const { startupSubscription, isDisabled } = this.state;
23
19
 
24
- if (startupSubscription === null) {
20
+ if (startupSubscription === null || isDisabled) {
25
21
  return;
26
22
  }
27
23
 
@@ -31,6 +27,7 @@ export class NetworkClient extends NetworkBehavior {
31
27
  minIntervalFloor: DEFAULT_MIN_INTERVAL_FLOOR,
32
28
  maxIntervalCeiling: 0,
33
29
  attributes: [{}],
30
+ events: [{ isUrgent: true }],
34
31
  ...startupSubscription,
35
32
  });
36
33
 
@@ -59,6 +56,12 @@ export class NetworkClient extends NetworkBehavior {
59
56
  default: { type: "properties", properties: {} },
60
57
  quality: "XN",
61
58
  }),
59
+
60
+ FieldElement({
61
+ name: "isDisabled",
62
+ type: "bool",
63
+ quality: "N",
64
+ }),
62
65
  ],
63
66
  });
64
67
  }
@@ -72,11 +75,16 @@ export namespace NetworkClient {
72
75
  /**
73
76
  * A subscription installed when the node is first commissioned and when the service is restarted.
74
77
  *
75
- * The default subscription is a wildcard for all attributes and of the node. You can set to undefined or
76
- * filter the fields and values but only values selected by this subscription will update automatically.
78
+ * The default subscription is a wildcard for all attributes of the node. You can set to undefined or filter
79
+ * the fields and values but only values selected by this subscription will update automatically.
77
80
  *
78
81
  * Set to null to disable automatic subscription.
79
82
  */
80
83
  startupSubscription?: Subscribe | null;
84
+
85
+ /**
86
+ * If true, the matter.js will not perform network communication with the node.
87
+ */
88
+ isDisabled = false;
81
89
  }
82
90
  }
@@ -34,7 +34,6 @@ export abstract class NetworkRuntime {
34
34
 
35
35
  async [Construction.construct]() {
36
36
  await this.start();
37
- await this.#owner.act(agent => this.owner.lifecycle.online.emit(agent.context));
38
37
  }
39
38
 
40
39
  async [Construction.destruct]() {
@@ -293,6 +293,8 @@ export class ServerNetworkRuntime extends NetworkRuntime {
293
293
  if (this.owner.stateOf(CommissioningServer).commissioned) {
294
294
  this.enableMdnsAdvertising();
295
295
  }
296
+
297
+ await this.owner.act(agent => this.owner.lifecycle.online.emit(agent.context));
296
298
  }
297
299
 
298
300
  override async [Construction.construct]() {
@@ -37,7 +37,7 @@ export class PartsBehavior extends Behavior implements MutableSet<Endpoint, Endp
37
37
 
38
38
  *[Symbol.iterator]() {
39
39
  for (const part of this.endpoint.parts) {
40
- yield this.context.agentFor(part);
40
+ yield part.agentFor(this.context);
41
41
  }
42
42
  }
43
43
  }
@@ -116,7 +116,7 @@ function inferDeviceType(agent: Agent): DeviceTypeId | undefined {
116
116
  }
117
117
 
118
118
  for (const child of agent.endpoint.parts) {
119
- const deviceType = inferDeviceType(agent.context.agentFor(child));
119
+ const deviceType = inferDeviceType(child.agentFor(agent.context));
120
120
  if (deviceType !== undefined) {
121
121
  return deviceType;
122
122
  }
@@ -81,7 +81,7 @@ export class ServerNodeFailsafeContext extends FailsafeContext {
81
81
  await this.#node.visit(async endpoint => {
82
82
  const networks = this.#storedState?.networks.get(endpoint);
83
83
  if (networks) {
84
- context.agentFor(endpoint).get(NetworkCommissioningBehavior).state.networks = [...networks];
84
+ endpoint.agentFor(context).get(NetworkCommissioningBehavior).state.networks = [...networks];
85
85
  }
86
86
  });
87
87
  });
@@ -67,7 +67,7 @@ export class GroupsServer extends GroupsBase {
67
67
 
68
68
  // We need to search the root here ourselves because we cannot include ServerNode because else we generate a
69
69
  // circular dependency
70
- #rootEndpoint(): Endpoint<RootEndpoint> {
70
+ get #rootEndpoint(): Endpoint<RootEndpoint> {
71
71
  const rootEndpoint = this.endpoint.ownerOfType(RootEndpoint);
72
72
  if (rootEndpoint === undefined) {
73
73
  throw new InternalError("RootEndpoint not found");
@@ -76,7 +76,7 @@ export class GroupsServer extends GroupsBase {
76
76
  }
77
77
 
78
78
  async #actOnGroupKeyManagement<T>(act: (groupKeyManagement: GroupKeyManagementServer) => T): Promise<T> {
79
- const agent = this.context.agentFor(this.#rootEndpoint());
79
+ const agent = this.#rootEndpoint.agentFor(this.context);
80
80
  const gkm = agent.get(GroupKeyManagementServer);
81
81
  await agent.context.transaction.addResources(gkm);
82
82
  await agent.context.transaction.begin();
@@ -122,7 +122,7 @@ export class GroupsServer extends GroupsBase {
122
122
  const fabricIndex = fabric.fabricIndex;
123
123
  const endpointNumber = this.endpoint.number;
124
124
 
125
- const { groupTable } = this.#rootEndpoint().stateOf(GroupKeyManagementServer);
125
+ const { groupTable } = this.#rootEndpoint.stateOf(GroupKeyManagementServer);
126
126
  const groupEntry = groupTable.find(entry => entry.groupId === groupId && entry.fabricIndex === fabricIndex);
127
127
  if (groupEntry === undefined || !groupEntry.endpoints.includes(endpointNumber)) {
128
128
  return { status: StatusCode.NotFound, groupId, groupName: "" };
@@ -137,7 +137,7 @@ export class GroupsServer extends GroupsBase {
137
137
  const fabricIndex = fabric.fabricIndex;
138
138
  const endpointNumber = this.endpoint.number;
139
139
 
140
- const { groupTable } = this.#rootEndpoint().stateOf(GroupKeyManagementServer);
140
+ const { groupTable } = this.#rootEndpoint.stateOf(GroupKeyManagementServer);
141
141
  const endpointGroups = groupTable.filter(
142
142
  entry => entry.endpoints.includes(endpointNumber) && entry.fabricIndex === fabricIndex,
143
143
  );
@@ -51,7 +51,7 @@ export class Agent {
51
51
  if (this.#endpoint.owner === undefined) {
52
52
  return undefined;
53
53
  }
54
- return this.context.agentFor(this.#endpoint.owner);
54
+ return this.#endpoint.owner.agentFor(this.context);
55
55
  }
56
56
 
57
57
  /**
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  import { Behavior } from "#behavior/Behavior.js";
8
+ import { ActionContext } from "#behavior/context/ActionContext.js";
8
9
  import { NodeActivity } from "#behavior/context/NodeActivity.js";
10
+ import { ContextAgents } from "#behavior/context/server/ContextAgents.js";
9
11
  import { OfflineContext } from "#behavior/context/server/OfflineContext.js";
10
12
  import {
11
13
  Construction,
@@ -112,6 +114,17 @@ export class Endpoint<T extends EndpointType = EndpointType.Empty> {
112
114
  return this.#owner;
113
115
  }
114
116
 
117
+ /**
118
+ * Access an {@link Agent} for this endpoint.
119
+ *
120
+ * An {@link Agent} allows you to interact directly with the behaviors supported by the endpoint. Normally you
121
+ * would use {@link act} to obtain an agent but {@link agentFor} is useful if you need to interact with multiple
122
+ * endpoints in the same context.
123
+ */
124
+ agentFor<T extends EndpointType>(this: Endpoint<T>, context: ActionContext) {
125
+ return ContextAgents(context).agentFor(this);
126
+ }
127
+
115
128
  get endpointProtocol() {
116
129
  if (this.#number === undefined || !this.env.has(ProtocolService)) {
117
130
  return undefined;
@@ -599,7 +612,7 @@ export class Endpoint<T extends EndpointType = EndpointType.Empty> {
599
612
  return OfflineContext.act(
600
613
  purpose,
601
614
  context => {
602
- return actor(context.agentFor(this));
615
+ return actor(this.agentFor(context));
603
616
  },
604
617
  { activity: this.#activity },
605
618
  );
@@ -186,7 +186,7 @@ export class Behaviors {
186
186
 
187
187
  // Initialization action. We initialize all behaviors in the same transaction
188
188
  const initializeBehaviors = (context: ActionContext): MaybePromise => {
189
- const agent = context.agentFor(this.#endpoint);
189
+ const agent = this.#endpoint.agentFor(context);
190
190
 
191
191
  // Activate behaviors
192
192
  //
@@ -377,7 +377,7 @@ export class Behaviors {
377
377
  */
378
378
  async close() {
379
379
  const dispose = async (context: ActionContext) => {
380
- const agent = context.agentFor(this.#endpoint);
380
+ const agent = this.#endpoint.agentFor(context);
381
381
 
382
382
  let destroyNow = new Set(Object.keys(this.#backings));
383
383
  while (destroyNow.size) {
@@ -565,7 +565,7 @@ export class Behaviors {
565
565
  const result = OfflineContext.act(
566
566
  "behavior-late-activation",
567
567
  context => {
568
- this.activate(type, context.agentFor(this.#endpoint));
568
+ this.activate(type, this.#endpoint.agentFor(context));
569
569
 
570
570
  // Agent must remain active until backing is initialized
571
571
  const backing = this.#backingFor(type);
@@ -67,7 +67,7 @@ function Implementation(endpoint: Endpoint, type: Behavior.Type, name: string):
67
67
 
68
68
  // Create function to perform invocation
69
69
  function invokerFor(context: ActionContext) {
70
- const agent = context.agentFor(endpoint);
70
+ const agent = endpoint.agentFor(context);
71
71
  const behavior = agent.get(type);
72
72
  const method = (behavior as unknown as Record<string, Commands.Command>)[name];
73
73
  if (typeof method !== "function") {
@@ -12,7 +12,7 @@ import { NetworkRuntime } from "#behavior/system/network/NetworkRuntime.js";
12
12
  import { Agent } from "#endpoint/Agent.js";
13
13
  import { EndpointInitializer } from "#endpoint/properties/EndpointInitializer.js";
14
14
  import { Identity, Lifecycle, MaybePromise } from "#general";
15
- import { Interactable } from "#protocol";
15
+ import { Interactable, OccurrenceManager } from "#protocol";
16
16
  import { ClientNodeStore } from "#storage/client/ClientNodeStore.js";
17
17
  import { RemoteWriter } from "#storage/client/RemoteWriter.js";
18
18
  import { ServerNodeStore } from "#storage/server/ServerNodeStore.js";
@@ -41,6 +41,9 @@ export class ClientNode extends Node<ClientNode.RootEndpoint> {
41
41
 
42
42
  super(opts);
43
43
 
44
+ // Block the OccurranceManager from parent environment so we don't attempt to record events from peers
45
+ this.env.block(OccurrenceManager);
46
+
44
47
  this.env.set(Node, this);
45
48
  this.env.set(ClientNode, this);
46
49
 
@@ -108,6 +111,36 @@ export class ClientNode extends Node<ClientNode.RootEndpoint> {
108
111
  await this.lifecycle.mutex.produce(this.eraseWithMutex.bind(this));
109
112
  }
110
113
 
114
+ /**
115
+ * Disable the node.
116
+ *
117
+ * This shuts down any active connections and prevents future connections until re-enabled.
118
+ */
119
+ async disable() {
120
+ if (this.state.network.isDisabled) {
121
+ return;
122
+ }
123
+
124
+ await this.lifecycle.mutex.produce(async () => {
125
+ await this.cancelWithMutex();
126
+ await this.setStateOf(NetworkClient, { isDisabled: true });
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Enable the node.
132
+ *
133
+ * If the node is disabled but reachable, this brings it online.
134
+ */
135
+ async enable() {
136
+ if (!this.state.network.isDisabled) {
137
+ return;
138
+ }
139
+
140
+ await this.setStateOf(NetworkClient, { isDisabled: false });
141
+ await this.start();
142
+ }
143
+
111
144
  protected async eraseWithMutex() {
112
145
  // First ensure we're offline
113
146
  await this.cancelWithMutex();
package/src/node/Node.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  import { ActionContext } from "#behavior/context/ActionContext.js";
8
8
  import { NodeActivity } from "#behavior/context/NodeActivity.js";
9
9
  import { IndexBehavior } from "#behavior/system/index/IndexBehavior.js";
10
+ import { NetworkBehavior } from "#behavior/system/network/NetworkBehavior.js";
10
11
  import { NetworkRuntime } from "#behavior/system/network/NetworkRuntime.js";
11
12
  import { PartsBehavior } from "#behavior/system/parts/PartsBehavior.js";
12
13
  import { Endpoint } from "#endpoint/Endpoint.js";
@@ -116,6 +117,7 @@ export abstract class Node<T extends Node.CommonRootEndpoint = Node.CommonRootEn
116
117
  this.#runtime.construction.start();
117
118
  this.#environment.set(NetworkRuntime, this.#runtime);
118
119
  await this.#runtime.construction.ready;
120
+ await this.act("network startup", agent => agent.get(NetworkBehavior).startup());
119
121
  } catch (e) {
120
122
  this.env.runtime.delete(this);
121
123
  throw e;