@matter/node 0.16.0-alpha.0-20251018-dd1ea6a8a → 0.16.0-alpha.0-20251020-3f6e46245

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 (127) hide show
  1. package/dist/cjs/behavior/Behavior.d.ts +1 -1
  2. package/dist/cjs/behavior/Behavior.d.ts.map +1 -1
  3. package/dist/cjs/behavior/Behavior.js +29 -3
  4. package/dist/cjs/behavior/Behavior.js.map +1 -1
  5. package/dist/cjs/behavior/cluster/ClusterBehavior.d.ts +1 -1
  6. package/dist/cjs/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
  7. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.d.ts.map +1 -1
  8. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.js +2 -4
  9. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.js.map +1 -1
  10. package/dist/cjs/behavior/supervision/RootSupervisor.d.ts.map +1 -1
  11. package/dist/cjs/behavior/supervision/RootSupervisor.js +2 -1
  12. package/dist/cjs/behavior/supervision/RootSupervisor.js.map +1 -1
  13. package/dist/cjs/behavior/system/commissioning/CommissioningClient.d.ts +35 -11
  14. package/dist/cjs/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  15. package/dist/cjs/behavior/system/commissioning/CommissioningClient.js +147 -138
  16. package/dist/cjs/behavior/system/commissioning/CommissioningClient.js.map +2 -2
  17. package/dist/cjs/behavior/system/commissioning/CommissioningServer.d.ts +0 -7
  18. package/dist/cjs/behavior/system/commissioning/CommissioningServer.d.ts.map +1 -1
  19. package/dist/cjs/behavior/system/commissioning/CommissioningServer.js +23 -27
  20. package/dist/cjs/behavior/system/commissioning/CommissioningServer.js.map +1 -1
  21. package/dist/cjs/behavior/system/commissioning/RemoteDescriptor.js +4 -4
  22. package/dist/cjs/behavior/system/commissioning/RemoteDescriptor.js.map +1 -1
  23. package/dist/cjs/behavior/system/network/NetworkClient.d.ts.map +1 -1
  24. package/dist/cjs/behavior/system/network/NetworkClient.js +7 -2
  25. package/dist/cjs/behavior/system/network/NetworkClient.js.map +1 -1
  26. package/dist/cjs/behavior/system/network/NetworkServer.js +1 -1
  27. package/dist/cjs/behavior/system/network/NetworkServer.js.map +1 -1
  28. package/dist/cjs/behaviors/access-control/AccessControlServer.d.ts.map +1 -1
  29. package/dist/cjs/behaviors/access-control/AccessControlServer.js +2 -9
  30. package/dist/cjs/behaviors/access-control/AccessControlServer.js.map +1 -1
  31. package/dist/cjs/behaviors/general-commissioning/GeneralCommissioningServer.js +1 -1
  32. package/dist/cjs/behaviors/general-commissioning/GeneralCommissioningServer.js.map +1 -1
  33. package/dist/cjs/node/ClientGroup.d.ts +18 -0
  34. package/dist/cjs/node/ClientGroup.d.ts.map +1 -0
  35. package/dist/cjs/node/ClientGroup.js +53 -0
  36. package/dist/cjs/node/ClientGroup.js.map +6 -0
  37. package/dist/cjs/node/ClientNode.d.ts +3 -0
  38. package/dist/cjs/node/ClientNode.d.ts.map +1 -1
  39. package/dist/cjs/node/ClientNode.js +8 -2
  40. package/dist/cjs/node/ClientNode.js.map +1 -1
  41. package/dist/cjs/node/client/ClientGroupInteraction.d.ts +22 -0
  42. package/dist/cjs/node/client/ClientGroupInteraction.d.ts.map +1 -0
  43. package/dist/cjs/node/client/ClientGroupInteraction.js +67 -0
  44. package/dist/cjs/node/client/ClientGroupInteraction.js.map +6 -0
  45. package/dist/cjs/node/client/ClientNodeFactory.d.ts +2 -1
  46. package/dist/cjs/node/client/ClientNodeFactory.d.ts.map +1 -1
  47. package/dist/cjs/node/client/ClientNodeFactory.js.map +1 -1
  48. package/dist/cjs/node/client/Peers.d.ts.map +1 -1
  49. package/dist/cjs/node/client/Peers.js +21 -8
  50. package/dist/cjs/node/client/Peers.js.map +1 -1
  51. package/dist/cjs/storage/client/ClientNodeStores.d.ts +2 -0
  52. package/dist/cjs/storage/client/ClientNodeStores.d.ts.map +1 -1
  53. package/dist/cjs/storage/client/ClientNodeStores.js +19 -0
  54. package/dist/cjs/storage/client/ClientNodeStores.js.map +1 -1
  55. package/dist/esm/behavior/Behavior.d.ts +1 -1
  56. package/dist/esm/behavior/Behavior.d.ts.map +1 -1
  57. package/dist/esm/behavior/Behavior.js +29 -3
  58. package/dist/esm/behavior/Behavior.js.map +1 -1
  59. package/dist/esm/behavior/cluster/ClusterBehavior.d.ts +1 -1
  60. package/dist/esm/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
  61. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.d.ts.map +1 -1
  62. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.js +3 -4
  63. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.js.map +1 -1
  64. package/dist/esm/behavior/supervision/RootSupervisor.d.ts.map +1 -1
  65. package/dist/esm/behavior/supervision/RootSupervisor.js +3 -1
  66. package/dist/esm/behavior/supervision/RootSupervisor.js.map +1 -1
  67. package/dist/esm/behavior/system/commissioning/CommissioningClient.d.ts +35 -11
  68. package/dist/esm/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  69. package/dist/esm/behavior/system/commissioning/CommissioningClient.js +167 -141
  70. package/dist/esm/behavior/system/commissioning/CommissioningClient.js.map +2 -2
  71. package/dist/esm/behavior/system/commissioning/CommissioningServer.d.ts +0 -7
  72. package/dist/esm/behavior/system/commissioning/CommissioningServer.d.ts.map +1 -1
  73. package/dist/esm/behavior/system/commissioning/CommissioningServer.js +23 -27
  74. package/dist/esm/behavior/system/commissioning/CommissioningServer.js.map +1 -1
  75. package/dist/esm/behavior/system/commissioning/RemoteDescriptor.js +4 -4
  76. package/dist/esm/behavior/system/commissioning/RemoteDescriptor.js.map +1 -1
  77. package/dist/esm/behavior/system/network/NetworkClient.d.ts.map +1 -1
  78. package/dist/esm/behavior/system/network/NetworkClient.js +7 -2
  79. package/dist/esm/behavior/system/network/NetworkClient.js.map +1 -1
  80. package/dist/esm/behavior/system/network/NetworkServer.js +1 -1
  81. package/dist/esm/behavior/system/network/NetworkServer.js.map +1 -1
  82. package/dist/esm/behaviors/access-control/AccessControlServer.d.ts.map +1 -1
  83. package/dist/esm/behaviors/access-control/AccessControlServer.js +2 -9
  84. package/dist/esm/behaviors/access-control/AccessControlServer.js.map +1 -1
  85. package/dist/esm/behaviors/general-commissioning/GeneralCommissioningServer.js +1 -1
  86. package/dist/esm/behaviors/general-commissioning/GeneralCommissioningServer.js.map +1 -1
  87. package/dist/esm/node/ClientGroup.d.ts +18 -0
  88. package/dist/esm/node/ClientGroup.d.ts.map +1 -0
  89. package/dist/esm/node/ClientGroup.js +33 -0
  90. package/dist/esm/node/ClientGroup.js.map +6 -0
  91. package/dist/esm/node/ClientNode.d.ts +3 -0
  92. package/dist/esm/node/ClientNode.d.ts.map +1 -1
  93. package/dist/esm/node/ClientNode.js +8 -2
  94. package/dist/esm/node/ClientNode.js.map +1 -1
  95. package/dist/esm/node/client/ClientGroupInteraction.d.ts +22 -0
  96. package/dist/esm/node/client/ClientGroupInteraction.d.ts.map +1 -0
  97. package/dist/esm/node/client/ClientGroupInteraction.js +47 -0
  98. package/dist/esm/node/client/ClientGroupInteraction.js.map +6 -0
  99. package/dist/esm/node/client/ClientNodeFactory.d.ts +2 -1
  100. package/dist/esm/node/client/ClientNodeFactory.d.ts.map +1 -1
  101. package/dist/esm/node/client/ClientNodeFactory.js.map +1 -1
  102. package/dist/esm/node/client/Peers.d.ts.map +1 -1
  103. package/dist/esm/node/client/Peers.js +21 -8
  104. package/dist/esm/node/client/Peers.js.map +1 -1
  105. package/dist/esm/storage/client/ClientNodeStores.d.ts +2 -0
  106. package/dist/esm/storage/client/ClientNodeStores.d.ts.map +1 -1
  107. package/dist/esm/storage/client/ClientNodeStores.js +20 -1
  108. package/dist/esm/storage/client/ClientNodeStores.js.map +1 -1
  109. package/package.json +7 -7
  110. package/src/behavior/Behavior.ts +42 -4
  111. package/src/behavior/cluster/ClusterBehavior.ts +1 -1
  112. package/src/behavior/cluster/ClusterBehaviorUtil.ts +7 -7
  113. package/src/behavior/supervision/RootSupervisor.ts +4 -2
  114. package/src/behavior/system/commissioning/CommissioningClient.ts +113 -73
  115. package/src/behavior/system/commissioning/CommissioningServer.ts +25 -30
  116. package/src/behavior/system/commissioning/RemoteDescriptor.ts +4 -4
  117. package/src/behavior/system/network/NetworkClient.ts +8 -2
  118. package/src/behavior/system/network/NetworkServer.ts +1 -1
  119. package/src/behaviors/access-control/AccessControlServer.ts +1 -8
  120. package/src/behaviors/general-commissioning/GeneralCommissioningServer.ts +1 -1
  121. package/src/node/ClientGroup.ts +36 -0
  122. package/src/node/ClientNode.ts +10 -2
  123. package/src/node/client/ClientEndpointInitializer.ts +1 -1
  124. package/src/node/client/ClientGroupInteraction.ts +70 -0
  125. package/src/node/client/ClientNodeFactory.ts +2 -1
  126. package/src/node/client/Peers.ts +23 -8
  127. package/src/storage/client/ClientNodeStores.ts +25 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter/node",
