@matter/node 0.16.0-alpha.0-20251103-b47ffa15b → 0.16.0-alpha.0-20251104-8c3166ea3

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 (59) hide show
  1. package/dist/cjs/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
  2. package/dist/cjs/behavior/cluster/ClusterBehavior.js +8 -5
  3. package/dist/cjs/behavior/cluster/ClusterBehavior.js.map +1 -1
  4. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.d.ts +1 -1
  5. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.d.ts.map +1 -1
  6. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.js +7 -32
  7. package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.js.map +1 -1
  8. package/dist/cjs/behavior/cluster/ValidatedElements.d.ts +13 -0
  9. package/dist/cjs/behavior/cluster/ValidatedElements.d.ts.map +1 -1
  10. package/dist/cjs/behavior/cluster/ValidatedElements.js +34 -11
  11. package/dist/cjs/behavior/cluster/ValidatedElements.js.map +1 -1
  12. package/dist/cjs/behavior/internal/ClientBehaviorBacking.d.ts.map +1 -1
  13. package/dist/cjs/behavior/internal/ClientBehaviorBacking.js +2 -1
  14. package/dist/cjs/behavior/internal/ClientBehaviorBacking.js.map +1 -1
  15. package/dist/cjs/behavior/internal/ServerBehaviorBacking.d.ts.map +1 -1
  16. package/dist/cjs/behavior/internal/ServerBehaviorBacking.js +2 -0
  17. package/dist/cjs/behavior/internal/ServerBehaviorBacking.js.map +1 -1
  18. package/dist/cjs/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  19. package/dist/cjs/endpoint/properties/Behaviors.d.ts +6 -0
  20. package/dist/cjs/endpoint/properties/Behaviors.d.ts.map +1 -1
  21. package/dist/cjs/endpoint/properties/Behaviors.js +14 -0
  22. package/dist/cjs/endpoint/properties/Behaviors.js.map +1 -1
  23. package/dist/cjs/node/client/ClientBehavior.d.ts.map +1 -1
  24. package/dist/cjs/node/client/ClientBehavior.js +49 -3
  25. package/dist/cjs/node/client/ClientBehavior.js.map +1 -1
  26. package/dist/esm/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
  27. package/dist/esm/behavior/cluster/ClusterBehavior.js +9 -6
  28. package/dist/esm/behavior/cluster/ClusterBehavior.js.map +1 -1
  29. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.d.ts +1 -1
  30. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.d.ts.map +1 -1
  31. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.js +7 -34
  32. package/dist/esm/behavior/cluster/ClusterBehaviorUtil.js.map +1 -1
  33. package/dist/esm/behavior/cluster/ValidatedElements.d.ts +13 -0
  34. package/dist/esm/behavior/cluster/ValidatedElements.d.ts.map +1 -1
  35. package/dist/esm/behavior/cluster/ValidatedElements.js +35 -12
  36. package/dist/esm/behavior/cluster/ValidatedElements.js.map +1 -1
  37. package/dist/esm/behavior/internal/ClientBehaviorBacking.d.ts.map +1 -1
  38. package/dist/esm/behavior/internal/ClientBehaviorBacking.js +2 -1
  39. package/dist/esm/behavior/internal/ClientBehaviorBacking.js.map +1 -1
  40. package/dist/esm/behavior/internal/ServerBehaviorBacking.d.ts.map +1 -1
  41. package/dist/esm/behavior/internal/ServerBehaviorBacking.js +2 -0
  42. package/dist/esm/behavior/internal/ServerBehaviorBacking.js.map +1 -1
  43. package/dist/esm/behavior/system/commissioning/CommissioningClient.d.ts.map +1 -1
  44. package/dist/esm/endpoint/properties/Behaviors.d.ts +6 -0
  45. package/dist/esm/endpoint/properties/Behaviors.d.ts.map +1 -1
  46. package/dist/esm/endpoint/properties/Behaviors.js +14 -0
  47. package/dist/esm/endpoint/properties/Behaviors.js.map +1 -1
  48. package/dist/esm/node/client/ClientBehavior.d.ts.map +1 -1
  49. package/dist/esm/node/client/ClientBehavior.js +50 -4
  50. package/dist/esm/node/client/ClientBehavior.js.map +1 -1
  51. package/package.json +7 -7
  52. package/src/behavior/cluster/ClusterBehavior.ts +18 -10
  53. package/src/behavior/cluster/ClusterBehaviorUtil.ts +10 -52
  54. package/src/behavior/cluster/ValidatedElements.ts +41 -14
  55. package/src/behavior/internal/ClientBehaviorBacking.ts +2 -3
  56. package/src/behavior/internal/ServerBehaviorBacking.ts +3 -1
  57. package/src/behavior/system/commissioning/CommissioningClient.ts +1 -1
  58. package/src/endpoint/properties/Behaviors.ts +18 -0
  59. package/src/node/client/ClientBehavior.ts +80 -5
