@matter/protocol 0.13.1-alpha.0-20250515-a4c61c546 → 0.13.1-alpha.0-20250516-6288f3c54

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 (132) hide show
  1. package/dist/cjs/action/Interactable.d.ts +5 -1
  2. package/dist/cjs/action/Interactable.d.ts.map +1 -1
  3. package/dist/cjs/action/client/ClientInteraction.d.ts +3 -4
  4. package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
  5. package/dist/cjs/action/client/ClientInteraction.js +28 -16
  6. package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
  7. package/dist/cjs/action/protocols.d.ts +7 -2
  8. package/dist/cjs/action/protocols.d.ts.map +1 -1
  9. package/dist/cjs/action/request/Write.d.ts +43 -2
  10. package/dist/cjs/action/request/Write.d.ts.map +1 -1
  11. package/dist/cjs/action/request/Write.js +74 -0
  12. package/dist/cjs/action/request/Write.js.map +2 -2
  13. package/dist/cjs/action/response/InvokeResult.d.ts +1 -2
  14. package/dist/cjs/action/response/InvokeResult.d.ts.map +1 -1
  15. package/dist/cjs/action/response/ReadResult.d.ts +5 -14
  16. package/dist/cjs/action/response/ReadResult.d.ts.map +1 -1
  17. package/dist/cjs/action/response/WriteResult.d.ts +19 -5
  18. package/dist/cjs/action/response/WriteResult.d.ts.map +1 -1
  19. package/dist/cjs/action/server/AccessControl.js +4 -4
  20. package/dist/cjs/action/server/AccessControl.js.map +1 -1
  21. package/dist/cjs/action/server/{AttributeResponse.d.ts → AttributeReadResponse.d.ts} +4 -4
  22. package/dist/cjs/action/server/AttributeReadResponse.d.ts.map +1 -0
  23. package/dist/cjs/action/server/{AttributeResponse.js → AttributeReadResponse.js} +12 -12
  24. package/dist/cjs/action/server/{AttributeResponse.js.map → AttributeReadResponse.js.map} +2 -2
  25. package/dist/cjs/action/server/AttributeSubscriptionResponse.d.ts +4 -4
  26. package/dist/cjs/action/server/AttributeSubscriptionResponse.d.ts.map +1 -1
  27. package/dist/cjs/action/server/AttributeSubscriptionResponse.js +2 -2
  28. package/dist/cjs/action/server/AttributeSubscriptionResponse.js.map +1 -1
  29. package/dist/cjs/action/server/AttributeWriteResponse.d.ts +28 -0
  30. package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -0
  31. package/dist/cjs/action/server/AttributeWriteResponse.js +349 -0
  32. package/dist/cjs/action/server/AttributeWriteResponse.js.map +6 -0
  33. package/dist/cjs/action/server/DataResponse.d.ts +4 -3
  34. package/dist/cjs/action/server/DataResponse.d.ts.map +1 -1
  35. package/dist/cjs/action/server/DataResponse.js +1 -1
  36. package/dist/cjs/action/server/DataResponse.js.map +1 -1
  37. package/dist/cjs/action/server/{EventResponse.d.ts → EventReadResponse.d.ts} +4 -4
  38. package/dist/cjs/action/server/EventReadResponse.d.ts.map +1 -0
  39. package/dist/cjs/action/server/{EventResponse.js → EventReadResponse.js} +8 -8
  40. package/dist/cjs/action/server/EventReadResponse.js.map +6 -0
  41. package/dist/cjs/action/server/ServerInteraction.d.ts +3 -4
  42. package/dist/cjs/action/server/ServerInteraction.d.ts.map +1 -1
  43. package/dist/cjs/action/server/ServerInteraction.js +12 -10
  44. package/dist/cjs/action/server/ServerInteraction.js.map +1 -1
  45. package/dist/cjs/action/server/index.d.ts +3 -2
  46. package/dist/cjs/action/server/index.d.ts.map +1 -1
  47. package/dist/cjs/action/server/index.js +3 -2
  48. package/dist/cjs/action/server/index.js.map +1 -1
  49. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  50. package/dist/cjs/interaction/InteractionClient.js +12 -1
  51. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  52. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  53. package/dist/cjs/interaction/InteractionMessenger.js +8 -3
  54. package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
  55. package/dist/esm/action/Interactable.d.ts +5 -1
  56. package/dist/esm/action/Interactable.d.ts.map +1 -1
  57. package/dist/esm/action/client/ClientInteraction.d.ts +3 -4
  58. package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
  59. package/dist/esm/action/client/ClientInteraction.js +29 -17
  60. package/dist/esm/action/client/ClientInteraction.js.map +1 -1
  61. package/dist/esm/action/protocols.d.ts +7 -2
  62. package/dist/esm/action/protocols.d.ts.map +1 -1
  63. package/dist/esm/action/request/Write.d.ts +43 -2
  64. package/dist/esm/action/request/Write.d.ts.map +1 -1
  65. package/dist/esm/action/request/Write.js +70 -0
  66. package/dist/esm/action/request/Write.js.map +2 -2
  67. package/dist/esm/action/response/InvokeResult.d.ts +1 -2
  68. package/dist/esm/action/response/InvokeResult.d.ts.map +1 -1
  69. package/dist/esm/action/response/ReadResult.d.ts +5 -14
  70. package/dist/esm/action/response/ReadResult.d.ts.map +1 -1
  71. package/dist/esm/action/response/WriteResult.d.ts +19 -5
  72. package/dist/esm/action/response/WriteResult.d.ts.map +1 -1
  73. package/dist/esm/action/server/AccessControl.js +4 -4
  74. package/dist/esm/action/server/AccessControl.js.map +1 -1
  75. package/dist/esm/action/server/{AttributeResponse.d.ts → AttributeReadResponse.d.ts} +4 -4
  76. package/dist/esm/action/server/AttributeReadResponse.d.ts.map +1 -0
  77. package/dist/esm/action/server/{AttributeResponse.js → AttributeReadResponse.js} +9 -9
  78. package/dist/esm/action/server/{AttributeResponse.js.map → AttributeReadResponse.js.map} +2 -2
  79. package/dist/esm/action/server/AttributeSubscriptionResponse.d.ts +4 -4
  80. package/dist/esm/action/server/AttributeSubscriptionResponse.d.ts.map +1 -1
  81. package/dist/esm/action/server/AttributeSubscriptionResponse.js +2 -2
  82. package/dist/esm/action/server/AttributeSubscriptionResponse.js.map +1 -1
  83. package/dist/esm/action/server/AttributeWriteResponse.d.ts +28 -0
  84. package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -0
  85. package/dist/esm/action/server/AttributeWriteResponse.js +335 -0
  86. package/dist/esm/action/server/AttributeWriteResponse.js.map +6 -0
  87. package/dist/esm/action/server/DataResponse.d.ts +4 -3
  88. package/dist/esm/action/server/DataResponse.d.ts.map +1 -1
  89. package/dist/esm/action/server/DataResponse.js +1 -1
  90. package/dist/esm/action/server/DataResponse.js.map +1 -1
  91. package/dist/esm/action/server/{EventResponse.d.ts → EventReadResponse.d.ts} +4 -4
  92. package/dist/esm/action/server/EventReadResponse.d.ts.map +1 -0
  93. package/dist/esm/action/server/{EventResponse.js → EventReadResponse.js} +5 -5
  94. package/dist/esm/action/server/EventReadResponse.js.map +6 -0
  95. package/dist/esm/action/server/ServerInteraction.d.ts +3 -4
  96. package/dist/esm/action/server/ServerInteraction.d.ts.map +1 -1
  97. package/dist/esm/action/server/ServerInteraction.js +12 -10
  98. package/dist/esm/action/server/ServerInteraction.js.map +1 -1
  99. package/dist/esm/action/server/index.d.ts +3 -2
  100. package/dist/esm/action/server/index.d.ts.map +1 -1
  101. package/dist/esm/action/server/index.js +3 -2
  102. package/dist/esm/action/server/index.js.map +1 -1
  103. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  104. package/dist/esm/interaction/InteractionClient.js +12 -1
  105. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  106. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  107. package/dist/esm/interaction/InteractionMessenger.js +8 -3
  108. package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
  109. package/package.json +6 -6
  110. package/src/action/Interactable.ts +6 -1
  111. package/src/action/client/ClientInteraction.ts +31 -23
  112. package/src/action/protocols.ts +8 -2
  113. package/src/action/request/Write.ts +127 -4
  114. package/src/action/response/InvokeResult.ts +1 -2
  115. package/src/action/response/ReadResult.ts +5 -22
  116. package/src/action/response/WriteResult.ts +21 -5
  117. package/src/action/server/AccessControl.ts +4 -4
  118. package/src/action/server/{AttributeResponse.ts → AttributeReadResponse.ts} +14 -13
  119. package/src/action/server/AttributeSubscriptionResponse.ts +5 -5
  120. package/src/action/server/AttributeWriteResponse.ts +437 -0
  121. package/src/action/server/DataResponse.ts +5 -4
  122. package/src/action/server/{EventResponse.ts → EventReadResponse.ts} +6 -5
  123. package/src/action/server/ServerInteraction.ts +16 -14
  124. package/src/action/server/index.ts +3 -2
  125. package/src/interaction/InteractionClient.ts +20 -1
  126. package/src/interaction/InteractionMessenger.ts +8 -3
  127. package/dist/cjs/action/server/AttributeResponse.d.ts.map +0 -1
  128. package/dist/cjs/action/server/EventResponse.d.ts.map +0 -1
  129. package/dist/cjs/action/server/EventResponse.js.map +0 -6
  130. package/dist/esm/action/server/AttributeResponse.d.ts.map +0 -1
  131. package/dist/esm/action/server/EventResponse.d.ts.map +0 -1
  132. package/dist/esm/action/server/EventResponse.js.map +0 -6
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Interactable } from "#action/Interactable.js";
7
+ import { Interactable, InteractionSession } from "#action/Interactable.js";
8
8
  import { Invoke } from "#action/request/Invoke.js";