3
- "version": "0.16.0-alpha.0-20251018-dd1ea6a8a",
3
+ "version": "0.16.0-alpha.0-20251020-3f6e46245",
4
4
  "description": "API for building Matter nodes",
5
5
  "keywords": [
6
6
  "iot",
@@ -42,14 +42,14 @@
42
42
  "#*": "./src/*"
43
43
  },
44
44
  "dependencies": {
45
- "@matter/general": "0.16.0-alpha.0-20251018-dd1ea6a8a",
46
- "@matter/model": "0.16.0-alpha.0-20251018-dd1ea6a8a",
47
- "@matter/types": "0.16.0-alpha.0-20251018-dd1ea6a8a",
48
- "@matter/protocol": "0.16.0-alpha.0-20251018-dd1ea6a8a"
45
+ "@matter/general": "0.16.0-alpha.0-20251020-3f6e46245",
46
+ "@matter/model": "0.16.0-alpha.0-20251020-3f6e46245",
47
+ "@matter/types": "0.16.0-alpha.0-20251020-3f6e46245",
48
+ "@matter/protocol": "0.16.0-alpha.0-20251020-3f6e46245"
49
49
  },
50
50
  "devDependencies": {
51
- "@matter/tools": "0.16.0-alpha.0-20251018-dd1ea6a8a",
52
- "@matter/testing": "0.16.0-alpha.0-20251018-dd1ea6a8a"
51
+ "@matter/tools": "0.16.0-alpha.0-20251020-3f6e46245",
52
+ "@matter/testing": "0.16.0-alpha.0-20251020-3f6e46245"
53
53
  },