@@ -7,7 +7,7 @@
7
7
  import { Behavior } from "#behavior/Behavior.js";
8
8
  import { ClusterBehavior } from "#behavior/cluster/ClusterBehavior.js";
9
9
  import { camelize, capitalize, InternalError } from "#general";
10
- import { AttributeModel, ClusterModel, CommandModel, FeatureBitmap, Matter } from "#model";
10
+ import { AttributeModel, ClusterModel, CommandModel, Conformance, FeatureBitmap, Matter } from "#model";
11
11
  import type { ClientNode } from "#node/ClientNode.js";
12
12
  import { Node } from "#node/Node.js";
13
13
  import { ClientInteraction, Invoke } from "#protocol";
@@ -75,7 +75,7 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
75
75
 
76
76
  let { schema } = analysis;
77
77
  let isCloned = false;
78
- const { extraAttrs, extraCommands } = analysis;
78
+ const { attrSupportOverrides, extraAttrs, commandSupportOverrides, extraCommands } = analysis;
79
79
 
80
80
  // Obtain a ClusterType. This provides TLV for known elements
81
81
  let { cluster } = baseType;
@@ -107,7 +107,13 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
107
107
 
108
108
  // If the schema does not match what the device actually returned, further augment both the ClusterModel and
109
109
  // ClusterType with unknown attributes and/or commands
