@matter/protocol 0.16.0-alpha.0-20251016-b56cf5683 → 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.
- package/dist/cjs/action/client/ClientInteraction.d.ts +10 -5
- package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/cjs/action/client/ClientInteraction.js +129 -18
- package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
- package/dist/cjs/action/request/Invoke.d.ts +36 -8
- package/dist/cjs/action/request/Invoke.d.ts.map +1 -1
- package/dist/cjs/action/request/Invoke.js +80 -15
- package/dist/cjs/action/request/Invoke.js.map +1 -1
- package/dist/cjs/action/request/Read.d.ts +1 -1
- package/dist/cjs/action/request/Read.d.ts.map +1 -1
- package/dist/cjs/action/request/Read.js +10 -2
- package/dist/cjs/action/request/Read.js.map +1 -1
- package/dist/cjs/action/request/Specifier.d.ts +16 -1
- package/dist/cjs/action/request/Specifier.d.ts.map +1 -1
- package/dist/cjs/action/request/Specifier.js +56 -1
- package/dist/cjs/action/request/Specifier.js.map +1 -1
- package/dist/cjs/action/request/Write.d.ts +5 -3
- package/dist/cjs/action/request/Write.d.ts.map +1 -1
- package/dist/cjs/action/request/Write.js +52 -12
- package/dist/cjs/action/request/Write.js.map +1 -1
- package/dist/cjs/action/response/InvokeResult.d.ts +6 -0
- package/dist/cjs/action/response/InvokeResult.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeContext.d.ts +2 -1
- package/dist/cjs/common/FailsafeContext.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +10 -5
- package/dist/cjs/common/FailsafeContext.js.map +1 -1
- package/dist/cjs/common/FailsafeTimer.d.ts +2 -0
- package/dist/cjs/common/FailsafeTimer.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeTimer.js +9 -0
- package/dist/cjs/common/FailsafeTimer.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +91 -74
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts +3 -2
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +10 -3
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +20 -17
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageChannel.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageChannel.js +1 -1
- package/dist/cjs/protocol/MessageChannel.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +1 -0
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +14 -4
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/protocol/ProtocolHandler.d.ts +7 -2
- package/dist/cjs/protocol/ProtocolHandler.d.ts.map +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.d.ts +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.d.ts.map +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js +5 -4
- package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/cjs/session/GroupSession.d.ts +8 -1
- package/dist/cjs/session/GroupSession.d.ts.map +1 -1
- package/dist/cjs/session/GroupSession.js +10 -0
- package/dist/cjs/session/GroupSession.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +4 -1
- package/dist/cjs/session/NodeSession.d.ts.map +1 -1
- package/dist/cjs/session/NodeSession.js +17 -0
- package/dist/cjs/session/NodeSession.js.map +2 -2
- package/dist/cjs/session/SecureSession.d.ts +2 -0
- package/dist/cjs/session/SecureSession.d.ts.map +1 -1
- package/dist/cjs/session/SecureSession.js.map +1 -1
- package/dist/cjs/session/Session.d.ts +1 -0
- package/dist/cjs/session/Session.d.ts.map +1 -1
- package/dist/cjs/session/Session.js +4 -0
- package/dist/cjs/session/Session.js.map +1 -1
- package/dist/cjs/session/case/CaseClient.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseClient.js +3 -15
- package/dist/cjs/session/case/CaseClient.js.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.js.map +1 -1
- package/dist/cjs/session/case/CaseServer.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseServer.js +10 -18
- package/dist/cjs/session/case/CaseServer.js.map +1 -1
- package/dist/cjs/session/index.d.ts +1 -0
- package/dist/cjs/session/index.d.ts.map +1 -1
- package/dist/cjs/session/index.js +1 -0
- package/dist/cjs/session/index.js.map +1 -1
- package/dist/cjs/session/pase/PaseClient.js +1 -1
- package/dist/cjs/session/pase/PaseClient.js.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.js.map +1 -1
- package/dist/cjs/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseServer.js +2 -2
- package/dist/cjs/session/pase/PaseServer.js.map +1 -1
- package/dist/esm/action/client/ClientInteraction.d.ts +10 -5
- package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/esm/action/client/ClientInteraction.js +140 -20
- package/dist/esm/action/client/ClientInteraction.js.map +1 -1
- package/dist/esm/action/request/Invoke.d.ts +36 -8
- package/dist/esm/action/request/Invoke.d.ts.map +1 -1
- package/dist/esm/action/request/Invoke.js +81 -16
- package/dist/esm/action/request/Invoke.js.map +1 -1
- package/dist/esm/action/request/Read.d.ts +1 -1
- package/dist/esm/action/request/Read.d.ts.map +1 -1
- package/dist/esm/action/request/Read.js +12 -4
- package/dist/esm/action/request/Read.js.map +1 -1
- package/dist/esm/action/request/Specifier.d.ts +16 -1
- package/dist/esm/action/request/Specifier.d.ts.map +1 -1
- package/dist/esm/action/request/Specifier.js +56 -1
- package/dist/esm/action/request/Specifier.js.map +1 -1
- package/dist/esm/action/request/Write.d.ts +5 -3
- package/dist/esm/action/request/Write.d.ts.map +1 -1
- package/dist/esm/action/request/Write.js +53 -13
- package/dist/esm/action/request/Write.js.map +1 -1
- package/dist/esm/action/response/InvokeResult.d.ts +6 -0
- package/dist/esm/action/response/InvokeResult.d.ts.map +1 -1
- package/dist/esm/common/FailsafeContext.d.ts +2 -1
- package/dist/esm/common/FailsafeContext.d.ts.map +1 -1
- package/dist/esm/common/FailsafeContext.js +10 -5
- package/dist/esm/common/FailsafeContext.js.map +1 -1
- package/dist/esm/common/FailsafeTimer.d.ts +2 -0
- package/dist/esm/common/FailsafeTimer.d.ts.map +1 -1
- package/dist/esm/common/FailsafeTimer.js +9 -0
- package/dist/esm/common/FailsafeTimer.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +92 -74
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts +3 -2
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +10 -3
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +20 -17
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageChannel.d.ts.map +1 -1
- package/dist/esm/protocol/MessageChannel.js +2 -2
- package/dist/esm/protocol/MessageChannel.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +1 -0
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +14 -4
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/protocol/ProtocolHandler.d.ts +7 -2
- package/dist/esm/protocol/ProtocolHandler.d.ts.map +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.d.ts +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.d.ts.map +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.js +5 -4
- package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/esm/session/GroupSession.d.ts +8 -1
- package/dist/esm/session/GroupSession.d.ts.map +1 -1
- package/dist/esm/session/GroupSession.js +11 -1
- package/dist/esm/session/GroupSession.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +4 -1
- package/dist/esm/session/NodeSession.d.ts.map +1 -1
- package/dist/esm/session/NodeSession.js +17 -0
- package/dist/esm/session/NodeSession.js.map +2 -2
- package/dist/esm/session/SecureSession.d.ts +2 -0
- package/dist/esm/session/SecureSession.d.ts.map +1 -1
- package/dist/esm/session/SecureSession.js.map +1 -1
- package/dist/esm/session/Session.d.ts +1 -0
- package/dist/esm/session/Session.d.ts.map +1 -1
- package/dist/esm/session/Session.js +4 -0
- package/dist/esm/session/Session.js.map +1 -1
- package/dist/esm/session/case/CaseClient.d.ts.map +1 -1
- package/dist/esm/session/case/CaseClient.js +5 -17
- package/dist/esm/session/case/CaseClient.js.map +1 -1
- package/dist/esm/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/case/CaseMessenger.js.map +1 -1
- package/dist/esm/session/case/CaseServer.d.ts.map +1 -1
- package/dist/esm/session/case/CaseServer.js +12 -20
- package/dist/esm/session/case/CaseServer.js.map +1 -1
- package/dist/esm/session/index.d.ts +1 -0
- package/dist/esm/session/index.d.ts.map +1 -1
- package/dist/esm/session/index.js +1 -0
- package/dist/esm/session/index.js.map +1 -1
- package/dist/esm/session/pase/PaseClient.js +1 -1
- package/dist/esm/session/pase/PaseClient.js.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.js.map +1 -1
- package/dist/esm/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseServer.js +3 -2
- package/dist/esm/session/pase/PaseServer.js.map +1 -1
- package/package.json +6 -6
- package/src/action/client/ClientInteraction.ts +181 -27
- package/src/action/request/Invoke.ts +149 -27
- package/src/action/request/Read.ts +27 -7
- package/src/action/request/Specifier.ts +80 -1
- package/src/action/request/Write.ts +71 -19
- package/src/action/response/InvokeResult.ts +8 -0
- package/src/common/FailsafeContext.ts +15 -6
- package/src/common/FailsafeTimer.ts +11 -0
- package/src/interaction/InteractionClient.ts +135 -96
- package/src/interaction/InteractionMessenger.ts +15 -3
- package/src/protocol/ExchangeManager.ts +27 -29
- package/src/protocol/MessageChannel.ts +2 -2
- package/src/protocol/MessageExchange.ts +18 -4
- package/src/protocol/ProtocolHandler.ts +7 -2
- package/src/securechannel/SecureChannelProtocol.ts +8 -5
- package/src/session/GroupSession.ts +12 -1
- package/src/session/NodeSession.ts +26 -0
- package/src/session/SecureSession.ts +2 -0
- package/src/session/Session.ts +5 -0
- package/src/session/case/CaseClient.ts +3 -23
- package/src/session/case/CaseMessenger.ts +2 -0
- package/src/session/case/CaseServer.ts +15 -20
- package/src/session/index.ts +1 -0
- package/src/session/pase/PaseClient.ts +1 -1
- package/src/session/pase/PaseMessenger.ts +2 -0
- package/src/session/pase/PaseServer.ts +3 -2
|
@@ -41,7 +41,7 @@ export namespace Specifier {
|
|
|
41
41
|
export type Command<C extends ClusterType = ClusterType> = ClusterType.Command | (string & keyof C["commands"]);
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* An event specifier may be the name of a
|
|
44
|
+
* An event specifier may be the name of a cluster event or an event object.
|
|
45
45
|
*/
|
|
46
46
|
export type Event<C extends ClusterType = ClusterType> = ClusterType.Event | (string & keyof C["events"]);
|
|
47
47
|
|
|
@@ -97,6 +97,26 @@ export namespace Specifier {
|
|
|
97
97
|
? CMD
|
|
98
98
|
: never;
|
|
99
99
|
|
|
100
|
+
export function commandFor<const C extends ClusterType, const CMD extends Specifier.Command<C>>(
|
|
101
|
+
cluster: C | undefined,
|
|
102
|
+
specifier: CMD,
|
|
103
|
+
): CommandFor<C, CMD> {
|
|
104
|
+
if (typeof specifier !== "string") {
|
|
105
|
+
return specifier as CommandFor<C, CMD>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (cluster === undefined) {
|
|
109
|
+
throw new MalformedRequestError(`Cannot designate command "${specifier}" without a cluster`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const command = cluster.commands?.[specifier];
|
|
113
|
+
if (command === undefined) {
|
|
114
|
+
throw new MalformedRequestError(`Cluster ${cluster.name} does not define command ${specifier}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return command as CommandFor<C, CMD>;
|
|
118
|
+
}
|
|
119
|
+
|
|
100
120
|
/**
|
|
101
121
|
* Extract an event object from a cluster and event specifier.
|
|
102
122
|
*/
|
|
@@ -144,3 +164,62 @@ export namespace Specifier {
|
|
|
144
164
|
return request.endpoint?.number;
|
|
145
165
|
}
|
|
146
166
|
}
|
|
167
|
+
|
|
168
|
+
export function toWildcardOrHexPath(name: string, value: number | bigint | undefined) {
|
|
169
|
+
if (value === undefined) {
|
|
170
|
+
return "*";
|
|
171
|
+
}
|
|
172
|
+
return `${name ? `${name}:` : ""}0x${value.toString(16)}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Resolve a path into a human readable textual form for logging
|
|
177
|
+
* TODO: Add a Diagnostic display formatter for this
|
|
178
|
+
*/
|
|
179
|
+
export function resolvePathForSpecifier<const C extends ClusterType>(location: {
|
|
180
|
+
endpoint?: Specifier.Endpoint;
|
|
181
|
+
cluster?: Specifier.Cluster;
|
|
182
|
+
attribute?: Specifier.Attribute<Specifier.ClusterFor<C>>;
|
|
183
|
+
event?: Specifier.Event<Specifier.ClusterFor<C>>;
|
|
184
|
+
command?: Specifier.Command<Specifier.ClusterFor<C>>;
|
|
185
|
+
isUrgent?: boolean;
|
|
186
|
+
listIndex?: number | null;
|
|
187
|
+
}) {
|
|
188
|
+
const endpointId = Specifier.endpointIdOf(location);
|
|
189
|
+
const cluster = location.cluster ? Specifier.clusterFor(location.cluster) : undefined;
|
|
190
|
+
const attribute = location.attribute && cluster ? Specifier.attributeFor(cluster, location.attribute) : undefined;
|
|
191
|
+
const event = location.event && cluster ? Specifier.eventFor(cluster, location.event) : undefined;
|
|
192
|
+
const command = location.command && cluster ? Specifier.commandFor(cluster, location.command) : undefined;
|
|
193
|
+
const isUrgentString = "isUrgent" in location && location.isUrgent ? "!" : "";
|
|
194
|
+
const listIndexString = "listIndex" in location && location.listIndex === null ? "[ADD]" : "";
|
|
195
|
+
const postString = `${listIndexString}${isUrgentString}`;
|
|
196
|
+
|
|
197
|
+
const clusterId = cluster?.id;
|
|
198
|
+
const elementId = attribute ? attribute.id : event ? event.id : command ? command.requestId : undefined;
|
|
199
|
+
|
|
200
|
+
if (endpointId === undefined) {
|
|
201
|
+
return `*.${toWildcardOrHexPath("", clusterId)}.${toWildcardOrHexPath("", elementId)}${postString}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const endpointName = toWildcardOrHexPath("", endpointId);
|
|
205
|
+
|
|
206
|
+
if (cluster === undefined || clusterId === undefined) {
|
|
207
|
+
return `${endpointName}.*.${toWildcardOrHexPath("", elementId)}${postString}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const clusterName = toWildcardOrHexPath(cluster.name, clusterId);
|
|
211
|
+
|
|
212
|
+
if (elementId !== undefined) {
|
|
213
|
+
if (event) {
|
|
214
|
+
return `${endpointName}.${clusterName}.${toWildcardOrHexPath(typeof location.event === "string" ? location.event : "?", elementId)}${postString}`;
|
|
215
|
+
} else if (attribute) {
|
|
216
|
+
return `${endpointName}.${clusterName}.${toWildcardOrHexPath(typeof location.attribute === "string" ? location.attribute : "?", elementId)}${postString}`;
|
|
217
|
+
} else if (command) {
|
|
218
|
+
return `${endpointName}.${clusterName}.${toWildcardOrHexPath(typeof location.command === "string" ? location.command : "?", elementId)}${postString}`;
|
|
219
|
+
} else {
|
|
220
|
+
return "unknown";
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
return `${endpointName}.${clusterName}.*${postString}`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -4,14 +4,25 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { AccessControl } from "#clusters/access-control";
|
|
8
|
+
import { Diagnostic, Duration } from "#general";
|
|
9
|
+
import { Specification } from "#model";
|
|
10
|
+
import { ArraySchema, AttributeData, AttributeId, ClusterId, ClusterType, WriteRequest } from "#types";
|
|
9
11
|
import { MalformedRequestError } from "./MalformedRequestError.js";
|
|
10
|
-
import { Specifier } from "./Specifier.js";
|
|
12
|
+
import { resolvePathForSpecifier, Specifier } from "./Specifier.js";
|
|
13
|
+
|
|
14
|
+
const AclClusterId = AccessControl.Complete.id;
|
|
15
|
+
const AclAttributeId = AccessControl.Complete.attributes.acl.id;
|
|
16
|
+
const AclExtensionAttributeId = AccessControl.Complete.attributes.extension.id;
|
|
17
|
+
|
|
18
|
+
function isAclOrExtensionPath(path: { clusterId: ClusterId; attributeId: AttributeId }) {
|
|
19
|
+
const { clusterId, attributeId } = path;
|
|
20
|
+
return clusterId === AclClusterId && (attributeId === AclAttributeId || attributeId === AclExtensionAttributeId);
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
export interface Write extends WriteRequest {
|
|
13
|
-
/** Timeout only relevant for Client Interactions */
|
|
14
|
-
timeout?:
|
|
24
|
+
/** Timeout only relevant for Client Interactions with a required TimedRequest flagging */
|
|
25
|
+
timeout?: Duration;
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
/**
|
|
@@ -41,13 +52,25 @@ export function Write(optionsOrData: Write.Options | Write.Attribute, ...data: W
|
|
|
41
52
|
} else {
|
|
42
53
|
options = optionsOrData;
|
|
43
54
|
}
|
|
44
|
-
const { writes: writeRequests = [] } = options;
|
|
55
|
+
const { writes: writeRequests = [], timed, timeout, chunkLists } = options;
|
|
45
56
|
|
|
46
|
-
const result
|
|
47
|
-
timedRequest: !!
|
|
57
|
+
const result = {
|
|
58
|
+
timedRequest: !!timed || !!timeout,
|
|
59
|
+
timeout,
|
|
48
60
|
writeRequests,
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
moreChunkedMessages: false,
|
|
62
|
+
interactionModelRevision: options.interactionModelRevision ?? Specification.INTERACTION_MODEL_REVISION,
|
|
63
|
+
|
|
64
|
+
[Diagnostic.value]: () =>
|
|
65
|
+
Diagnostic.list(
|
|
66
|
+
data.map(entry => {
|
|
67
|
+
const { version, value } = entry;
|
|
68
|
+
return `${resolvePathForSpecifier(entry)} = ${Diagnostic.json(
|
|
69
|
+
value,
|
|
70
|
+
)}${version !== undefined ? `(version=${version})` : ""}`;
|
|
71
|
+
}),
|
|
72
|
+
),
|
|
73
|
+
} as Write;
|
|
51
74
|
|
|
52
75
|
for (const entry of data) {
|
|
53
76
|
reifyData(entry);
|
|
@@ -87,15 +110,43 @@ export function Write(optionsOrData: Write.Options | Write.Attribute, ...data: W
|
|
|
87
110
|
};
|
|
88
111
|
|
|
89
112
|
for (const specifier of attributes) {
|
|
113
|
+
const clusterId = cluster.id;
|
|
90
114
|
const attribute = Specifier.attributeFor(cluster, specifier);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
115
|
+
const { schema, id: attributeId } = attribute;
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
chunkLists &&
|
|
119
|
+
Array.isArray(value) &&
|
|
120
|
+
schema instanceof ArraySchema &&
|
|
121
|
+
// As implemented for Matter 1.4.2 in https://github.com/project-chip/connectedhomeip/pull/38263
|
|
122
|
+
// Acl writes will no longer be chunked by default, all others still
|
|
123
|
+
// Will be streamlined later ... see https://github.com/project-chip/connectedhomeip/issues/38270
|
|
124
|
+
!isAclOrExtensionPath({ clusterId, attributeId })
|
|
125
|
+
) {
|
|
126
|
+
writeRequests.push(
|
|
127
|
+
...schema
|
|
128
|
+
.encodeAsChunkedArray(value, { forWriteInteraction: true })
|
|
129
|
+
.map(({ element: data, listIndex }) => ({
|
|
130
|
+
path: {
|
|
131
|
+
...prototype.path,
|
|
132
|
+
attributeId: attribute.id,
|
|
133
|
+
listIndex,
|
|
134
|
+
},
|
|
135
|
+
data,
|
|
136
|
+
dataVersion,
|
|
137
|
+
})),
|
|
138
|
+
);
|
|
139
|
+
} else {
|
|
140
|
+
writeRequests.push({
|
|
141
|
+
...prototype,
|
|
142
|
+
path: {
|
|
143
|
+
...prototype.path,
|
|
144
|
+
attributeId: attribute.id,
|
|
145
|
+
},
|
|
146
|
+
data: attribute.schema.encodeTlv(value, { forWriteInteraction: true }),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
result.timedRequest ||= attribute.timed;
|
|
99
150
|
}
|
|
100
151
|
}
|
|
101
152
|
}
|
|
@@ -104,8 +155,9 @@ export namespace Write {
|
|
|
104
155
|
export interface Options {
|
|
105
156
|
writes?: AttributeData[];
|
|
106
157
|
timed?: boolean;
|
|
107
|
-
timeout?:
|
|
158
|
+
timeout?: Duration;
|
|
108
159
|
interactionModelRevision?: number;
|
|
160
|
+
chunkLists?: boolean;
|
|
109
161
|
}
|
|
110
162
|
|
|
111
163
|
/**
|
|
@@ -8,10 +8,14 @@ import type { ClusterId, CommandId, CommandPath, EndpointNumber, StatusCode, Tlv
|
|
|
8
8
|
|
|
9
9
|
export type InvokeResult = AsyncIterable<InvokeResult.Chunk>;
|
|
10
10
|
|
|
11
|
+
export type DecodedInvokeResult = AsyncIterable<InvokeResult.DecodedChunk>;
|
|
12
|
+
|
|
11
13
|
export namespace InvokeResult {
|
|
12
14
|
export type Chunk = Iterable<Data>;
|
|
15
|
+
export type DecodedChunk = Iterable<DecodedData>;
|
|
13
16
|
|
|
14
17
|
export type Data = CommandStatus | CommandResponse;
|
|
18
|
+
export type DecodedData = CommandStatus | DecodedCommandResponse;
|
|
15
19
|
|
|
16
20
|
export interface ConcreteCommandPath extends CommandPath {
|
|
17
21
|
endpointId: EndpointNumber;
|
|
@@ -33,4 +37,8 @@ export namespace InvokeResult {
|
|
|
33
37
|
commandRef?: number;
|
|
34
38
|
data: TlvStream;
|
|
35
39
|
}
|
|
40
|
+
|
|
41
|
+
export interface DecodedCommandResponse extends Omit<CommandResponse, "data"> {
|
|
42
|
+
data: any;
|
|
43
|
+
}
|
|
36
44
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
UnexpectedDataError,
|
|
15
15
|
UninitializedDependencyError,
|
|
16
16
|
} from "#general";
|
|
17
|
+
import { SecureSession } from "#session/SecureSession.js";
|
|
17
18
|
import { CaseAuthenticatedTag, NodeId, ValidationError, VendorId } from "#types";
|
|
18
19
|
import { Fabric, FabricBuilder } from "../fabric/Fabric.js";
|
|
19
20
|
import { FabricManager } from "../fabric/FabricManager.js";
|
|
@@ -47,11 +48,11 @@ export abstract class FailsafeContext {
|
|
|
47
48
|
#commissioned = AsyncObservable<[], void>();
|
|
48
49
|
|
|
49
50
|
constructor(options: FailsafeContext.Options) {
|
|
50
|
-
const { expiryLength,
|
|
51
|
+
const { sessions, fabrics, expiryLength, session, maxCumulativeFailsafe } = options;
|
|
51
52
|
|
|
52
|
-
this.#sessions =
|
|
53
|
-
this.#fabrics =
|
|
54
|
-
this.#associatedFabric =
|
|
53
|
+
this.#sessions = sessions;
|
|
54
|
+
this.#fabrics = fabrics;
|
|
55
|
+
this.#associatedFabric = session.fabric;
|
|
55
56
|
|
|
56
57
|
this.#construction = Construction(this, async () => {
|
|
57
58
|
this.#fabricBuilder = await FabricBuilder.create(this.#fabrics.crypto);
|
|
@@ -62,10 +63,18 @@ export abstract class FailsafeContext {
|
|
|
62
63
|
|
|
63
64
|
// If ExpiryLengthSeconds is non-zero and the fail-safe timer was not currently armed, then the fail-safe
|
|
64
65
|
// timer SHALL be armed for that duration.
|
|
65
|
-
this.#failsafe = new FailsafeTimer(associatedFabric, expiryLength, maxCumulativeFailsafe, () =>
|
|
66
|
+
this.#failsafe = new FailsafeTimer(this.#associatedFabric, expiryLength, maxCumulativeFailsafe, () =>
|
|
66
67
|
this.#failSafeExpired(),
|
|
67
68
|
);
|
|
68
69
|
logger.debug(`Arm failSafe timer for ${Duration.format(expiryLength)}`);
|
|
70
|
+
|
|
71
|
+
// When the PASE session used to arm the Fail-Safe timer is terminated by peer, the Fail-Safe timer SHALL
|
|
72
|
+
// be considered expired and do the relevant cleanup actions.
|
|
73
|
+
session.closedByPeer.on(() => {
|
|
74
|
+
if (!this.#failsafe?.completed) {
|
|
75
|
+
return this.#failSafeExpired();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
69
78
|
});
|
|
70
79
|
}
|
|
71
80
|
|
|
@@ -341,6 +350,6 @@ export namespace FailsafeContext {
|
|
|
341
350
|
fabrics: FabricManager;
|
|
342
351
|
expiryLength: Duration;
|
|
343
352
|
maxCumulativeFailsafe: Duration;
|
|
344
|
-
|
|
353
|
+
session: SecureSession;
|
|
345
354
|
}
|
|
346
355
|
}
|
|
@@ -19,6 +19,7 @@ export class FailsafeTimer {
|
|
|
19
19
|
#expiryCallback: () => Promise<void>;
|
|
20
20
|
#failsafeTimer: Timer;
|
|
21
21
|
#maxCumulativeFailsafeTimer: Timer;
|
|
22
|
+
#completed = false;
|
|
22
23
|
|
|
23
24
|
constructor(
|
|
24
25
|
public associatedFabric: Fabric | undefined,
|
|
@@ -69,14 +70,24 @@ export class FailsafeTimer {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
/** Returns whether the FailSafe context is currently armed. */
|
|
74
|
+
get completed() {
|
|
75
|
+
return this.#completed;
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
/** Expire the FailSafe context. This is called by the timer and can also be called manually if needed. */
|
|
73
79
|
async expire() {
|
|
80
|
+
if (this.#completed) {
|
|
81
|
+
// Completion was already triggered, so do nothing
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
74
84
|
this.complete();
|
|
75
85
|
await this.#expiryCallback();
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
/** Complete the FailSafe context. This is called when the commissioning is completed. */
|
|
79
89
|
complete() {
|
|
90
|
+
this.#completed = true;
|
|
80
91
|
this.#failsafeTimer.stop();
|
|
81
92
|
this.#maxCumulativeFailsafeTimer.stop();
|
|
82
93
|
}
|