@matter/protocol 0.13.0-alpha.0-20250318-c1aa38b08 → 0.13.0-alpha.0-20250323-770919c6a
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/ble/BtpSessionHandler.js +2 -2
- package/dist/cjs/ble/BtpSessionHandler.js.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.d.ts +1 -0
- package/dist/cjs/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.js.map +1 -1
- package/dist/cjs/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateManager.js +21 -19
- package/dist/cjs/certificate/CertificateManager.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.js +3 -0
- package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.js +5 -5
- package/dist/cjs/cluster/server/AttributeServer.js.map +1 -1
- package/dist/cjs/cluster/server/CommandServer.js +2 -2
- package/dist/cjs/cluster/server/CommandServer.js.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +1 -1
- package/dist/cjs/common/FailsafeContext.js.map +1 -1
- package/dist/cjs/endpoint/EndpointStructureLogger.js +1 -1
- package/dist/cjs/endpoint/EndpointStructureLogger.js.map +1 -1
- package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/cjs/events/OccurrenceManager.js +2 -2
- package/dist/cjs/events/OccurrenceManager.js.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts +21 -4
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.js +41 -2
- package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.js +3 -3
- package/dist/cjs/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.d.ts +4 -2
- package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.js +6 -2
- package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
- package/dist/cjs/interaction/EventDataDecoder.d.ts +15 -3
- package/dist/cjs/interaction/EventDataDecoder.d.ts.map +1 -1
- package/dist/cjs/interaction/EventDataDecoder.js +39 -2
- package/dist/cjs/interaction/EventDataDecoder.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts +44 -4
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +71 -18
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +7 -4
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionServer.js +7 -7
- package/dist/cjs/interaction/InteractionServer.js.map +1 -1
- package/dist/cjs/interaction/ServerSubscription.d.ts.map +1 -1
- package/dist/cjs/interaction/ServerSubscription.js +1 -1
- package/dist/cjs/interaction/ServerSubscription.js.map +1 -1
- package/dist/cjs/mdns/MdnsScanner.js +2 -2
- package/dist/cjs/mdns/MdnsScanner.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.d.ts +15 -3
- package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +17 -6
- package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +47 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.js +136 -136
- package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.js +4 -4
- package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts +2 -2
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +6 -1
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ChannelManager.js +11 -4
- package/dist/cjs/protocol/ChannelManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +1 -2
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/ble/BtpSessionHandler.js +2 -2
- package/dist/esm/ble/BtpSessionHandler.js.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.d.ts +1 -0
- package/dist/esm/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.js.map +1 -1
- package/dist/esm/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateManager.js +22 -19
- package/dist/esm/certificate/CertificateManager.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.js +3 -0
- package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.js +15 -6
- package/dist/esm/cluster/server/AttributeServer.js.map +1 -1
- package/dist/esm/cluster/server/CommandServer.js +3 -3
- package/dist/esm/cluster/server/CommandServer.js.map +1 -1
- package/dist/esm/common/FailsafeContext.js +1 -1
- package/dist/esm/common/FailsafeContext.js.map +1 -1
- package/dist/esm/endpoint/EndpointStructureLogger.js +1 -1
- package/dist/esm/endpoint/EndpointStructureLogger.js.map +1 -1
- package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/esm/events/OccurrenceManager.js +3 -2
- package/dist/esm/events/OccurrenceManager.js.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.d.ts +21 -4
- package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.js +41 -2
- package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.js +4 -4
- package/dist/esm/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.d.ts +4 -2
- package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.js +12 -4
- package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
- package/dist/esm/interaction/EventDataDecoder.d.ts +15 -3
- package/dist/esm/interaction/EventDataDecoder.d.ts.map +1 -1
- package/dist/esm/interaction/EventDataDecoder.js +39 -2
- package/dist/esm/interaction/EventDataDecoder.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts +44 -4
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +74 -18
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +8 -4
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionServer.js +17 -8
- package/dist/esm/interaction/InteractionServer.js.map +1 -1
- package/dist/esm/interaction/ServerSubscription.d.ts.map +1 -1
- package/dist/esm/interaction/ServerSubscription.js +2 -1
- package/dist/esm/interaction/ServerSubscription.js.map +1 -1
- package/dist/esm/mdns/MdnsScanner.js +2 -2
- package/dist/esm/mdns/MdnsScanner.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.d.ts +15 -3
- package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +18 -6
- package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts +47 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.js +147 -137
- package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.js +5 -5
- package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts +2 -2
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +7 -2
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/esm/protocol/ChannelManager.js +11 -4
- package/dist/esm/protocol/ChannelManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +2 -2
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/package.json +6 -6
- package/src/ble/BtpSessionHandler.ts +2 -2
- package/src/certificate/CertificateAuthority.ts +1 -0
- package/src/certificate/CertificateManager.ts +22 -19
- package/src/cluster/client/ClusterClient.ts +3 -0
- package/src/cluster/server/AttributeServer.ts +15 -6
- package/src/cluster/server/CommandServer.ts +3 -3
- package/src/common/FailsafeContext.ts +1 -1
- package/src/endpoint/EndpointStructureLogger.ts +1 -1
- package/src/events/OccurrenceManager.ts +3 -2
- package/src/interaction/AttributeDataDecoder.ts +67 -7
- package/src/interaction/AttributeDataEncoder.ts +4 -4
- package/src/interaction/DecodedDataReport.ts +24 -5
- package/src/interaction/EventDataDecoder.ts +57 -5
- package/src/interaction/InteractionClient.ts +112 -18
- package/src/interaction/InteractionMessenger.ts +8 -4
- package/src/interaction/InteractionServer.ts +19 -9
- package/src/interaction/ServerSubscription.ts +2 -1
- package/src/mdns/MdnsScanner.ts +2 -2
- package/src/peer/ControllerCommissioner.ts +32 -7
- package/src/peer/ControllerCommissioningFlow.ts +160 -146
- package/src/peer/ControllerDiscovery.ts +5 -5
- package/src/peer/PeerSet.ts +7 -2
- package/src/protocol/ChannelManager.ts +11 -4
- package/src/protocol/ExchangeManager.ts +2 -2
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
Diagnostic,
|
|
8
9
|
Environment,
|
|
9
10
|
Environmental,
|
|
10
11
|
ImplementationError,
|
|
@@ -31,7 +32,9 @@ import {
|
|
|
31
32
|
Event,
|
|
32
33
|
EventId,
|
|
33
34
|
EventNumber,
|
|
35
|
+
FabricIndex,
|
|
34
36
|
NodeId,
|
|
37
|
+
ObjectSchema,
|
|
35
38
|
RequestType,
|
|
36
39
|
ResponseType,
|
|
37
40
|
StatusCode,
|
|
@@ -46,10 +49,11 @@ import {
|
|
|
46
49
|
resolveCommandName,
|
|
47
50
|
resolveEventName,
|
|
48
51
|
} from "#types";
|
|
52
|
+
import { MessageChannel } from "../protocol/ExchangeManager.js";
|
|
49
53
|
import { ExchangeProvider, ReconnectableExchangeProvider } from "../protocol/ExchangeProvider.js";
|
|
50
|
-
import { DecodedAttributeReportValue } from "./AttributeDataDecoder.js";
|
|
54
|
+
import { DecodedAttributeReportStatus, DecodedAttributeReportValue } from "./AttributeDataDecoder.js";
|
|
51
55
|
import { DecodedDataReport } from "./DecodedDataReport.js";
|
|
52
|
-
import { DecodedEventData, DecodedEventReportValue } from "./EventDataDecoder.js";
|
|
56
|
+
import { DecodedEventData, DecodedEventReportStatus, DecodedEventReportValue } from "./EventDataDecoder.js";
|
|
53
57
|
import { DataReport, InteractionClientMessenger, ReadRequest } from "./InteractionMessenger.js";
|
|
54
58
|
import { RegisteredSubscription, SubscriptionClient } from "./SubscriptionClient.js";
|
|
55
59
|
|
|
@@ -103,6 +107,17 @@ export class InteractionClientProvider {
|
|
|
103
107
|
return this.getInteractionClient(address, discoveryOptions);
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
async getInteractionClientForChannel(channel: MessageChannel): Promise<InteractionClient> {
|
|
111
|
+
const exchangeProvider = await this.#peers.exchangeProviderFor(channel);
|
|
112
|
+
|
|
113
|
+
return new InteractionClient(
|
|
114
|
+
exchangeProvider,
|
|
115
|
+
this.#peers.subscriptionClient,
|
|
116
|
+
undefined,
|
|
117
|
+
this.#peers.interactionQueue,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
106
121
|
async getInteractionClient(address: PeerAddress, discoveryOptions: DiscoveryOptions) {
|
|
107
122
|
let client = this.#clients.get(address);
|
|
108
123
|
if (client !== undefined) {
|
|
@@ -141,11 +156,12 @@ export class InteractionClient {
|
|
|
141
156
|
readonly #ownSubscriptionIds = new Set<number>();
|
|
142
157
|
readonly #subscriptionClient: SubscriptionClient;
|
|
143
158
|
readonly #queue?: PromiseQueue;
|
|
159
|
+
readonly #address?: PeerAddress;
|
|
144
160
|
|
|
145
161
|
constructor(
|
|
146
162
|
exchangeProvider: ExchangeProvider,
|
|
147
163
|
subscriptionClient: SubscriptionClient,
|
|
148
|
-
|
|
164
|
+
address?: PeerAddress,
|
|
149
165
|
queue?: PromiseQueue,
|
|
150
166
|
nodeStore?: PeerDataStore,
|
|
151
167
|
) {
|
|
@@ -153,6 +169,18 @@ export class InteractionClient {
|
|
|
153
169
|
this.#nodeStore = nodeStore;
|
|
154
170
|
this.#subscriptionClient = subscriptionClient;
|
|
155
171
|
this.#queue = queue;
|
|
172
|
+
this.#address = address;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
get address() {
|
|
176
|
+
if (this.#address === undefined) {
|
|
177
|
+
throw new ImplementationError("This InteractionClient is not bound to a specific peer.");
|
|
178
|
+
}
|
|
179
|
+
return this.#address;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
get isReconnectable() {
|
|
183
|
+
return this.#exchangeProvider instanceof ReconnectableExchangeProvider;
|
|
156
184
|
}
|
|
157
185
|
|
|
158
186
|
get channelUpdated() {
|
|
@@ -233,6 +261,22 @@ export class InteractionClient {
|
|
|
233
261
|
return (await this.getMultipleAttributesAndEvents(options)).attributeReports;
|
|
234
262
|
}
|
|
235
263
|
|
|
264
|
+
async getMultipleAttributesAndStatus(
|
|
265
|
+
options: {
|
|
266
|
+
attributes?: { endpointId?: EndpointNumber; clusterId?: ClusterId; attributeId?: AttributeId }[];
|
|
267
|
+
dataVersionFilters?: { endpointId: EndpointNumber; clusterId: ClusterId; dataVersion: number }[];
|
|
268
|
+
enrichCachedAttributeData?: boolean;
|
|
269
|
+
isFabricFiltered?: boolean;
|
|
270
|
+
executeQueued?: boolean;
|
|
271
|
+
} = {},
|
|
272
|
+
): Promise<{
|
|
273
|
+
attributeData: DecodedAttributeReportValue<any>[];
|
|
274
|
+
attributeStatus?: DecodedAttributeReportStatus[];
|
|
275
|
+
}> {
|
|
276
|
+
const { attributeReports, attributeStatus } = await this.getMultipleAttributesAndEvents(options);
|
|
277
|
+
return { attributeData: attributeReports, attributeStatus };
|
|
278
|
+
}
|
|
279
|
+
|
|
236
280
|
async getMultipleEvents(
|
|
237
281
|
options: {
|
|
238
282
|
events?: { endpointId?: EndpointNumber; clusterId?: ClusterId; eventId?: EventId }[];
|
|
@@ -244,6 +288,18 @@ export class InteractionClient {
|
|
|
244
288
|
return (await this.getMultipleAttributesAndEvents(options)).eventReports;
|
|
245
289
|
}
|
|
246
290
|
|
|
291
|
+
async getMultipleEventsAndStatus(
|
|
292
|
+
options: {
|
|
293
|
+
events?: { endpointId?: EndpointNumber; clusterId?: ClusterId; eventId?: EventId }[];
|
|
294
|
+
eventFilters?: TypeFromSchema<typeof TlvEventFilter>[];
|
|
295
|
+
isFabricFiltered?: boolean;
|
|
296
|
+
executeQueued?: boolean;
|
|
297
|
+
} = {},
|
|
298
|
+
): Promise<{ eventData: DecodedEventReportValue<any>[]; eventStatus?: DecodedEventReportStatus[] }> {
|
|
299
|
+
const { eventReports, eventStatus } = await this.getMultipleAttributesAndEvents(options);
|
|
300
|
+
return { eventData: eventReports, eventStatus };
|
|
301
|
+
}
|
|
302
|
+
|
|
247
303
|
async getMultipleAttributesAndEvents(
|
|
248
304
|
options: {
|
|
249
305
|
attributes?: { endpointId?: EndpointNumber; clusterId?: ClusterId; attributeId?: AttributeId }[];
|
|
@@ -405,12 +461,23 @@ export class InteractionClient {
|
|
|
405
461
|
|
|
406
462
|
// Normalize and decode the response
|
|
407
463
|
const normalizedResult = DecodedDataReport(response);
|
|
464
|
+
const { attributeReports, attributeStatus, eventReports, eventStatus } = normalizedResult;
|
|
465
|
+
|
|
466
|
+
const logData = Array<string>();
|
|
467
|
+
if (attributeReports.length > 0) {
|
|
468
|
+
logData.push(`attributes ${attributeReports.map(({ path }) => resolveAttributeName(path)).join(", ")}`);
|
|
469
|
+
}
|
|
470
|
+
if (eventReports.length > 0) {
|
|
471
|
+
logData.push(`events ${eventReports.map(({ path }) => resolveEventName(path)).join(", ")}`);
|
|
472
|
+
}
|
|
473
|
+
if (attributeStatus !== undefined && attributeStatus.length > 0) {
|
|
474
|
+
logData.push(`attributeErrors ${attributeStatus.map(({ path }) => resolveAttributeName(path)).join(", ")}`);
|
|
475
|
+
}
|
|
476
|
+
if (eventStatus !== undefined && eventStatus.length > 0) {
|
|
477
|
+
logData.push(`eventErrors ${eventStatus.map(({ path }) => resolveEventName(path)).join(", ")}`);
|
|
478
|
+
}
|
|
408
479
|
logger.debug(
|
|
409
|
-
`Received read response with
|
|
410
|
-
.map(({ path, value }) => `${resolveAttributeName(path)} = ${Logger.toJSON(value)}`)
|
|
411
|
-
.join(", ")} and events ${normalizedResult.eventReports
|
|
412
|
-
.map(({ path, events }) => `${resolveEventName(path)} = ${Logger.toJSON(events)}`)
|
|
413
|
-
.join(", ")}`,
|
|
480
|
+
logData.length ? `Received read response with ${logData.join(", ")}` : "Received empty read response",
|
|
414
481
|
);
|
|
415
482
|
return normalizedResult;
|
|
416
483
|
}
|
|
@@ -483,7 +550,7 @@ export class InteractionClient {
|
|
|
483
550
|
`Sending write request: ${attributes
|
|
484
551
|
.map(
|
|
485
552
|
({ endpointId, clusterId, attribute: { id }, value, dataVersion }) =>
|
|
486
|
-
`${resolveAttributeName({ endpointId, clusterId, attributeId: id })} = ${
|
|
553
|
+
`${resolveAttributeName({ endpointId, clusterId, attributeId: id })} = ${Diagnostic.json(
|
|
487
554
|
value,
|
|
488
555
|
)} (version=${dataVersion})`,
|
|
489
556
|
)
|
|
@@ -893,11 +960,11 @@ export class InteractionClient {
|
|
|
893
960
|
eventReports?: DecodedEventReportValue<any>[];
|
|
894
961
|
subscriptionId?: number;
|
|
895
962
|
}) => {
|
|
896
|
-
updateReceived?.();
|
|
897
963
|
if (
|
|
898
964
|
(!Array.isArray(dataReport.attributeReports) || !dataReport.attributeReports.length) &&
|
|
899
965
|
(!Array.isArray(dataReport.eventReports) || !dataReport.eventReports.length)
|
|
900
966
|
) {
|
|
967
|
+
updateReceived?.();
|
|
901
968
|
return;
|
|
902
969
|
}
|
|
903
970
|
const { attributeReports, eventReports } = dataReport;
|
|
@@ -907,7 +974,7 @@ export class InteractionClient {
|
|
|
907
974
|
let maxEventNumber = this.#nodeStore?.maxEventNumber ?? eventReports[0].events[0].eventNumber;
|
|
908
975
|
eventReports.forEach(data => {
|
|
909
976
|
logger.debug(
|
|
910
|
-
`Received event update: ${resolveEventName(data.path)}: ${
|
|
977
|
+
`Received event update: ${resolveEventName(data.path)}: ${Diagnostic.json(data.events)}`,
|
|
911
978
|
);
|
|
912
979
|
const { events } = data;
|
|
913
980
|
|
|
@@ -935,7 +1002,7 @@ export class InteractionClient {
|
|
|
935
1002
|
endpointId,
|
|
936
1003
|
clusterId,
|
|
937
1004
|
attributeId,
|
|
938
|
-
})} = ${
|
|
1005
|
+
})} = ${Diagnostic.json(value)} (version=${version})`,
|
|
939
1006
|
);
|
|
940
1007
|
if (value === undefined) throw new MatterFlowError("Received empty subscription result value.");
|
|
941
1008
|
const { value: oldValue } =
|
|
@@ -948,6 +1015,7 @@ export class InteractionClient {
|
|
|
948
1015
|
attributeListener?.(data, changed, oldValue);
|
|
949
1016
|
}
|
|
950
1017
|
}
|
|
1018
|
+
updateReceived?.();
|
|
951
1019
|
};
|
|
952
1020
|
|
|
953
1021
|
const seedReport = DecodedDataReport(report);
|
|
@@ -977,33 +1045,59 @@ export class InteractionClient {
|
|
|
977
1045
|
clusterId: ClusterId;
|
|
978
1046
|
request: RequestType<C>;
|
|
979
1047
|
command: C;
|
|
1048
|
+
|
|
1049
|
+
/** Send as timed request. If no timedRequestTimeoutMs is provided the default of 10s will be used. */
|
|
980
1050
|
asTimedRequest?: boolean;
|
|
1051
|
+
|
|
1052
|
+
/** Use this timeout and send the request as Timed Request. If this is specified the above parameter is implied. */
|
|
981
1053
|
timedRequestTimeoutMs?: number;
|
|
1054
|
+
|
|
1055
|
+
/** Use an extended Message Response Timeout as defined for FailSafe cases which is 30s. */
|
|
982
1056
|
useExtendedFailSafeMessageResponseTimeout?: boolean;
|
|
1057
|
+
|
|
1058
|
+
/** Execute this request queued - mainly used to execute invokes sequentially for thread devices. */
|
|
983
1059
|
executeQueued?: boolean;
|
|
1060
|
+
|
|
1061
|
+
/** Skip request data validation. Use this only when you know that your data is correct and validation would return an error. */
|
|
1062
|
+
skipValidation?: boolean;
|
|
984
1063
|
}): Promise<ResponseType<C>> {
|
|
985
1064
|
const { executeQueued } = options;
|
|
986
1065
|
|
|
987
1066
|
const {
|
|
988
1067
|
endpointId,
|
|
989
1068
|
clusterId,
|
|
990
|
-
request,
|
|
991
1069
|
command: { requestId, requestSchema, responseId, responseSchema, optional, timed },
|
|
992
1070
|
asTimedRequest,
|
|
993
1071
|
timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT_MS,
|
|
994
1072
|
useExtendedFailSafeMessageResponseTimeout = false,
|
|
1073
|
+
skipValidation,
|
|
995
1074
|
} = options;
|
|
996
|
-
|
|
1075
|
+
let { request } = options;
|
|
1076
|
+
const timedRequest =
|
|
1077
|
+
(timed && !skipValidation) || asTimedRequest === true || options.timedRequestTimeoutMs !== undefined;
|
|
1078
|
+
|
|
1079
|
+
if (requestSchema instanceof ObjectSchema) {
|
|
1080
|
+
if (request === undefined) {
|
|
1081
|
+
// If developer did not provide a request object, create an empty one if it needs to be an object
|
|
1082
|
+
// This can happen when all object properties are optional
|
|
1083
|
+
request = {} as RequestType<C>;
|
|
1084
|
+
}
|
|
1085
|
+
if (requestSchema.isFabricScoped && request.fabricIndex === undefined) {
|
|
1086
|
+
request.fabricIndex = FabricIndex.NO_FABRIC;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
997
1089
|
|
|
998
1090
|
logger.debug(
|
|
999
1091
|
`Invoking command: ${resolveCommandName({
|
|
1000
1092
|
endpointId,
|
|
1001
1093
|
clusterId,
|
|
1002
1094
|
commandId: requestId,
|
|
1003
|
-
})} with ${
|
|
1095
|
+
})} with ${Diagnostic.json(request)}`,
|
|
1004
1096
|
);
|
|
1005
1097
|
|
|
1006
|
-
|
|
1098
|
+
if (!skipValidation) {
|
|
1099
|
+
requestSchema.validate(request);
|
|
1100
|
+
}
|
|
1007
1101
|
|
|
1008
1102
|
const commandFields = requestSchema.encodeTlv(request);
|
|
1009
1103
|
|
|
@@ -1067,7 +1161,7 @@ export class InteractionClient {
|
|
|
1067
1161
|
endpointId,
|
|
1068
1162
|
clusterId,
|
|
1069
1163
|
commandId: requestId,
|
|
1070
|
-
})} with ${
|
|
1164
|
+
})} with ${Diagnostic.json(response)})}`,
|
|
1071
1165
|
);
|
|
1072
1166
|
return response;
|
|
1073
1167
|
}
|
|
@@ -1103,7 +1197,7 @@ export class InteractionClient {
|
|
|
1103
1197
|
endpointId,
|
|
1104
1198
|
clusterId,
|
|
1105
1199
|
commandId: requestId,
|
|
1106
|
-
})} with ${
|
|
1200
|
+
})} with ${Diagnostic.json(request)}`,
|
|
1107
1201
|
);
|
|
1108
1202
|
const commandFields = requestSchema.encodeTlv(request);
|
|
1109
1203
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "#general";
|
|
15
15
|
import { Specification } from "#model";
|
|
16
16
|
import {
|
|
17
|
+
ReceivedStatusResponseError,
|
|
17
18
|
Status,
|
|
18
19
|
StatusCode,
|
|
19
20
|
StatusResponseError,
|
|
@@ -184,7 +185,10 @@ class InteractionMessenger {
|
|
|
184
185
|
if (messageType !== MessageType.StatusResponse) return;
|
|
185
186
|
const { status } = TlvStatusResponse.decode(payload);
|
|
186
187
|
if (status !== StatusCode.Success)
|
|
187
|
-
throw new
|
|
188
|
+
throw new ReceivedStatusResponseError(
|
|
189
|
+
`Received error status: ${status}${logHint ? ` (${logHint})` : ""}`,
|
|
190
|
+
status,
|
|
191
|
+
);
|
|
188
192
|
}
|
|
189
193
|
|
|
190
194
|
getExchangeChannelName() {
|
|
@@ -629,7 +633,7 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
629
633
|
const encodedMessage = TlvDataReportForSend.encode(dataReportToSend);
|
|
630
634
|
if (encodedMessage.length > this.exchange.maxPayloadSize) {
|
|
631
635
|
throw new MatterFlowError(
|
|
632
|
-
`DataReport with ${encodedMessage.length}bytes is too long to fit in a single chunk (${this.exchange.maxPayloadSize}bytes), This should not happen! Data: ${
|
|
636
|
+
`DataReport with ${encodedMessage.length}bytes is too long to fit in a single chunk (${this.exchange.maxPayloadSize}bytes), This should not happen! Data: ${Diagnostic.json(
|
|
633
637
|
dataReportToSend,
|
|
634
638
|
)}`,
|
|
635
639
|
);
|
|
@@ -680,7 +684,7 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
|
|
|
680
684
|
if (receivedMessageType !== messageType) {
|
|
681
685
|
if (receivedMessageType === MessageType.StatusResponse) {
|
|
682
686
|
const statusCode = TlvStatusResponse.decode(message.payload).status;
|
|
683
|
-
throw new
|
|
687
|
+
throw new ReceivedStatusResponseError(`Received status response ${statusCode}`, statusCode);
|
|
684
688
|
}
|
|
685
689
|
throw new MatterFlowError(
|
|
686
690
|
`Received unexpected message type ${receivedMessageType.toString(16)}. Expected ${messageType.toString(
|
|
@@ -852,7 +856,7 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
|
|
|
852
856
|
});
|
|
853
857
|
if (requestWithoutDataVersionFilters.length > this.exchange.maxPayloadSize) {
|
|
854
858
|
throw new MatterFlowError(
|
|
855
|
-
`Request is too long to fit in a single chunk, This should not happen! Data: ${
|
|
859
|
+
`Request is too long to fit in a single chunk, This should not happen! Data: ${Diagnostic.json(request)}`,
|
|
856
860
|
);
|
|
857
861
|
}
|
|
858
862
|
|
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Crypto,
|
|
9
|
+
Diagnostic,
|
|
10
|
+
InternalError,
|
|
11
|
+
Logger,
|
|
12
|
+
MatterError,
|
|
13
|
+
MatterFlowError,
|
|
14
|
+
Observable,
|
|
15
|
+
ServerAddressIp,
|
|
16
|
+
} from "#general";
|
|
8
17
|
import { AttributeModel, ClusterModel, CommandModel, GLOBAL_IDS, MatterModel, Specification } from "#model";
|
|
9
18
|
import { PeerAddress } from "#peer/PeerAddress.js";
|
|
10
19
|
import { SessionManager } from "#session/SessionManager.js";
|
|
@@ -19,6 +28,7 @@ import {
|
|
|
19
28
|
EventNumber,
|
|
20
29
|
INTERACTION_PROTOCOL_ID,
|
|
21
30
|
NodeId,
|
|
31
|
+
ReceivedStatusResponseError,
|
|
22
32
|
StatusCode,
|
|
23
33
|
StatusResponseError,
|
|
24
34
|
TlvAny,
|
|
@@ -355,7 +365,7 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
355
365
|
logger.debug(
|
|
356
366
|
`Read event from ${exchange.channel.name}: ${this.#endpointStructure.resolveEventName(
|
|
357
367
|
path,
|
|
358
|
-
)}=${
|
|
368
|
+
)}=${Diagnostic.json(matchingEvents)}`,
|
|
359
369
|
);
|
|
360
370
|
const { schema } = event;
|
|
361
371
|
reportsForPath.push(
|
|
@@ -513,7 +523,7 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
513
523
|
logger.debug(
|
|
514
524
|
`Read attribute from ${exchange.channel.name}: ${this.#endpointStructure.resolveAttributeName(
|
|
515
525
|
path,
|
|
516
|
-
)}=${
|
|
526
|
+
)}=${Diagnostic.json(value)} (version=${version}) ignored because of dataVersionFilter`,
|
|
517
527
|
);
|
|
518
528
|
continue;
|
|
519
529
|
}
|
|
@@ -521,7 +531,7 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
521
531
|
logger.debug(
|
|
522
532
|
`Read attribute from ${exchange.channel.name}: ${this.#endpointStructure.resolveAttributeName(
|
|
523
533
|
path,
|
|
524
|
-
)}=${
|
|
534
|
+
)}=${Diagnostic.json(value)} (version=${version})`,
|
|
525
535
|
);
|
|
526
536
|
|
|
527
537
|
const { schema } = attribute;
|
|
@@ -868,7 +878,7 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
868
878
|
logger.debug(
|
|
869
879
|
`Handle write request from ${
|
|
870
880
|
exchange.channel.name
|
|
871
|
-
} resolved to: ${this.#endpointStructure.resolveAttributeName(path)}=${
|
|
881
|
+
} resolved to: ${this.#endpointStructure.resolveAttributeName(path)}=${Diagnostic.json(
|
|
872
882
|
value,
|
|
873
883
|
)} (listIndex=${listIndex}, for-version=${dataVersion})`,
|
|
874
884
|
);
|
|
@@ -950,7 +960,7 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
950
960
|
? `with following errors: ${errorResults
|
|
951
961
|
.map(
|
|
952
962
|
({ path, statusCode }) =>
|
|
953
|
-
`${this.#endpointStructure.resolveAttributeName(path)}=${
|
|
963
|
+
`${this.#endpointStructure.resolveAttributeName(path)}=${Diagnostic.json(statusCode)}`,
|
|
954
964
|
)
|
|
955
965
|
.join(", ")}`
|
|
956
966
|
: "without errors"
|
|
@@ -1115,12 +1125,12 @@ export class InteractionServer implements ProtocolHandler, InteractionRecipient
|
|
|
1115
1125
|
exchange,
|
|
1116
1126
|
message,
|
|
1117
1127
|
);
|
|
1118
|
-
} catch (error
|
|
1128
|
+
} catch (error) {
|
|
1119
1129
|
logger.error(
|
|
1120
1130
|
`Subscription ${subscriptionId} for Session ${session.id}: Error while sending initial data reports`,
|
|
1121
|
-
error,
|
|
1131
|
+
error instanceof MatterError ? error.message : error,
|
|
1122
1132
|
);
|
|
1123
|
-
if (error instanceof StatusResponseError) {
|
|
1133
|
+
if (error instanceof StatusResponseError && !(error instanceof ReceivedStatusResponseError)) {
|
|
1124
1134
|
logger.info(`Sending status response ${error.code} for interaction error: ${error.message}`);
|
|
1125
1135
|
await messenger.sendStatus(error.code, {
|
|
1126
1136
|
logContext: {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { NumberedOccurrence } from "#events/Occurrence.js";
|
|
8
8
|
import {
|
|
9
|
+
Diagnostic,
|
|
9
10
|
InternalError,
|
|
10
11
|
Logger,
|
|
11
12
|
MatterAggregateError,
|
|
@@ -989,7 +990,7 @@ export class ServerSubscription extends Subscription {
|
|
|
989
990
|
`Subscription attribute changes for ID ${this.id}: ${attributes
|
|
990
991
|
.map(
|
|
991
992
|
({ path, value, version }) =>
|
|
992
|
-
`${this.#structure.resolveAttributeName(path)}=${
|
|
993
|
+
`${this.#structure.resolveAttributeName(path)}=${Diagnostic.json(value)} (${version})`,
|
|
993
994
|
)
|
|
994
995
|
.join(", ")}`,
|
|
995
996
|
); // TODO Format path better using endpoint structure
|
package/src/mdns/MdnsScanner.ts
CHANGED
|
@@ -213,7 +213,7 @@ export class MdnsScanner implements Scanner {
|
|
|
213
213
|
if (dnsMessageDataToSend.answers.length === 0) {
|
|
214
214
|
// The first answer is already too big, log at least a warning
|
|
215
215
|
logger.warn(
|
|
216
|
-
`MDNS Query with ${
|
|
216
|
+
`MDNS Query with ${Diagnostic.json(
|
|
217
217
|
queries,
|
|
218
218
|
)} is too big to fit into a single MDNS message. Send anyway, but please report!`,
|
|
219
219
|
);
|
|
@@ -265,7 +265,7 @@ export class MdnsScanner implements Scanner {
|
|
|
265
265
|
answers = this.#combineStructuredAnswers(activeExistingQuery.answers, answers);
|
|
266
266
|
}
|
|
267
267
|
this.#activeAnnounceQueries.set(queryId, { queries, answers });
|
|
268
|
-
logger.debug(`Set ${queries.length} query records for query ${queryId}: ${
|
|
268
|
+
logger.debug(`Set ${queries.length} query records for query ${queryId}: ${Diagnostic.json(queries)}`);
|
|
269
269
|
this.#queryTimer?.stop();
|
|
270
270
|
this.#nextAnnounceIntervalSeconds = START_ANNOUNCE_INTERVAL_SECONDS; // Reset query interval
|
|
271
271
|
this.#queryTimer = Time.getTimer("MDNS discovery", 0, () => this.#sendQueries()).start();
|
|
@@ -11,6 +11,8 @@ import { Fabric } from "#fabric/Fabric.js";
|
|
|
11
11
|
import {
|
|
12
12
|
Channel,
|
|
13
13
|
ChannelType,
|
|
14
|
+
ClassExtends,
|
|
15
|
+
Diagnostic,
|
|
14
16
|
Environment,
|
|
15
17
|
Environmental,
|
|
16
18
|
isIPv6,
|
|
@@ -55,6 +57,12 @@ export interface CommissioningOptions extends Partial<ControllerCommissioningFlo
|
|
|
55
57
|
* not throw, the commissioner considers commissioning complete.
|
|
56
58
|
*/
|
|
57
59
|
finalizeCommissioning?: (peerAddress: PeerAddress, discoveryData?: DiscoveryData) => Promise<void>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Commissioning Flow Implementation as class that extends the official implementation to use for commissioning.
|
|
63
|
+
* Defaults to the matter.js default implementation {@link ControllerCommissioningFlow}.
|
|
64
|
+
*/
|
|
65
|
+
commissioningFlowImpl?: ClassExtends<ControllerCommissioningFlow>;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
/**
|
|
@@ -169,9 +177,11 @@ export class ControllerCommissioner {
|
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
/**
|
|
172
|
-
*
|
|
180
|
+
* Discover and establish a PASE channel with a device.
|
|
173
181
|
*/
|
|
174
|
-
async
|
|
182
|
+
async discoverAndEstablishPase(
|
|
183
|
+
options: DiscoveryAndCommissioningOptions,
|
|
184
|
+
): Promise<{ paseSecureChannel: MessageChannel; discoveryData?: DiscoveryData }> {
|
|
175
185
|
const {
|
|
176
186
|
discovery: { timeoutSeconds = 30 },
|
|
177
187
|
passcode,
|
|
@@ -211,9 +221,9 @@ export class ControllerCommissioner {
|
|
|
211
221
|
const scannersToUse = this.#context.scanners.select(discoveryCapabilities);
|
|
212
222
|
|
|
213
223
|
logger.info(
|
|
214
|
-
`
|
|
224
|
+
`Connecting to device with identifier ${Diagnostic.json(identifierData)} and ${
|
|
215
225
|
scannersToUse.length
|
|
216
|
-
} scanners and knownAddress ${
|
|
226
|
+
} scanners and knownAddress ${Diagnostic.json(knownAddress)}`,
|
|
217
227
|
);
|
|
218
228
|
|
|
219
229
|
// If we have a known address we try this first before we discover the device
|
|
@@ -251,6 +261,17 @@ export class ControllerCommissioner {
|
|
|
251
261
|
paseSecureChannel = result;
|
|
252
262
|
}
|
|
253
263
|
|
|
264
|
+
return { paseSecureChannel, discoveryData };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Commission a node with discovery.
|
|
269
|
+
*/
|
|
270
|
+
async commissionWithDiscovery(options: DiscoveryAndCommissioningOptions): Promise<PeerAddress> {
|
|
271
|
+
// Establish PASE channel
|
|
272
|
+
const { paseSecureChannel, discoveryData } = await this.discoverAndEstablishPase(options);
|
|
273
|
+
|
|
274
|
+
// Commission the node
|
|
254
275
|
return await this.#commissionConnectedNode(paseSecureChannel, options, discoveryData);
|
|
255
276
|
}
|
|
256
277
|
|
|
@@ -266,7 +287,7 @@ export class ControllerCommissioner {
|
|
|
266
287
|
): Promise<MessageChannel> {
|
|
267
288
|
let paseChannel: Channel<Uint8Array>;
|
|
268
289
|
if (device !== undefined) {
|
|
269
|
-
logger.info(`
|
|
290
|
+
logger.info(`Establish PASE to device`, MdnsScanner.discoveryDataDiagnostics(device));
|
|
270
291
|
}
|
|
271
292
|
if (address.type === "udp") {
|
|
272
293
|
const { ip } = address;
|
|
@@ -347,7 +368,11 @@ export class ControllerCommissioner {
|
|
|
347
368
|
...options,
|
|
348
369
|
};
|
|
349
370
|
|
|
350
|
-
const {
|
|
371
|
+
const {
|
|
372
|
+
fabric,
|
|
373
|
+
finalizeCommissioning: performCaseCommissioning,
|
|
374
|
+
commissioningFlowImpl = ControllerCommissioningFlow,
|
|
375
|
+
} = commissioningOptions;
|
|
351
376
|
|
|
352
377
|
// TODO: Create the fabric only when needed before commissioning (to do when refactoring MatterController away)
|
|
353
378
|
// TODO also move certificateManager and other parts into that class to get rid of them here
|
|
@@ -381,7 +406,7 @@ export class ControllerCommissioner {
|
|
|
381
406
|
logger.info(
|
|
382
407
|
`Start commissioning of node ${address.nodeId} into fabric ${fabric.fabricId} (index ${address.fabricIndex})`,
|
|
383
408
|
);
|
|
384
|
-
const commissioningManager = new
|
|
409
|
+
const commissioningManager = new commissioningFlowImpl(
|
|
385
410
|
// Use the created secure session to do the commissioning
|
|
386
411
|
new InteractionClient(
|
|
387
412
|
new DedicatedChannelExchangeProvider(this.#context.exchanges, paseSecureMessageChannel),
|