110
- if (schema.revision !== analysis.shape.revision || extraAttrs.size || extraCommands.size) {
110
+ if (
111
+ schema.revision !== analysis.shape.revision ||
112
+ extraAttrs.size ||
113
+ extraCommands.size ||
114
+ Object.keys(attrSupportOverrides).length ||
115
+ Object.keys(commandSupportOverrides).length
116
+ ) {
111
117
  cloneSchema();
112
118
 
113
119
  cluster = {
@@ -117,12 +123,24 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
117
123
  commands: { ...cluster.commands },
118
124
  };
119
125
 
126
+ if (attrSupportOverrides) {
127
+ for (const [attr, isSupported] of attrSupportOverrides.entries()) {
128
+ schema.children.push(attr.extend({ operationalIsSupported: isSupported }));
129
+ }
130
+ }
131
+
120
132
  for (const id of extraAttrs) {
121
133
  const name = createUnknownName("attr", id);
122
134
  cluster.attributes[camelize(name, false)] = Attribute(id, TlvAny);
123
135
  schema.children.push(new AttributeModel({ id, name, type: "any" }));
124
136
  }
125
137
 
138
+ if (commandSupportOverrides) {
139
+ for (const [command, isSupported] of commandSupportOverrides.entries()) {
140
+ schema.children.push(command.extend({ operationalIsSupported: isSupported }));
141
+ }
142
+ }
143
+
126
144
  for (const id of extraCommands) {
127
145
  const name = createUnknownName("command", id);
128
146
  cluster.commands[camelize(name, false)] = Command(id, TlvAny, 0, TlvNoResponse);
@@ -233,29 +251,86 @@ function createUnknownName(prefix: string, id: number) {
233
251
  interface ShapeAnalysis {
234
252
  schema: ClusterModel & { id: ClusterId };
235
253
  shape: ClientBehavior.ClusterShape;
254
+ attrSupportOverrides: Map<AttributeModel, boolean>;
236
255
  extraAttrs: Set<number>;
256
+ commandSupportOverrides: Map<CommandModel, boolean>;
237
257
  extraCommands: Set<number>;
238
258
  }
239
259
 
260
+ /**
261
+ * Analyze the cluster shape to determine how we should override the behavior and schema.
262
+ */
240
263
  function ShapeAnalysis(shape: ClientBehavior.ClusterShape): ShapeAnalysis {
264
+ const standardCluster = Matter.get(ClusterModel, shape.id);
241
265
  const schema =
242
- Matter.get(ClusterModel, shape.id) ??
266
+ standardCluster ??
243
267
  new ClusterModel({ id: shape.id, name: createUnknownName("Cluster", shape.id), revision: shape.revision });
244
268
 
245
- const extraAttrs = new Set(shape.attributes);
269
+ const attrSupportOverrides = new Map<AttributeModel, boolean>();
270
+ const extraAttrs = new Set<number>(shape.attributes);
246
271
  for (const attr of schema.attributes) {
272
+ maybeOverrideSupport(standardCluster, attr, extraAttrs, attrSupportOverrides);
273
+ if (standardCluster) {
274
+ const supported = extraAttrs.has(attr.id);
275
+ const applicability = attr.conformance.applicabilityFor(standardCluster);
276
+ if (!supported) {
277
+ if (applicability) {
278
+ attrSupportOverrides.set(attr, false);
279
+ }
280
+ } else {
281
+ if (applicability !== Conformance.Applicability.Mandatory) {
282
+ attrSupportOverrides.set(attr, true);
283
+ }
284
+ }
285
+ }
247
286
  extraAttrs.delete(attr.id as AttributeId);
248
287
  }
249
288
 
289
+ const commandSupportOverrides = new Map<CommandModel, boolean>();
250
290
  const extraCommands = new Set(shape.commands);
251
291
  for (const command of schema.commands) {
292
+ maybeOverrideSupport(standardCluster, command, extraCommands, commandSupportOverrides);
252
293
  extraCommands.delete(command.id as CommandId);
253
294
  }
254
295
 
255
296
  return {
256
297
  schema: schema as ClusterModel & { id: ClusterId },
257
298
  shape,
299
+ attrSupportOverrides,
258
300
  extraAttrs,
301
+ commandSupportOverrides,
259
302
  extraCommands,
260
303
  };
261
304
  }
305
+
306
+ /**
307
+ * Determine whether we need to override {@link ClusterModel#operationalIsSupported}.
308
+ *
309
+ * We do this if:
310
+ *
311
+ * * The element may be present according to the standard but is not implemented on the peer, or
312
+ *
313
+ * * the element is optional according to the standard and is implemented on the peer
314
+ */
315
+ function maybeOverrideSupport<T extends AttributeModel | CommandModel>(
316
+ standardCluster: ClusterModel | undefined,
317
+ element: T,
318
+ supported: Set<number>,
319
+ overrides: Map<T, boolean>,
320
+ ) {
321
+ if (!standardCluster) {
322
+ return;
323
+ }
324
+
325
+ const isSupported = supported.has(element.id);
326
+ const applicability = element.conformance.applicabilityFor(standardCluster);
327
+ if (!isSupported) {
328
+ if (applicability) {
329
+ overrides.set(element, false);
330
+ }
331
+ } else {
332
+ if (applicability !== Conformance.Applicability.Mandatory) {
333
+ overrides.set(element, true);
334
+ }
335
+ }
336
+ }