54
54
  "files": [
55
55
  "dist/**/*",
@@ -14,12 +14,11 @@ import {
14
14
  Observable,
15
15
  Transaction,
16
16
  } from "#general";
17
- import { Schema } from "#model";
17
+ import { ClassSemantics, Schema, Semantics } from "#model";
18
18
  import type { ClusterType } from "#types";
19
19
  import { Reactor } from "./Reactor.js";
20
20
  import type { BehaviorBacking } from "./internal/BehaviorBacking.js";
21
21
  import { DerivedState, EmptyState } from "./state/StateType.js";
22
- import { BehaviorSupervisor } from "./supervision/BehaviorSupervisor.js";
23
22
  import { RootSupervisor } from "./supervision/RootSupervisor.js";
24
23
 
25
24
  // Internal fields
@@ -68,7 +67,9 @@ export abstract class Behavior {
68
67
  * Schema is inferred from the methods and properties of the behavior but you can specify explicitly for additional
69
68
  * control.
70
69
  */
71
- static readonly schema?: Schema;
70
+ static get schema() {
71
+ return Schema(this);
72
+ }
72
73
 
73
74
  /**
74
75
  * By default behaviors load lazily as they are accessed. You can set this flag to true to force behaviors to load
@@ -139,7 +140,7 @@ export abstract class Behavior {
139
140
  if (Object.hasOwn(this, SUPERVISOR)) {
140
141
  return (this as StaticInternal)[SUPERVISOR] as RootSupervisor;
141
142
  }
142
- return ((this as StaticInternal)[SUPERVISOR] = BehaviorSupervisor(this));
143
+ return ((this as StaticInternal)[SUPERVISOR] = RootSupervisor.for(Schema(this) ?? Schema.empty));
143
144
  }
144
145
 
145
146
  /**
@@ -310,6 +311,43 @@ Object.defineProperties(Behavior.prototype, {
310
311
  },
311
312
  });
312
313
 
314
+ /**
315
+ * Install {@link ClassSemantics} extension logic to integrate schema metadata.
316
+ */
317
+ Object.defineProperties(Behavior, {
318
+ [ClassSemantics.extend]: {
319
+ value(this: Behavior.Type, decoration: ClassSemantics) {
320
+ const type = decoration.new as Behavior.Type;
321
+
322
+ // Support static override of schema
323
+ if (Object.hasOwn(type, "schema") && type.schema !== undefined) {
324
+ decoration.mutableModel = type.schema;
325
+ }
326
+
327
+ // Obtain state and base schema
328
+ const { State, Events, defaults } = type;
329
+ if (!State || !defaults) {
330
+ return;
331
+ }
332
+
333
+ // Merge state properties into my schema
334
+ if (ClassSemantics.hasOwnSemantics(State)) {
335
+ const stateSemantics = Semantics.classOf(State);
336
+ stateSemantics.mutableModel = decoration.mutableModel;
337
+ }
338
+
339
+ // Merge events into my schema
340
+ if (ClassSemantics.hasOwnSemantics(Events)) {
341
+ const eventSemantics = Semantics.classOf(Events);
342
+ eventSemantics.mutableModel = decoration.mutableModel;
343
+ }
344
+
345
+ // Augment with fields for untyped state members
346
+ decoration.defineUnknownMembers(defaults);
347
+ },
348
+ },
349
+ });
350
+
313
351
  export namespace Behavior {
314
352
  /**
315
353
  * Static properties supported by all behaviors.
@@ -7,7 +7,7 @@
7
7
  import { Events } from "#behavior/Events.js";
8
8
  import type { Agent } from "#endpoint/Agent.js";
9
9
  import { ImplementationError, MaybePromise } from "#general";
10
- import type { Schema } from "#model";
10
+ import { type Schema } from "#model";
11
11
  import { ClusterComposer, ClusterType, ElementModifier, TypeFromBitSchema } from "#types";
12
12
  import { Behavior } from "../Behavior.js";
13
13
  import type { BehaviorBacking } from "../internal/BehaviorBacking.js";
@@ -7,6 +7,7 @@
7
7
  import { Events, OfflineEvent, OnlineEvent, QuietEvent } from "#behavior/Events.js";
8
8
  import { camelize, EventEmitter, GeneratedClass, ImplementationError, Observable } from "#general";
9
9
  import {
10
+ ClassSemantics,
10
11
  ClusterModel,
11
12
  DefaultValue,
12
13
  ElementTag,
@@ -81,9 +82,6 @@ export function createType<const C extends ClusterType>(
81
82
  }
82
83
  }
83
84
 
84
- // Mutation of schema will almost certainly result in logic errors so ensure that can't happen
85
- schema.freeze();
86
-
87
85
  const newProps = {} as Record<string, ValueModel>;
88
86
  const scope = Scope(schema);
89
87
 
@@ -110,15 +108,17 @@ export function createType<const C extends ClusterType>(
110
108
  value: cluster,
111
109
  enumerable: true,
112
110
  },
113
-
114
- schema: {
115
- value: schema,
116
- },
117
111
  },
118
112
 
119
113
  instanceDescriptors: createDefaultCommandDescriptors(cluster, base),
120
114
  }) as ClusterBehavior.Type;
121
115
 
116
+ // Decorate the class
117
+ ClassSemantics.of(type).mutableModel = schema;
118
+
119
+ // Mutation of schema will almost certainly result in logic errors so ensure that can't happen
120
+ schema.finalize();
121
+
122
122
  if (useCache) {
123
123
  ClusterBehaviorCache.set(cluster, base, schema, type);
124
124
  }
@@ -8,6 +8,7 @@ import { camelize, InternalError } from "#general";
8
8
  import {
9
9
  AttributeModel,
10
10
  ClusterModel,
11
+ ElementTag,
11
12
  FeatureMap,
12
13
  FeatureSet,
13
14
  Matter,
@@ -160,8 +161,9 @@ export class RootSupervisor implements ValueSupervisor {
160
161
  // TODO: We should handle writable/fabric scoped being non-volatile already in the conformance interpreter
161
162
  if (
162
163
  member.effectiveQuality.nonvolatile ||
163
- member.effectiveAccess.writable ||
164
- member.effectiveAccess.fabricScoped
164
+ // Persist all writable attributes in addition to those officially marked as nonvolatile
165
+ (member.tag === ElementTag.Attribute &&
166
+ (member.effectiveAccess.writable || member.effectiveAccess.fabricScoped))
165
167
  ) {
166
168
  if (key === "id") {
167
169
  const id = member.effectiveId;
@@ -19,7 +19,22 @@ import {
19
19
  Time,
20
20
  Timestamp,
21
21
  } from "#general";
22
- import { DatatypeModel, FieldElement } from "#model";
22
+ import {
23
+ bool,
24
+ duration,
25
+ fabricIdx,
26
+ field,
27
+ listOf,
28
+ mandatory,
29
+ nodeId,
30
+ nonvolatile,
31
+ string,
32
+ systimeMs,
33
+ uint16,
34
+ uint32,
35
+ uint8,
36
+ vendorId,
37
+ } from "#model";
23
38
  import type { ClientNode } from "#node/ClientNode.js";
24
39
  import type { Node } from "#node/Node.js";
25
40
  import { IdentityService } from "#node/server/IdentityService.js";
@@ -32,14 +47,15 @@ import {
32
47
  FabricAuthority,
33
48
  FabricManager,
34
49
  LocatedNodeCommissioningOptions,
35
- PeerAddress,
36
- SessionParameters,
50
+ PeerAddress as ProtocolPeerAddress,
51
+ SessionIntervals as ProtocolSessionIntervals,
37
52
  Subscribe,
38
53
  } from "#protocol";
39
54
  import {
40
55
  CaseAuthenticatedTag,
41
56
  DeviceTypeId,
42
57
  DiscoveryCapabilitiesBitmap,
58
+ FabricIndex,
43
59
  ManualPairingCodeCodec,
44
60
  NodeId,
45
61
  TypeFromPartialBitSchema,
@@ -194,7 +210,7 @@ export class CommissioningClient extends Behavior {
194
210
  throw new ImplementationError("Cannot decommission node that is not commissioned");
195
211
  }
196
212
 
197
- const formerAddress = PeerAddress(peerAddress).toString();
213
+ const formerAddress = ProtocolPeerAddress(peerAddress).toString();
198
214
 
199
215
  const opcreds = this.agent.get(OperationalCredentialsClient);
200
216
 
@@ -218,7 +234,7 @@ export class CommissioningClient extends Behavior {
218
234
  * If you override, matter.js commissions to the point where commissioning over PASE is complete. You must then
219
235
  * complete commissioning yourself by connecting to the device and invokeint the "CommissioningComplete" command.
220
236
  */
221
- protected async finalizeCommissioning(_address: PeerAddress, _discoveryData?: DiscoveryData) {
237
+ protected async finalizeCommissioning(_address: ProtocolPeerAddress, _discoveryData?: DiscoveryData) {
222
238
  throw new NotImplementedError();
223
239
  }
224
240
 
@@ -235,7 +251,7 @@ export class CommissioningClient extends Behavior {
235
251
  endpoint.lifecycle.initialized.emit(this.state.peerAddress !== undefined);
236
252
  }
237
253
 
238
- #peerAddressChanged(addr?: PeerAddress) {
254
+ #peerAddressChanged(addr?: ProtocolPeerAddress) {
239
255
  const node = this.endpoint as ClientNode;
240
256
 
241
257
  if (addr) {
@@ -258,174 +274,198 @@ export class CommissioningClient extends Behavior {
258
274
  node.lifecycle.decommissioned.emit(this.context);
259
275
  }
260
276
  }
277
+ }
261
278
 
279
+ export namespace CommissioningClient {
262
280
  /**
263
- * Define logical schema. This enables runtime validation, make fields persistent and makes subfields editable.
281
+ * Concrete version of {@link ProtocolPeerAddress}.
264
282
  */
265
- static override readonly schema = new DatatypeModel(
266
- {
267
- name: "CommissioningState",
268
- type: "struct",
269
- },
270
-
271
- FieldElement({
272
- name: "peerAddress",
273
- type: "struct",
274
- quality: "N",
275
- children: [
276
- FieldElement({ name: "fabricIndex", type: "fabric-id" }),
277
- FieldElement({ name: "nodeId", type: "node-id" }),
278
- ],
279
- }),
280
-
281
- FieldElement({
282
- name: "addresses",
283
- type: "list",
284
- quality: "N",
285
- children: [
286
- FieldElement({
287
- name: "entry",
288
- type: "struct",
289
- children: [
290
- FieldElement({ name: "type", type: "string" }),
291
- FieldElement({ name: "ip", type: "string" }),
292
- FieldElement({ name: "port", type: "uint16" }),
293
- FieldElement({ name: "peripheralAddress", type: "string" }),
294
- ],
295
- }),
296
- ],
297
- }),
298
-
299
- FieldElement({ name: "discoveredAt", type: "systime-ms", quality: "N", conformance: "M" }),
300
- FieldElement({ name: "onlineAt", type: "systime-ms" }),
301
- FieldElement({ name: "offlineAt", type: "systime-ms" }),
302
- FieldElement({ name: "ttl", type: "uint32", quality: "N" }),
303
- FieldElement({ name: "deviceIdentifier", type: "string", quality: "N" }),
304
- FieldElement({ name: "discriminator", type: "uint16", quality: "N" }),
305
- FieldElement({ name: "commissioningMode", type: "uint8", quality: "N" }),
306
- FieldElement({ name: "vendorId", type: "vendor-id", quality: "N" }),
307
- FieldElement({ name: "productId", type: "uint16", quality: "N" }),
308
- FieldElement({ name: "deviceType", type: "uint16", quality: "N" }),
309
- FieldElement({ name: "deviceName", type: "string", quality: "N" }),
310
- FieldElement({ name: "rotatingIdentifier", type: "string", quality: "N" }),
311
- FieldElement({ name: "pairingHint", type: "uint32", quality: "N" }),
312
- FieldElement({ name: "pairingInstructions", type: "string", quality: "N" }),
313
- FieldElement({
314
- name: "sessionParameters",
315
- type: "struct",
316
- quality: "N",
317
- children: [
318
- FieldElement({ name: "idleInterval", type: "duration", constraint: "max 3600000" }),
319
- FieldElement({ name: "activeInterval", type: "duration", constraint: "max 3600000" }),
320
- FieldElement({ name: "activeThreshold", type: "duration", constraint: "max 65535" }),
321
- ],
322
- }),
323
- FieldElement({ name: "tcpSupport", type: "uint8", quality: "N" }),
324
- FieldElement({ name: "longIdleOperatingMode", type: "bool", quality: "N" }),
325
- );
326
- }
283
+ export class PeerAddress implements ProtocolPeerAddress {
284
+ @field(fabricIdx, mandatory)
285
+ fabricIndex: FabricIndex;
286
+
287
+ @field(nodeId, mandatory)
288
+ nodeId: NodeId;
289
+
290
+ constructor(fabricIndex: FabricIndex, nodeId: NodeId) {
291
+ this.fabricIndex = fabricIndex;
292
+ this.nodeId = nodeId;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Concrete version of {@link SessionIntervals}.
298
+ */
299
+ export class SessionIntervals implements ProtocolSessionIntervals {
300
+ @field(duration.extend({ constraint: "max 3600000" }), mandatory)
301
+ idleInterval: Duration;
302
+
303
+ @field(duration.extend({ constraint: "max 3600000" }), mandatory)
304
+ activeInterval: Duration;
305
+
306
+ @field(duration.extend({ constraint: "max 65535" }), mandatory)
307
+ activeThreshold: Duration;
308
+
309
+ constructor(intervals: SessionIntervals) {
310
+ this.idleInterval = intervals.idleInterval;
311
+ this.activeInterval = intervals.activeInterval;
312
+ this.activeThreshold = intervals.activeThreshold;
313
+ }
314
+ }
315
+
316
+ /**
317
+ * The network address of a node.
318
+ */
319
+ export class NetworkAddress implements ServerAddress.Definition {
320
+ @field(string, mandatory)
321
+ type: "udp" | "tcp" | "ble";
322
+
323
+ @field(string)
324
+ ip?: string;
325
+
326
+ @field(uint16)
327
+ port?: number;
328
+
329
+ @field(string)
330
+ peripheralAddress?: string;
331
+
332
+ @field(uint32)
333
+ ttl?: Duration | undefined;
334
+
335
+ @field(systimeMs)
336
+ discoveredAt?: Timestamp | undefined;
337
+
338
+ constructor(address: NetworkAddress) {
339
+ this.type = address.type;
340
+ this.ip = address.ip;
341
+ this.port = address.port;
342
+ this.peripheralAddress = address.peripheralAddress;
343
+ this.ttl = address.ttl;
344
+ this.discoveredAt = address.discoveredAt;
345
+ }
346
+ }
327
347
 
328
- export namespace CommissioningClient {
329
348
  export class State {
330
349
  /**
331
350
  * Fabric index and node ID for paired peers. If this is undefined the node is uncommissioned.
332
351
  */
352
+ @field(PeerAddress, nonvolatile)
333
353
  peerAddress?: PeerAddress;
334
354
 
335
355
  /**
336
356
  * Known network addresses for the device. If this is undefined the node has not been located on any network
337
357
  * interface.
338
358
  */
359
+ @field(listOf(NetworkAddress), nonvolatile)
339
360
  addresses?: ServerAddress.Definition[];
340
361
 
341
362
  /**
342
363
  * Time at which the device was discovered.
343
364
  */
365
+ @field(systimeMs, nonvolatile)
344
366
  discoveredAt?: Timestamp;
345
367
 
346
368
  /**
347
369
  * Time at which we discovered the device's current operational addresses.
348
370
  */
371
+ @field(systimeMs)
349
372
  onlineAt?: Timestamp;
350
373
 
351
374
  /**
352
375
  * Time at which we concluded the device's current operational address is unreachable.
353
376
  */
377
+ @field(systimeMs)
354
378
  offlineAt?: Timestamp;
355
379
 
356
380
  /**
357
381
  * The TTL of the discovery record if applicable (in seconds).
358
382
  */
383
+ @field(duration, nonvolatile)
359
384
  ttl?: Duration;
360
385
 
361
386
  /**
362
387
  * The canonical global ID of the device.
363
388
  */
389
+ @field(string, nonvolatile)
364
390
  deviceIdentifier?: string;
365
391
 
366
392
  /**
367
393
  * The device's long discriminator.
368
394
  */
395
+ @field(uint16, nonvolatile)
369
396
  discriminator?: number;
370
397
 
371
398
  /**
372
399
  * The last know commissioning mode of the device.
373
400
  */
401
+ @field(uint8, nonvolatile)
374
402
  commissioningMode?: CommissioningMode;
375
403
 
376
404
  /**
377
405
  * Vendor.
378
406
  */
407
+ @field(vendorId, nonvolatile)
379
408
  vendorId?: VendorId;
380
409
 
381
410
  /**
382
411
  * Product.
383
412
  */
413
+ @field(uint16, nonvolatile)
384
414
  productId?: number;
385
415
 
386
416
  /**
387
417
  * Advertised device type.
388
418
  */
419
+ @field(uint16, nonvolatile)
389
420
  deviceType?: DeviceTypeId;
390
421
 
391
422
  /**
392
423
  * The advertised device name specified by the user.
393
424
  */
425
+ @field(string, nonvolatile)
394
426
  deviceName?: string;
395
427
 
396
428
  /**
397
429
  * An optional manufacturer-specific unique rotating ID for uniquely identifying the device.
398
430
  */
431
+ @field(string, nonvolatile)
399
432
  rotatingIdentifier?: string;
400
433
 
401
434
  /**
402
435
  * A bitmap indicating how to transition the device to commissioning mode from its current state.
403
436
  */
437
+ @field(uint32, nonvolatile)
404
438
  pairingHint?: number;
405
439
 
406
440
  /**
407
441
  * Textual pairing instructions associated with pairing hint.
408
442
  */
443
+ @field(string, nonvolatile)
409
444
  pairingInstructions?: string;
410
445
 
411
446
  /**
412
- * The remote node's session parameters.
447
+ * The remote node's session intervals.
413
448
  */
414
- sessionParameters?: Partial<SessionParameters>;
449
+ @field(SessionIntervals, nonvolatile)
450
+ sessionIntervals?: Partial<ProtocolSessionIntervals>;
415
451
 
416
452
  /**
417
453
  * TCP support bitmap.
418
454
  */
455
+ @field(uint8, nonvolatile)
419
456
  tcpSupport?: number;
420
457
 
421
458
  /**
422
459
  * Indicates whether node is ICD with a slow (15 s+) polling interval.
423
460
  */
461
+ @field(bool, nonvolatile)
424
462
  longIdleTimeOperatingMode?: boolean;
425
463
  }
426
464
 
427
465
  export class Events extends BaseEvents {
428
- peerAddress$Changed = new Observable<[value: PeerAddress | undefined, oldValue: PeerAddress | undefined]>();
466
+ peerAddress$Changed = new Observable<
467
+ [value: ProtocolPeerAddress | undefined, oldValue: ProtocolPeerAddress | undefined]
468
+ >();
429
469
  }
430
470
 
431
471
  /**
@@ -296,35 +296,6 @@ export class CommissioningServer extends Behavior {
296
296
  );
297
297
  }
298
298
 
299
- /**
300
- * Obtain pairing codes for a node.
301
- */
302
- static pairingCodesFor(node: Endpoint) {
303
- const bi = node.stateOf(BasicInformationBehavior);
304
- const comm = node.stateOf(CommissioningServer);
305
- const net = node.stateOf(NetworkServer);
306
-
307
- const qrPairingCode = QrPairingCodeCodec.encode([
308
- {
309
- version: 0,
310
- vendorId: bi.vendorId,
311
- productId: bi.productId,
312
- flowType: comm.flowType,
313
- discriminator: comm.discriminator,
314
- passcode: comm.passcode,
315
- discoveryCapabilities: DiscoveryCapabilitiesSchema.encode(net.discoveryCapabilities),
316
- },
317
- ]);
318
-
319
- return {
320
- manualPairingCode: ManualPairingCodeCodec.encode({
321
- discriminator: comm.discriminator,
322
- passcode: comm.passcode,
323
- }),
324
- qrPairingCode,
325
- };
326
- }
327
-
328
299
  /**
329
300
  * Define logical schema to make passcode and discriminator persistent.
330
301
  */
@@ -384,9 +355,33 @@ export namespace CommissioningServer {
384
355
  ble?: BleAdvertiser.Options;
385
356
 
386
357
  [Val.properties](endpoint: Endpoint) {
358
+ const comm = this;
387
359
  return {
388
360
  get pairingCodes() {
389
- return CommissioningServer.pairingCodesFor(endpoint);
361
+ const bi = endpoint.stateOf(BasicInformationBehavior);
362
+ const net = endpoint.stateOf(NetworkServer);
363
+
364
+ const qrPairingCode = QrPairingCodeCodec.encode([
365
+ {
366
+ version: 0,
367
+ vendorId: bi.vendorId,
368
+ productId: bi.productId,
369
+ flowType: comm.flowType,
370
+ discriminator: comm.discriminator,
371
+ passcode: comm.passcode,
372
+ discoveryCapabilities: DiscoveryCapabilitiesSchema.encode(net.discoveryCapabilities),
373
+ },
374
+ ]);
375
+
376
+ return {
377
+ manualPairingCode: ManualPairingCodeCodec.encode({
378
+ // We use -1 to flag "need generated value" but this will crash the pairing code generator. So use 0
379
+ // so we don't throw an error during initialization
380
+ discriminator: comm.discriminator < 0 ? 0 : comm.discriminator,
381
+ passcode: comm.passcode < 0 ? 0 : comm.passcode,
382
+ }),
383
+ qrPairingCode,
384
+ };
390
385
  },
391
386
 
392
387
  get fabrics() {
@@ -57,7 +57,7 @@ export namespace RemoteDescriptor {
57
57
  rotatingIdentifier,
58
58
  pairingHint,
59
59
  pairingInstructions,
60
- sessionParameters,
60
+ sessionIntervals,
61
61
  tcpSupport,
62
62
  longIdleTimeOperatingMode,
63
63
  } = long;
@@ -102,8 +102,8 @@ export namespace RemoteDescriptor {
102
102
  result.PI = pairingInstructions;
103
103
  }
104
104
 
105
- if (sessionParameters !== undefined) {
106
- const { idleInterval, activeInterval, activeThreshold } = sessionParameters;
105
+ if (sessionIntervals !== undefined) {
106
+ const { idleInterval, activeInterval, activeThreshold } = sessionIntervals;
107
107
 
108
108
  if (idleInterval !== undefined) {
109
109
  result.SII = idleInterval;
@@ -189,7 +189,7 @@ export namespace RemoteDescriptor {
189
189
  if (SAT !== undefined) {
190
190
  (sessionParameters ??= {}).activeThreshold = SAT;
191
191
  }
192
- long.sessionParameters = sessionParameters;
192
+ long.sessionIntervals = sessionParameters;
193
193
 
194
194
  long.deviceType = DT === undefined ? undefined : DeviceTypeId(DT);
195
195
  long.deviceName = DN;
@@ -20,8 +20,14 @@ export class NetworkClient extends NetworkBehavior {
20
20
  declare events: NetworkClient.Events;
21
21
 
22
22
  override initialize() {
23
- this.reactTo(this.events.autoSubscribe$Changed, this.#handleSubscription);
24
- this.reactTo(this.events.defaultSubscription$Changed, this.#handleChangedDefaultSubscription);
23
+ if (this.#node.isGroup) {
24
+ // Groups can never subscribe
25
+ this.state.autoSubscribe = false;
26
+ this.state.defaultSubscription = undefined;
27
+ } else {
28
+ this.reactTo(this.events.autoSubscribe$Changed, this.#handleSubscription, { offline: true });
29
+ this.reactTo(this.events.defaultSubscription$Changed, this.#handleChangedDefaultSubscription);
30
+ }
25
31
  }
26
32
 
27
33
  override async startup() {
@@ -49,7 +49,7 @@ export class NetworkServer extends NetworkBehavior {
49
49
  discoveryCaps.onIpNetwork = true;
50
50
  }
51
51
 
52
- this.reactTo(this.agent.get(CommissioningServer).events.commissioned, this.#endUncommissionedMode);
52
+ this.reactTo(this.endpoint.eventsOf(CommissioningServer).commissioned, this.#endUncommissionedMode);
53
53
 
54
54
  return super.initialize();
55
55
  }
@@ -77,21 +77,14 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
77
77
  // Handle Backward compatibility to Matter.js before 0.9.1 and add the missing ACL entry if no entry was set
78
78
  // so far by the controller
79
79
  const fallbackAcl: AccessControlTypes.AccessControlEntry = {
80
- fabricIndex: fabric.fabricIndex,
81
80
  privilege: AccessControlTypes.AccessControlEntryPrivilege.Administer,
82
81
  authMode: AccessControlTypes.AccessControlEntryAuthMode.Case,
83
82
  subjects: [fabric.rootNodeId],
84
83
  targets: null, // entire node
84
+ fabricIndex: fabric.fabricIndex,
85
85
  };
86
86
  this.state.acl.push(fallbackAcl);
87
87
  fabricAcls.push(fallbackAcl);
88
- logger.warn(
89
- "Added missing ACL entry for fabric",
90
- fabric.fabricIndex,
91
- "for Node ID",
92
- fabric.rootNodeId,
93
- ". This should only happen once after upgrading to matter.js 0.9.1",
94
- );
95
88
  }
96
89
  fabric.accessControl.aclList = fabricAcls;
97
90
  fabric.accessControl.extensionEntryAccessCheck = this.extensionEntryAccessCheck.bind(this);