9
9
  import { Read } from "#action/request/Read.js";
10
10
  import { Subscribe } from "#action/request/Subscribe.js";
@@ -13,13 +13,11 @@ import { InvokeResult } from "#action/response/InvokeResult.js";
13
13
  import { ReadResult } from "#action/response/ReadResult.js";
14
14
  import { SubscribeResult } from "#action/response/SubscribeResult.js";
15
15
  import { WriteResult } from "#action/response/WriteResult.js";
16
- import { AccessControl } from "#action/server/AccessControl.js";
17
- import { CancelablePromise, Environment, Environmental, NotImplementedError, PromiseQueue } from "#general";
16
+ import { Environment, Environmental, NotImplementedError, PromiseQueue } from "#general";
18
17
  import { InteractionClientMessenger } from "#interaction/InteractionMessenger.js";
19
18
  import { SubscriptionClient } from "#interaction/SubscriptionClient.js";
20
19
  import { InteractionQueue } from "#peer/InteractionQueue.js";
21
20
  import { ExchangeProvider } from "#protocol/ExchangeProvider.js";
22
- import { WriteResponse } from "#types";
23
21
 
24
22
  export interface ClientInteractableContext {
25
23
  exchanges: ExchangeProvider;
@@ -30,7 +28,7 @@ export interface ClientInteractableContext {
30
28
  /**
31
29
  * This is a WIP and currently largely a stub.
32
30
  */
33
- export class ClientInteraction<SessionT extends AccessControl.Session = AccessControl.Session>
31
+ export class ClientInteraction<SessionT extends InteractionSession = InteractionSession>
34
32
  implements Interactable<SessionT>
35
33
  {
36
34
  readonly #exchanges: ExchangeProvider;
@@ -66,28 +64,38 @@ export class ClientInteraction<SessionT extends AccessControl.Session = AccessCo
66
64
  throw new NotImplementedError();
67
65
  }
68
66
 
69
- write<T extends Write>(request: T, _session?: SessionT) {
70
- return new CancelablePromise<void | WriteResponse>((resolve, reject) => {
71
- InteractionClientMessenger.create(this.#exchanges).then(messenger => {
72
- const send = messenger.sendWriteCommand(request);
73
-
74
- let sendResolve;
75
- if (request.suppressResponse) {
76
- sendResolve = send.then(() => {
77
- resolve();
78
- });
79
- } else {
80
- sendResolve = send.then(resolve);
81
- }
82
-
83
- sendResolve.catch(reject);
84
- }, reject);
85
- }) as WriteResult<T>;
67
+ async write<T extends Write>(request: T, _session?: SessionT): WriteResult<T> {
68
+ const messenger = await InteractionClientMessenger.create(this.#exchanges);
69
+ const response = await messenger.sendWriteCommand(request);
70
+ if (request.suppressResponse) {
71
+ return undefined as Awaited<WriteResult<T>>;
72
+ }
73
+ if (!response || !response.writeResponses?.length) {
74
+ return new Array<WriteResult.AttributeStatus>() as Awaited<WriteResult<T>>;
75
+ } else {
76
+ return response.writeResponses.map(
77
+ ({
78
+ path: { nodeId, endpointId, clusterId, attributeId, listIndex },
79
+ status: { status, clusterStatus },
80
+ }) => ({
81
+ kind: "attr-status",
82
+ path: {
83
+ nodeId,
84
+ endpointId: endpointId!,
85
+ clusterId: clusterId!,
86
+ attributeId: attributeId!,
87
+ listIndex,
88
+ },
89
+ status: status!,
90
+ clusterStatus,
91
+ }),
92
+ ) as Awaited<WriteResult<T>>;
93
+ }
86
94
  }
87
95
 
88
96
  invoke<T extends Invoke>(request: Invoke, _session?: SessionT): InvokeResult<T> {
89
97
  if (request.suppressResponse) {
90
- return new CancelablePromise<void>((resolve, reject) => {
98
+ return new Promise<void>((resolve, reject) => {
91
99
  InteractionClientMessenger.create(this.#exchanges)
92
100
  .then(messenger =>
93
101
  messenger
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { InteractionSession } from "#action/Interactable.js";
7
8
  import { OccurrenceManager } from "#events/OccurrenceManager.js";
8
9
  import { MaybePromise, Observable } from "#general";
9
10
  import { DataModelPath, MatterModel } from "#model";
@@ -106,12 +107,17 @@ export interface ClusterProtocol {
106
107
  stateChanged: Observable<[changes: AttributeId[], version: number], MaybePromise>;
107
108
 
108
109
  /**
109
- * Access a record of attribute values, keyed by attribute ID.
110
+ * Read-only state of the cluster
111
+ */
112
+ readState(session: InteractionSession): Val.ProtocolStruct;
113
+
114
+ /**
115
+ * Writeable record of attribute values, keyed by attribute ID.
110
116
  *
111
117
  * Note that current protocol implementations do not filter data within this responsibility based on the
112
118
  * session. So doing is the responsibility of the node implementation.
113
119
  */
114
- open(session: AccessControl.Session): Val.ProtocolStruct;
120
+ openForWrite(session: InteractionSession): Promise<Val.ProtocolStruct>;
115
121
  }
116
122
 
117
123
  /**
@@ -4,10 +4,133 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { WriteRequest } from "#types";
7
+ import { FALLBACK_INTERACTIONMODEL_REVISION } from "#session/Session.js";
8
+ import { AttributeData, ClusterType, WriteRequest } from "#types";
9
+ import { MalformedRequestError } from "./MalformedRequestError.js";
10
+ import { Specifier } from "./Specifier.js";
8
11
 
9
- export interface Write extends WriteRequest {
10
- timeout?: number;
12
+ export interface Write extends WriteRequest {}
13
+
14
+ /**
15
+ * Formulate a write-request using Matter numeric IDs.
16
+ */
17
+ export function Write(options: Write.Options): Write;
18
+
19
+ /**
20
+ * Formulate a write-request with extended options and name-based IDs.
21
+ */
22
+ export function Write(options: Write.Options, ...data: Write.Attribute[]): Write;
23
+
24
+ /**
25
+ * Formulate a write-request with name-based IDs.
26
+ */
27
+ export function Write(...data: Write.Attribute[]): Write;
28
+
29
+ export function Write(optionsOrData: Write.Options | Write.Attribute, ...data: Write.Attribute[]): Write {
30
+ let options;
31
+ if ("kind" in optionsOrData) {
32
+ data = [optionsOrData, ...data];
33
+ options = {};
34
+ } else {
35
+ options = optionsOrData;
36
+ }
37
+ const { writes: writeRequests = [] } = options;
38
+
39
+ const result: Write = {
40
+ timedRequest: !!options.timed || !!options.timeout,
41
+ writeRequests,
42
+ interactionModelRevision: options.interactionModelRevision ?? FALLBACK_INTERACTIONMODEL_REVISION,
43
+ };
44
+
45
+ for (const entry of data) {
46
+ reifyData(entry);
47
+ }
48
+
49
+ if (!writeRequests.length) {
50
+ throw new MalformedRequestError(`Write action contains no attributes to write`);
51
+ }
52
+
53
+ return result;
54
+
55
+ function reifyData(data: Write.Attribute) {
56
+ const cluster = Specifier.clusterOf(data);
57
+
58
+ if (cluster === undefined) {
59
+ throw new MalformedRequestError(`Write action must specify a cluster`);
60
+ }
61
+
62
+ let { attributes } = data;
63
+ if (attributes === undefined) {
64
+ throw new MalformedRequestError(`Write action must specify an attribute`);
65
+ }
66
+ if (!Array.isArray(attributes)) {
67
+ attributes = [attributes];
68
+ }
69
+
70
+ const { endpoint, value, version: dataVersion } = data;
71
+
72
+ // Configure base AttributePath
73
+ const prototype: Omit<AttributeData, "data"> = {
74
+ path: {
75
+ endpointId: endpoint !== undefined ? Specifier.endpointIdOf(data) : undefined,
76
+ clusterId: cluster.id,
77
+ attributeId: undefined,
78
+ },
79
+ dataVersion,
80
+ };
81
+
82
+ for (const specifier of attributes) {
83
+ const attribute = Specifier.attributeFor(cluster, specifier);
84
+ writeRequests.push({
85
+ ...prototype,
86
+ path: {
87
+ ...prototype.path,
88
+ attributeId: attribute.id,
89
+ },
90
+ data: attribute.schema.encodeTlv(value, { forWriteInteraction: true }),
91
+ });
92
+ }
93
+ }
11
94
  }
12
95
 
13
- // TODO - write DSL
96
+ export namespace Write {
97
+ export interface Options {
98
+ writes?: AttributeData[];
99
+ timed?: boolean;
100
+ timeout?: number;
101
+ interactionModelRevision?: number;
102
+ }
103
+
104
+ /**
105
+ * Selects attributes to Write. Limits fields to legal permutations per the Matter specification.
106
+ */
107
+ export type Attribute<C extends Specifier.Cluster = Specifier.Cluster> = (
108
+ | Attribute.Concrete<C>
109
+ | Attribute.WildcardEndpoint<C>
110
+ ) & {
111
+ kind: "attribute";
112
+ value: any;
113
+ version?: number;
114
+ };
115
+
116
+ export function Attribute<const C extends ClusterType>(data: Omit<Attribute<C>, "kind">): Attribute<C> {
117
+ return {
118
+ kind: "attribute",
119
+ ...data,
120
+ };
121
+ }
122
+
123
+ export namespace Attribute {
124
+ export interface Concrete<C extends Specifier.Cluster> {
125
+ endpoint: Specifier.Endpoint;
126
+ cluster: C;
127
+ attributes: Specifier.Attribute<Specifier.ClusterFor<C>> | Specifier.Attribute<Specifier.ClusterFor<C>>[];
128
+ }
129
+
130
+ export interface WildcardEndpoint<C extends Specifier.Cluster> {
131
+ endpoint?: undefined;
132
+ cluster: C;
133
+ attributes: Specifier.Attribute<Specifier.ClusterFor<C>> | Specifier.Attribute<Specifier.ClusterFor<C>>[];
134
+ }
135
+ }
136
+ }
@@ -6,10 +6,9 @@
6
6
 
7
7
  import type { Invoke } from "#action/request/Invoke.js";
8
8
  import type { CommandData } from "#types";
9
- import { CancelablePromise } from "@matter/general";
10
9
 
11
10
  export type InvokeResult<T extends Invoke> = T extends { suppressResponse: true }
12
- ? CancelablePromise<void>
11
+ ? Promise<void>
13
12
  : AsyncIterable<InvokeResult.Chunk>;
14
13
 
15
14
  export namespace InvokeResult {
@@ -33,13 +33,7 @@ export interface ReadResult<Chunk = ReadResult.Chunk> extends AsyncIterable<Read
33
33
  export namespace ReadResult {
34
34
  export type Chunk = Iterable<Report>;
35
35
 
36
- export type Report =
37
- | AttributeValue
38
- | GlobalAttributeStatus
39
- | ClusterAttributeStatus
40
- | EventValue
41
- | GlobalEventStatus
42
- | ClusterEventStatus;
36
+ export type Report = AttributeValue | AttributeStatus | EventValue | EventStatus;
43
37
 
44
38
  export interface ConcreteAttributePath extends AttributePath {
45
39
  nodeId?: NodeId;
@@ -56,17 +50,11 @@ export namespace ReadResult {
56
50
  tlv: TlvSchema<unknown>;
57
51
  }
58
52
 
59
- export interface GlobalAttributeStatus {
53
+ export interface AttributeStatus {
60
54
  kind: "attr-status";
61
55
  path: ConcreteAttributePath;
62
56
  status: StatusCode;
63
- }
64
-
65
- export interface ClusterAttributeStatus {
66
- kind: "attr-cluster-status";
67
- path: ConcreteAttributePath;
68
- status: number;
69
- clusterStatus: number;
57
+ clusterStatus?: number;
70
58
  }
71
59
 
72
60
  export interface ConcreteEventPath extends EventPath {
@@ -86,15 +74,10 @@ export namespace ReadResult {
86
74
  tlv: TlvSchema<unknown>;
87
75
  }
88
76
 
89
- export interface GlobalEventStatus {
77
+ export interface EventStatus {
90
78
  kind: "event-status";
91
79
  path: ConcreteEventPath;
92
80
  status: Status;
93
- }
94
-
95
- export interface ClusterEventStatus {
96
- kind: "event-cluster-status";
97
- path: ConcreteEventPath;
98
- clusterStatus: number;
81
+ clusterStatus?: number;
99
82
  }
100
83
  }
@@ -4,10 +4,26 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import type { Write } from "#action/request/Write.js";
8
- import type { CancelablePromise } from "#general";
9
- import type { WriteResponse } from "#types";
7
+ import { Write } from "#action/request/Write.js";
8
+ import type { AttributeId, AttributePath, ClusterId, EndpointNumber, NodeId, StatusCode } from "#types";
10
9
 
11
- export type WriteResult<T extends Write> = CancelablePromise<
12
- T extends { suppressResponse: true } ? void : WriteResponse
10
+ export type WriteResult<T extends Write> = Promise<
11
+ T extends { suppressResponse: true } ? void : WriteResult.AttributeStatus[]
13
12
  >;
13
+
14
+ export namespace WriteResult {
15
+ export interface ConcreteAttributePath extends AttributePath {
16
+ nodeId?: NodeId;
17
+ endpointId: EndpointNumber;
18
+ clusterId: ClusterId;
19
+ attributeId: AttributeId;
20
+ listIndex?: number | null;
21
+ }
22
+
23
+ export interface AttributeStatus {
24
+ kind: "attr-status";
25
+ path: ConcreteAttributePath;
26
+ status: StatusCode;
27
+ clusterStatus?: number;
28
+ }
29
+ }
@@ -286,7 +286,7 @@ function dataEnforcerFor(schema: Schema): AccessControl {
286
286
  );
287
287
  }
288
288
 
289
- if (location?.owningFabric && location.owningFabric !== session.fabric) {
289
+ if (location?.owningFabric !== undefined && location.owningFabric !== session.fabric) {
290
290
  throw new ReadError(
291
291
  location,
292
292
  "Permission denied: Owning/accessing fabric mismatch",
@@ -307,7 +307,7 @@ function dataEnforcerFor(schema: Schema): AccessControl {
307
307
  return false;
308
308
  }
309
309
 
310
- if (location?.owningFabric && location.owningFabric !== session.fabric) {
310
+ if (location?.owningFabric !== undefined && location.owningFabric !== session.fabric) {
311
311
  return false;
312
312
  }
313
313
 
@@ -323,7 +323,7 @@ function dataEnforcerFor(schema: Schema): AccessControl {
323
323
  throw new WriteError(location, "Permission denied: No accessing fabric", StatusCode.UnsupportedAccess);
324
324
  }
325
325
 
326
- if (location?.owningFabric && location.owningFabric !== session.fabric) {
326
+ if (location?.owningFabric !== undefined && location.owningFabric !== session.fabric) {
327
327
  throw new WriteError(location, "Permission denied: Owning/accessing fabric mismatch");
328
328
  }
329
329
 
@@ -339,7 +339,7 @@ function dataEnforcerFor(schema: Schema): AccessControl {
339
339
  return false;
340
340
  }
341
341
 
342
- if (location?.owningFabric && location.owningFabric !== session.fabric) {
342
+ if (location?.owningFabric !== undefined && location.owningFabric !== session.fabric) {
343
343
  return false;
344
344
  }
345
345
 
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { InteractionSession } from "#action/index.js";
7
8
  import { AttributeTypeProtocol, ClusterProtocol, EndpointProtocol, NodeProtocol } from "#action/protocols.js";
8
9
  import { Read } from "#action/request/Read.js";
9
10
  import { ReadResult } from "#action/response/ReadResult.js";
@@ -24,7 +25,7 @@ import {
24
25
  } from "#types";
25
26
  import { StatusCode } from "@matter/types";
26
27
 
27
- const logger = Logger.get("AttributeResponse");
28
+ const logger = Logger.get("AttributeReadResponse");
28
29
 
29
30
  export const GlobalAttrIds = new Set(Object.values(GlobalAttributes({})).map(attr => attr.id));
30
31
 
@@ -33,14 +34,14 @@ export const GlobalAttrIds = new Set(Object.values(GlobalAttributes({})).map(att
33
34
  *
34
35
  * TODO - profile; ensure nested functions are properly JITed and/or inlined
35
36
  */
36
- export class AttributeResponse<
37
- SessionT extends AccessControl.Session = AccessControl.Session,
37
+ export class AttributeReadResponse<
38
+ SessionT extends InteractionSession = InteractionSession,
38
39
  > extends DataResponse<SessionT> {
39
40
  #versions?: Record<EndpointNumber, Record<ClusterId, number>>;
40
41
 
41
42
  // Each input AttributePathIB that does not have an error installs a producer. Producers run after validation and
42
43
  // generate actual attribute data
43
- #dataProducers?: Array<(this: AttributeResponse) => Iterable<ReadResult.Chunk>>;
44
+ #dataProducers?: Array<(this: AttributeReadResponse) => Iterable<ReadResult.Chunk>>;
44
45
 
45
46
  // The initial "chunk" may be a list of errors. As producers execute it is a set of records associated with the
46
47
  // most recently touched endpoint. When the endpoint changes the previous chunk emits
@@ -124,7 +125,7 @@ export class AttributeResponse<
124
125
  get counts() {
125
126
  return {
126
127
  status: this.#statusCount,
127
- value: this.#valueCount,
128
+ success: this.#valueCount,
128
129
  existent: this.#valueCount + this.#filteredCount,
129
130
  };
130
131
  }
@@ -149,7 +150,7 @@ export class AttributeResponse<
149
150
  const wpf = wildcardPathFlags ? WildcardPathFlagsCodec.encode(wildcardPathFlags) : 0;
150
151
 
151
152
  if (endpointId === undefined) {
152
- this.#addProducer(function* (this: AttributeResponse) {
153
+ this.#addProducer(function* (this: AttributeReadResponse) {
153
154
  this.#wildcardPathFlags = wpf;
154
155
  for (const endpoint of this.node) {
155
156
  yield* this.readEndpointForWildcard(endpoint, path);
@@ -160,7 +161,7 @@ export class AttributeResponse<
160
161
 
161
162
  const endpoint = this.node[endpointId];
162
163
  if (endpoint) {
163
- this.#addProducer(function (this: AttributeResponse) {
164
+ this.#addProducer(function (this: AttributeReadResponse) {
164
165
  this.#wildcardPathFlags = wpf;
165
166
  return this.readEndpointForWildcard(endpoint, path);
166
167
  });
@@ -263,12 +264,12 @@ export class AttributeResponse<
263
264
  }
264
265
  this.#currentEndpoint = endpoint;
265
266
  this.#currentCluster = cluster;
266
- this.#currentState = cluster.open(this.session);
267
+ this.#currentState = cluster.readState(this.session);
267
268
  } else if (this.#currentCluster !== cluster) {
268
269
  this.#currentCluster = cluster;
269
- this.#currentState = cluster.open(this.session);
270
+ this.#currentState = cluster.readState(this.session);
270
271
  } else if (this.#currentState === undefined) {
271
- this.#currentState = cluster.open(this.session);
272
+ this.#currentState = cluster.readState(this.session);
272
273
  }
273
274
 
274
275
  const value = this.#currentState[attributeId];
@@ -386,7 +387,7 @@ export class AttributeResponse<
386
387
  }
387
388
 
388
389
  if (this.#currentState === undefined) {
389
- this.#currentState = this.#guardedCurrentCluster.open(this.session);
390
+ this.#currentState = this.#guardedCurrentCluster.readState(this.session);
390
391
  }
391
392
  const value = this.#currentState[attribute.id];
392
393
  if (value === undefined) {
@@ -411,7 +412,7 @@ export class AttributeResponse<
411
412
  /**
412
413
  * Add a function that produces data. These functions are run after validation of input paths.
413
414
  */
414
- #addProducer(producer: (this: AttributeResponse) => Iterable<ReadResult.Chunk>) {
415
+ #addProducer(producer: (this: AttributeReadResponse) => Iterable<ReadResult.Chunk>) {
415
416
  if (this.#dataProducers) {
416
417
  this.#dataProducers.push(producer);
417
418
  } else {
@@ -435,7 +436,7 @@ export class AttributeResponse<
435
436
  () => `Error reading attribute ${this.node.inspectPath(path)}: Status=${StatusCode[status]}(${status})`,
436
437
  );
437
438
 
438
- const report: ReadResult.GlobalAttributeStatus = {
439
+ const report: ReadResult.AttributeStatus = {
439
440
  kind: "attr-status",
440
441
  path,
441
442
  status,
@@ -3,12 +3,12 @@
3
3
  * Copyright 2022-2025 Project CHIP Authors
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { InteractionSession } from "#action/index.js";
6
7
  import { AttributeTypeProtocol, ClusterProtocol, EndpointProtocol, NodeProtocol } from "#action/protocols.js";
7
8
  import { ReadResult } from "#action/response/ReadResult.js";
8
9
  import { InternalError } from "#general";
9
10
  import { AttributeId, AttributePath, ClusterId, EndpointNumber } from "#types";
10
- import { AccessControl } from "./AccessControl.js";
11
- import { AttributeResponse } from "./AttributeResponse.js";
11
+ import { AttributeReadResponse } from "./AttributeReadResponse.js";
12
12
 
13
13
  type ClusterFilter = {
14
14
  [clusterId: ClusterId]: Set<AttributeId>;
@@ -18,12 +18,12 @@ export type AttributeResponseFilter = {
18
18
  };
19
19
 
20
20
  /**
21
- * AttributeSubscriptionResponse is a specialized version of AttributeResponse that processes a read/subscribe request
21
+ * AttributeSubscriptionResponse is a specialized version of AttributeReadResponse that processes a read/subscribe request
22
22
  * with a filter applied to the attributes. Only the attributes that match the filter will be processed.
23
23
  */
24
24
  export class AttributeSubscriptionResponse<
25
- SessionT extends AccessControl.Session = AccessControl.Session,
26
- > extends AttributeResponse<SessionT> {
25
+ SessionT extends InteractionSession = InteractionSession,
26
+ > extends AttributeReadResponse<SessionT> {
27
27
  #filter: AttributeResponseFilter;
28
28
  #currentEndpointFilter?: ClusterFilter;
29
29
  #currentClusterFilter?: Set<number>;