@matter/protocol 0.12.4-alpha.0-20250223-1e0341a1a → 0.12.4-alpha.0-20250224-e0964a795
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 +38 -0
- package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -0
- package/dist/cjs/action/client/ClientInteraction.js +91 -0
- package/dist/cjs/action/client/ClientInteraction.js.map +6 -0
- package/dist/cjs/action/client/index.d.ts +7 -0
- package/dist/cjs/action/client/index.d.ts.map +1 -0
- package/dist/cjs/action/client/index.js +24 -0
- package/dist/cjs/action/client/index.js.map +6 -0
- package/dist/cjs/action/index.d.ts +1 -0
- package/dist/cjs/action/index.d.ts.map +1 -1
- package/dist/cjs/action/index.js +1 -0
- package/dist/cjs/action/index.js.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.d.ts +15 -0
- package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -0
- package/dist/cjs/interaction/DecodedDataReport.js +42 -0
- package/dist/cjs/interaction/DecodedDataReport.js.map +6 -0
- package/dist/cjs/interaction/InteractionClient.d.ts +13 -23
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +99 -127
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts +94 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +56 -37
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/InteractionServer.d.ts +4 -2
- package/dist/cjs/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionServer.js +12 -4
- package/dist/cjs/interaction/InteractionServer.js.map +1 -1
- package/dist/cjs/interaction/SubscriptionClient.d.ts +38 -0
- package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -0
- package/dist/cjs/interaction/SubscriptionClient.js +98 -0
- package/dist/cjs/interaction/SubscriptionClient.js.map +6 -0
- package/dist/cjs/interaction/index.d.ts +1 -0
- package/dist/cjs/interaction/index.d.ts.map +1 -1
- package/dist/cjs/interaction/index.js +1 -0
- package/dist/cjs/interaction/index.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.d.ts +2 -2
- package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +4 -3
- package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
- package/dist/cjs/peer/InteractionQueue.d.ts +11 -0
- package/dist/cjs/peer/InteractionQueue.d.ts.map +1 -0
- package/dist/cjs/peer/InteractionQueue.js +42 -0
- package/dist/cjs/peer/InteractionQueue.js.map +6 -0
- package/dist/cjs/peer/PeerAddressStore.d.ts +1 -1
- package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts +16 -7
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +58 -61
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/peer/PhysicalDeviceProperties.d.ts +26 -0
- package/dist/cjs/peer/PhysicalDeviceProperties.d.ts.map +1 -0
- package/dist/cjs/peer/PhysicalDeviceProperties.js +74 -0
- package/dist/cjs/peer/PhysicalDeviceProperties.js.map +6 -0
- package/dist/cjs/peer/index.d.ts +1 -0
- package/dist/cjs/peer/index.d.ts.map +1 -1
- package/dist/cjs/peer/index.js +1 -0
- package/dist/cjs/peer/index.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts +1 -0
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +6 -3
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeProvider.d.ts +13 -1
- package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeProvider.js +2 -0
- package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
- package/dist/cjs/protocol/ProtocolHandler.d.ts +1 -1
- 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 +1 -3
- package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +1 -0
- package/dist/cjs/session/SessionManager.js.map +1 -1
- package/dist/cjs/session/case/CaseServer.d.ts +1 -1
- package/dist/cjs/session/case/CaseServer.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseServer.js +1 -3
- package/dist/cjs/session/case/CaseServer.js.map +1 -1
- package/dist/cjs/session/pase/PaseServer.d.ts +2 -3
- package/dist/cjs/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseServer.js +12 -14
- package/dist/cjs/session/pase/PaseServer.js.map +1 -1
- package/dist/esm/action/client/ClientInteraction.d.ts +38 -0
- package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -0
- package/dist/esm/action/client/ClientInteraction.js +71 -0
- package/dist/esm/action/client/ClientInteraction.js.map +6 -0
- package/dist/esm/action/client/index.d.ts +7 -0
- package/dist/esm/action/client/index.d.ts.map +1 -0
- package/dist/esm/action/client/index.js +7 -0
- package/dist/esm/action/client/index.js.map +6 -0
- package/dist/esm/action/index.d.ts +1 -0
- package/dist/esm/action/index.d.ts.map +1 -1
- package/dist/esm/action/index.js +1 -0
- package/dist/esm/action/index.js.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.d.ts +15 -0
- package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -0
- package/dist/esm/interaction/DecodedDataReport.js +22 -0
- package/dist/esm/interaction/DecodedDataReport.js.map +6 -0
- package/dist/esm/interaction/InteractionClient.d.ts +13 -23
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +101 -134
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts +94 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +56 -37
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/InteractionServer.d.ts +4 -2
- package/dist/esm/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionServer.js +12 -4
- package/dist/esm/interaction/InteractionServer.js.map +1 -1
- package/dist/esm/interaction/SubscriptionClient.d.ts +38 -0
- package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -0
- package/dist/esm/interaction/SubscriptionClient.js +78 -0
- package/dist/esm/interaction/SubscriptionClient.js.map +6 -0
- package/dist/esm/interaction/index.d.ts +1 -0
- package/dist/esm/interaction/index.d.ts.map +1 -1
- package/dist/esm/interaction/index.js +1 -0
- package/dist/esm/interaction/index.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.d.ts +2 -2
- package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +6 -5
- package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
- package/dist/esm/peer/InteractionQueue.d.ts +11 -0
- package/dist/esm/peer/InteractionQueue.d.ts.map +1 -0
- package/dist/esm/peer/InteractionQueue.js +22 -0
- package/dist/esm/peer/InteractionQueue.js.map +6 -0
- package/dist/esm/peer/PeerAddressStore.d.ts +1 -1
- package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts +16 -7
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +59 -62
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/peer/PhysicalDeviceProperties.d.ts +26 -0
- package/dist/esm/peer/PhysicalDeviceProperties.d.ts.map +1 -0
- package/dist/esm/peer/PhysicalDeviceProperties.js +54 -0
- package/dist/esm/peer/PhysicalDeviceProperties.js.map +6 -0
- package/dist/esm/peer/index.d.ts +1 -0
- package/dist/esm/peer/index.d.ts.map +1 -1
- package/dist/esm/peer/index.js +1 -0
- package/dist/esm/peer/index.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts +1 -0
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +6 -3
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.d.ts +13 -1
- package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.js +2 -0
- package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
- package/dist/esm/protocol/ProtocolHandler.d.ts +1 -1
- 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 +1 -3
- package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +1 -0
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/session/case/CaseServer.d.ts +1 -1
- package/dist/esm/session/case/CaseServer.d.ts.map +1 -1
- package/dist/esm/session/case/CaseServer.js +1 -3
- package/dist/esm/session/case/CaseServer.js.map +1 -1
- package/dist/esm/session/pase/PaseServer.d.ts +2 -3
- package/dist/esm/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseServer.js +12 -14
- package/dist/esm/session/pase/PaseServer.js.map +1 -1
- package/package.json +6 -6
- package/src/action/client/ClientInteraction.ts +110 -0
- package/src/action/client/index.ts +7 -0
- package/src/action/index.ts +1 -0
- package/src/interaction/DecodedDataReport.ts +29 -0
- package/src/interaction/InteractionClient.ts +112 -164
- package/src/interaction/InteractionMessenger.ts +63 -43
- package/src/interaction/InteractionServer.ts +18 -5
- package/src/interaction/SubscriptionClient.ts +107 -0
- package/src/interaction/index.ts +1 -0
- package/src/peer/ControllerCommissioner.ts +7 -6
- package/src/peer/InteractionQueue.ts +22 -0
- package/src/peer/PeerAddressStore.ts +1 -1
- package/src/peer/PeerSet.ts +69 -76
- package/src/peer/PhysicalDeviceProperties.ts +80 -0
- package/src/peer/index.ts +1 -0
- package/src/protocol/ExchangeManager.ts +7 -3
- package/src/protocol/ExchangeProvider.ts +14 -1
- package/src/protocol/ProtocolHandler.ts +1 -1
- package/src/securechannel/SecureChannelProtocol.ts +1 -3
- package/src/session/SessionManager.ts +1 -0
- package/src/session/case/CaseServer.ts +2 -4
- package/src/session/pase/PaseServer.ts +13 -15
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Interactable } from "#action/Interactable.js";
|
|
8
|
+
import { Invoke } from "#action/request/Invoke.js";
|
|
9
|
+
import { Read } from "#action/request/Read.js";
|
|
10
|
+
import { Subscribe } from "#action/request/Subscribe.js";
|
|
11
|
+
import { Write } from "#action/request/Write.js";
|
|
12
|
+
import { InvokeResult } from "#action/response/InvokeResult.js";
|
|
13
|
+
import { ReadResult } from "#action/response/ReadResult.js";
|
|
14
|
+
import { SubscribeResult } from "#action/response/SubscribeResult.js";
|
|
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";
|
|
18
|
+
import { InteractionClientMessenger } from "#interaction/InteractionMessenger.js";
|
|
19
|
+
import { SubscriptionClient } from "#interaction/SubscriptionClient.js";
|
|
20
|
+
import { InteractionQueue } from "#peer/InteractionQueue.js";
|
|
21
|
+
import { ExchangeProvider } from "#protocol/ExchangeProvider.js";
|
|
22
|
+
import { WriteResponse } from "#types";
|
|
23
|
+
|
|
24
|
+
export interface ClientInteractableContext {
|
|
25
|
+
exchanges: ExchangeProvider;
|
|
26
|
+
subscriptions: SubscriptionClient;
|
|
27
|
+
queue: PromiseQueue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* This is a WIP and currently largely a stub.
|
|
32
|
+
*/
|
|
33
|
+
export class ClientInteraction<SessionT extends AccessControl.Session = AccessControl.Session>
|
|
34
|
+
implements Interactable<SessionT>
|
|
35
|
+
{
|
|
36
|
+
readonly #exchanges: ExchangeProvider;
|
|
37
|
+
readonly #subscriptions: SubscriptionClient;
|
|
38
|
+
readonly #queue?: PromiseQueue;
|
|
39
|
+
|
|
40
|
+
constructor(context: ClientInteractableContext) {
|
|
41
|
+
this.#exchanges = context.exchanges;
|
|
42
|
+
this.#subscriptions = context.subscriptions;
|
|
43
|
+
this.#queue = context.queue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get subscriptions() {
|
|
47
|
+
return this.#subscriptions;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get queue() {
|
|
51
|
+
return this.#queue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static [Environmental.create](env: Environment) {
|
|
55
|
+
const instance = new ClientInteraction({
|
|
56
|
+
exchanges: env.get(ExchangeProvider),
|
|
57
|
+
subscriptions: env.get(SubscriptionClient),
|
|
58
|
+
queue: env.get(InteractionQueue),
|
|
59
|
+
});
|
|
60
|
+
env.set(ClientInteraction, instance);
|
|
61
|
+
return instance;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
read(_request: Read, _session?: SessionT): ReadResult {
|
|
65
|
+
// TODO
|
|
66
|
+
throw new NotImplementedError();
|
|
67
|
+
}
|
|
68
|
+
|
|
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>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
invoke<T extends Invoke>(request: Invoke, _session?: SessionT): InvokeResult<T> {
|
|
89
|
+
if (request.suppressResponse) {
|
|
90
|
+
return new CancelablePromise<void>((resolve, reject) => {
|
|
91
|
+
InteractionClientMessenger.create(this.#exchanges)
|
|
92
|
+
.then(messenger =>
|
|
93
|
+
messenger
|
|
94
|
+
.sendInvokeCommand(request)
|
|
95
|
+
.then(() => resolve())
|
|
96
|
+
.catch(reject),
|
|
97
|
+
)
|
|
98
|
+
.then(resolve, reject);
|
|
99
|
+
}) as InvokeResult<T>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// TODO
|
|
103
|
+
throw new NotImplementedError();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
subscribe(_request: Subscribe, _session?: SessionT): SubscribeResult {
|
|
107
|
+
// TODO
|
|
108
|
+
throw new NotImplementedError();
|
|
109
|
+
}
|
|
110
|
+
}
|
package/src/action/index.ts
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { DataReport } from "#types";
|
|
8
|
+
import { DecodedAttributeReportValue, normalizeAndDecodeReadAttributeReport } from "./AttributeDataDecoder.js";
|
|
9
|
+
import { DecodedEventReportValue, normalizeAndDecodeReadEventReport } from "./EventDataDecoder.js";
|
|
10
|
+
|
|
11
|
+
export interface DecodedDataReport extends DataReport {
|
|
12
|
+
isNormalized: true;
|
|
13
|
+
attributeReports: DecodedAttributeReportValue<any>[];
|
|
14
|
+
eventReports: DecodedEventReportValue<any>[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function DecodedDataReport(report: DataReport): DecodedDataReport {
|
|
18
|
+
if ((report as DecodedDataReport).isNormalized) {
|
|
19
|
+
return report as DecodedDataReport;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
...report,
|
|
24
|
+
isNormalized: true,
|
|
25
|
+
attributeReports:
|
|
26
|
+
report.attributeReports === undefined ? [] : normalizeAndDecodeReadAttributeReport(report.attributeReports),
|
|
27
|
+
eventReports: report.eventReports === undefined ? [] : normalizeAndDecodeReadEventReport(report.eventReports),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -5,20 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
Environment,
|
|
9
|
+
Environmental,
|
|
8
10
|
ImplementationError,
|
|
9
|
-
InternalError,
|
|
10
11
|
Logger,
|
|
11
12
|
MatterFlowError,
|
|
12
|
-
MaybePromise,
|
|
13
13
|
PromiseQueue,
|
|
14
|
-
Time,
|
|
15
14
|
Timer,
|
|
16
15
|
UnexpectedDataError,
|
|
17
16
|
isDeepEqual,
|
|
18
17
|
} from "#general";
|
|
19
18
|
import { Specification } from "#model";
|
|
20
|
-
import { PeerAddress } from "#peer/PeerAddress.js";
|
|
19
|
+
import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
|
|
21
20
|
import { PeerDataStore } from "#peer/PeerAddressStore.js";
|
|
21
|
+
import { DiscoveryOptions, PeerSet } from "#peer/PeerSet.js";
|
|
22
22
|
import {
|
|
23
23
|
ArraySchema,
|
|
24
24
|
Attribute,
|
|
@@ -30,7 +30,6 @@ import {
|
|
|
30
30
|
Event,
|
|
31
31
|
EventId,
|
|
32
32
|
EventNumber,
|
|
33
|
-
INTERACTION_PROTOCOL_ID,
|
|
34
33
|
NodeId,
|
|
35
34
|
RequestType,
|
|
36
35
|
ResponseType,
|
|
@@ -47,16 +46,11 @@ import {
|
|
|
47
46
|
resolveEventName,
|
|
48
47
|
} from "#types";
|
|
49
48
|
import { ExchangeProvider, ReconnectableExchangeProvider } from "../protocol/ExchangeProvider.js";
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
DataReport,
|
|
56
|
-
IncomingInteractionClientMessenger,
|
|
57
|
-
InteractionClientMessenger,
|
|
58
|
-
ReadRequest,
|
|
59
|
-
} from "./InteractionMessenger.js";
|
|
49
|
+
import { DecodedAttributeReportValue } from "./AttributeDataDecoder.js";
|
|
50
|
+
import { DecodedDataReport } from "./DecodedDataReport.js";
|
|
51
|
+
import { DecodedEventData, DecodedEventReportValue } from "./EventDataDecoder.js";
|
|
52
|
+
import { DataReport, InteractionClientMessenger, ReadRequest } from "./InteractionMessenger.js";
|
|
53
|
+
import { RegisteredSubscription, SubscriptionClient } from "./SubscriptionClient.js";
|
|
60
54
|
|
|
61
55
|
const logger = Logger.get("InteractionClient");
|
|
62
56
|
|
|
@@ -74,102 +68,98 @@ export interface AttributeStatus {
|
|
|
74
68
|
status: StatusCode;
|
|
75
69
|
}
|
|
76
70
|
|
|
77
|
-
export class
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
constructor() {}
|
|
71
|
+
export class InteractionClientProvider {
|
|
72
|
+
readonly #peers: PeerSet;
|
|
73
|
+
readonly #clients = new PeerAddressMap<InteractionClient>();
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
constructor(peers: PeerSet) {
|
|
76
|
+
this.#peers = peers;
|
|
77
|
+
this.#peers.deleted.on(peer => this.#onPeerLoss(peer.address));
|
|
78
|
+
this.#peers.disconnected.on(address => this.#onPeerLoss(address));
|
|
85
79
|
}
|
|
86
80
|
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
static [Environmental.create](env: Environment) {
|
|
82
|
+
const instance = new InteractionClientProvider(env.get(PeerSet));
|
|
83
|
+
env.set(InteractionClientProvider, instance);
|
|
84
|
+
return instance;
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
this
|
|
87
|
+
get peers() {
|
|
88
|
+
return this.#peers;
|
|
93
89
|
}
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
async connect(
|
|
92
|
+
address: PeerAddress,
|
|
93
|
+
discoveryOptions: DiscoveryOptions,
|
|
94
|
+
allowUnknownPeer = false,
|
|
95
|
+
): Promise<InteractionClient> {
|
|
96
|
+
await this.#peers.ensureConnection(address, discoveryOptions, allowUnknownPeer);
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
this.subscriptionUpdateTimers.get(subscriptionId)?.stop();
|
|
101
|
-
this.subscriptionUpdateTimers.delete(subscriptionId);
|
|
98
|
+
return this.getInteractionClient(address, discoveryOptions);
|
|
102
99
|
}
|
|
103
100
|
|
|
104
|
-
async
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
// TODO Adjust this to getting packages as callback when received to handle error cases and checks outside
|
|
110
|
-
dataReport = await messenger.readDataReports([...this.subscriptionListeners.keys()]);
|
|
111
|
-
} finally {
|
|
112
|
-
messenger.close().catch(error => logger.info("Error closing client messenger", error));
|
|
101
|
+
async getInteractionClient(address: PeerAddress, discoveryOptions: DiscoveryOptions) {
|
|
102
|
+
let client = this.#clients.get(address);
|
|
103
|
+
if (client !== undefined) {
|
|
104
|
+
return client;
|
|
113
105
|
}
|
|
114
|
-
const subscriptionId = dataReport.subscriptionId as number; // this is checked in the messenger already because we hand over allowed list
|
|
115
106
|
|
|
116
|
-
const
|
|
117
|
-
|
|
107
|
+
const nodeStore = this.#peers.get(address)?.dataStore;
|
|
108
|
+
await nodeStore?.construction; // Lazy initialize the data if not already done
|
|
118
109
|
|
|
119
|
-
|
|
120
|
-
timer.stop().start(); // Restart timer because we received data
|
|
121
|
-
}
|
|
110
|
+
const exchangeProvider = await this.#peers.exchangeProviderFor(address, discoveryOptions);
|
|
122
111
|
|
|
123
|
-
|
|
112
|
+
client = new InteractionClient(
|
|
113
|
+
exchangeProvider,
|
|
114
|
+
this.#peers.subscriptionClient,
|
|
115
|
+
address,
|
|
116
|
+
this.#peers.interactionQueue,
|
|
117
|
+
nodeStore,
|
|
118
|
+
);
|
|
119
|
+
this.#clients.set(address, client);
|
|
120
|
+
|
|
121
|
+
return client;
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
this.
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
#onPeerLoss(address: PeerAddress) {
|
|
125
|
+
const client = this.#clients.get(address);
|
|
126
|
+
if (client !== undefined) {
|
|
127
|
+
client.close();
|
|
128
|
+
this.#clients.delete(address);
|
|
129
|
+
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export class InteractionClient {
|
|
134
|
+
readonly #exchangeProvider: ExchangeProvider;
|
|
134
135
|
readonly #nodeStore?: PeerDataStore;
|
|
135
136
|
readonly #ownSubscriptionIds = new Set<number>();
|
|
136
137
|
readonly #subscriptionClient: SubscriptionClient;
|
|
137
138
|
readonly #queue?: PromiseQueue;
|
|
138
139
|
|
|
139
140
|
constructor(
|
|
140
|
-
|
|
141
|
+
exchangeProvider: ExchangeProvider,
|
|
142
|
+
subscriptionClient: SubscriptionClient,
|
|
141
143
|
readonly address: PeerAddress,
|
|
142
144
|
queue?: PromiseQueue,
|
|
143
145
|
nodeStore?: PeerDataStore,
|
|
144
146
|
) {
|
|
147
|
+
this.#exchangeProvider = exchangeProvider;
|
|
145
148
|
this.#nodeStore = nodeStore;
|
|
149
|
+
this.#subscriptionClient = subscriptionClient;
|
|
146
150
|
this.#queue = queue;
|
|
147
|
-
|
|
148
|
-
const client = this.exchangeProvider.getProtocolHandler(INTERACTION_PROTOCOL_ID);
|
|
149
|
-
if (client === undefined || !(client instanceof SubscriptionClient)) {
|
|
150
|
-
throw new InternalError(
|
|
151
|
-
`Subscription protocol handler ${INTERACTION_PROTOCOL_ID} missing or unexpected type.`,
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
this.#subscriptionClient = client;
|
|
155
151
|
}
|
|
156
152
|
|
|
157
153
|
get channelUpdated() {
|
|
158
|
-
if (this
|
|
159
|
-
return this
|
|
154
|
+
if (this.#exchangeProvider instanceof ReconnectableExchangeProvider) {
|
|
155
|
+
return this.#exchangeProvider.channelUpdated;
|
|
160
156
|
}
|
|
161
157
|
throw new ImplementationError("ExchangeProvider does not support channelUpdated");
|
|
162
158
|
}
|
|
163
159
|
|
|
164
|
-
registerSubscriptionListener(subscriptionId: number, listener: (dataReport: DataReport) => MaybePromise<void>) {
|
|
165
|
-
this.#ownSubscriptionIds.add(subscriptionId);
|
|
166
|
-
this.#subscriptionClient.registerSubscriptionListener(subscriptionId, listener);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
160
|
removeSubscription(subscriptionId: number) {
|
|
170
161
|
this.#ownSubscriptionIds.delete(subscriptionId);
|
|
171
|
-
this.#subscriptionClient.
|
|
172
|
-
this.#subscriptionClient.removeSubscriptionUpdateTimer(subscriptionId);
|
|
162
|
+
this.#subscriptionClient.delete(subscriptionId);
|
|
173
163
|
}
|
|
174
164
|
|
|
175
165
|
async getAllAttributes(
|
|
@@ -259,10 +249,7 @@ export class InteractionClient {
|
|
|
259
249
|
isFabricFiltered?: boolean;
|
|
260
250
|
executeQueued?: boolean;
|
|
261
251
|
} = {},
|
|
262
|
-
): Promise<{
|
|
263
|
-
attributeReports: DecodedAttributeReportValue<any>[];
|
|
264
|
-
eventReports: DecodedEventReportValue<any>[];
|
|
265
|
-
}> {
|
|
252
|
+
): Promise<DecodedDataReport> {
|
|
266
253
|
const {
|
|
267
254
|
attributes: attributeRequests,
|
|
268
255
|
dataVersionFilters,
|
|
@@ -302,10 +289,7 @@ export class InteractionClient {
|
|
|
302
289
|
);
|
|
303
290
|
}
|
|
304
291
|
|
|
305
|
-
const result = await this.withMessenger
|
|
306
|
-
attributeReports: DecodedAttributeReportValue<any>[];
|
|
307
|
-
eventReports: DecodedEventReportValue<any>[];
|
|
308
|
-
}>(async messenger => {
|
|
292
|
+
const result = await this.withMessenger(async messenger => {
|
|
309
293
|
const { isFabricFiltered = true } = options;
|
|
310
294
|
return await this.processReadRequest(messenger, {
|
|
311
295
|
attributeRequests,
|
|
@@ -404,7 +388,7 @@ export class InteractionClient {
|
|
|
404
388
|
private async processReadRequest(
|
|
405
389
|
messenger: InteractionClientMessenger,
|
|
406
390
|
request: ReadRequest,
|
|
407
|
-
): Promise<
|
|
391
|
+
): Promise<DecodedDataReport> {
|
|
408
392
|
const { attributeRequests, eventRequests } = request;
|
|
409
393
|
logger.debug(
|
|
410
394
|
`Sending read request to ${messenger.getExchangeChannelName()} for attributes ${attributeRequests
|
|
@@ -415,10 +399,7 @@ export class InteractionClient {
|
|
|
415
399
|
const response = await messenger.sendReadRequest(request);
|
|
416
400
|
|
|
417
401
|
// Normalize and decode the response
|
|
418
|
-
const normalizedResult =
|
|
419
|
-
attributeReports: normalizeAndDecodeReadAttributeReport(response.attributeReports ?? []),
|
|
420
|
-
eventReports: normalizeAndDecodeReadEventReport(response.eventReports ?? []),
|
|
421
|
-
};
|
|
402
|
+
const normalizedResult = DecodedDataReport(response);
|
|
422
403
|
logger.debug(
|
|
423
404
|
`Received read response with attributes ${normalizedResult.attributeReports
|
|
424
405
|
.map(({ path, value }) => `${resolveAttributeName(path)} = ${Logger.toJSON(value)}`)
|
|
@@ -643,33 +624,39 @@ export class InteractionClient {
|
|
|
643
624
|
return;
|
|
644
625
|
}
|
|
645
626
|
|
|
646
|
-
const
|
|
627
|
+
const { attributeReports } = DecodedDataReport(dataReport);
|
|
647
628
|
|
|
648
|
-
if (
|
|
629
|
+
if (attributeReports.length === 0) {
|
|
649
630
|
throw new MatterFlowError("Subscription result reporting undefined/no value not specified");
|
|
650
631
|
}
|
|
651
|
-
if (
|
|
632
|
+
if (attributeReports.length > 1) {
|
|
652
633
|
throw new UnexpectedDataError("Unexpected response with more then one attribute");
|
|
653
634
|
}
|
|
654
|
-
const { value, version } =
|
|
635
|
+
const { value, version } = attributeReports[0];
|
|
655
636
|
if (value === undefined)
|
|
656
637
|
throw new MatterFlowError("Subscription result reporting undefined value not specified.");
|
|
657
638
|
|
|
658
|
-
await this.#nodeStore?.persistAttributes([
|
|
639
|
+
await this.#nodeStore?.persistAttributes([attributeReports[0]]);
|
|
659
640
|
|
|
660
641
|
listener?.(value, version);
|
|
661
642
|
};
|
|
662
643
|
|
|
663
|
-
this
|
|
664
|
-
|
|
665
|
-
|
|
644
|
+
await this.#registerSubscription(
|
|
645
|
+
{
|
|
646
|
+
id: subscriptionId,
|
|
666
647
|
maximumPeerResponseTime,
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
updateTimeoutHandler,
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
648
|
+
maxIntervalS: maxInterval,
|
|
649
|
+
onData: subscriptionListener,
|
|
650
|
+
onTimeout: updateTimeoutHandler,
|
|
651
|
+
},
|
|
652
|
+
report,
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
async #registerSubscription(subscription: RegisteredSubscription, initialReport: DataReport) {
|
|
657
|
+
this.#ownSubscriptionIds.add(subscription.id);
|
|
658
|
+
this.#subscriptionClient.add(subscription);
|
|
659
|
+
await subscription.onData(initialReport);
|
|
673
660
|
}
|
|
674
661
|
|
|
675
662
|
async subscribeEvent<T, E extends Event<T, any>>(options: {
|
|
@@ -736,30 +723,30 @@ export class InteractionClient {
|
|
|
736
723
|
return;
|
|
737
724
|
}
|
|
738
725
|
|
|
739
|
-
const
|
|
726
|
+
const { eventReports } = DecodedDataReport(dataReport);
|
|
740
727
|
|
|
741
|
-
if (
|
|
728
|
+
if (eventReports.length === 0) {
|
|
742
729
|
throw new MatterFlowError("Received empty subscription result value.");
|
|
743
730
|
}
|
|
744
|
-
if (
|
|
731
|
+
if (eventReports.length > 1) {
|
|
745
732
|
throw new UnexpectedDataError("Unexpected response with more then one attribute.");
|
|
746
733
|
}
|
|
747
|
-
const { events } =
|
|
734
|
+
const { events } = eventReports[0];
|
|
748
735
|
if (events === undefined)
|
|
749
736
|
throw new MatterFlowError("Subscription result reporting undefined value not specified.");
|
|
750
737
|
|
|
751
738
|
events.forEach(event => listener?.(event));
|
|
752
739
|
};
|
|
753
|
-
this
|
|
754
|
-
|
|
755
|
-
|
|
740
|
+
await this.#registerSubscription(
|
|
741
|
+
{
|
|
742
|
+
id: subscriptionId,
|
|
756
743
|
maximumPeerResponseTime,
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
updateTimeoutHandler,
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
744
|
+
maxIntervalS: maxInterval,
|
|
745
|
+
onData: subscriptionListener,
|
|
746
|
+
onTimeout: updateTimeoutHandler,
|
|
747
|
+
},
|
|
748
|
+
report,
|
|
749
|
+
);
|
|
763
750
|
}
|
|
764
751
|
|
|
765
752
|
async subscribeAllAttributesAndEvents(options: {
|
|
@@ -957,39 +944,21 @@ export class InteractionClient {
|
|
|
957
944
|
}
|
|
958
945
|
}
|
|
959
946
|
};
|
|
960
|
-
this.registerSubscriptionListener(subscriptionId, async dataReport => {
|
|
961
|
-
await subscriptionListener({
|
|
962
|
-
...dataReport,
|
|
963
|
-
attributeReports:
|
|
964
|
-
dataReport.attributeReports !== undefined
|
|
965
|
-
? normalizeAndDecodeReadAttributeReport(dataReport.attributeReports)
|
|
966
|
-
: undefined,
|
|
967
|
-
eventReports:
|
|
968
|
-
dataReport.eventReports !== undefined
|
|
969
|
-
? normalizeAndDecodeReadEventReport(dataReport.eventReports)
|
|
970
|
-
: undefined,
|
|
971
|
-
});
|
|
972
|
-
});
|
|
973
947
|
|
|
974
|
-
|
|
975
|
-
|
|
948
|
+
const seedReport = DecodedDataReport(report);
|
|
949
|
+
|
|
950
|
+
await this.#registerSubscription(
|
|
951
|
+
{
|
|
952
|
+
id: subscriptionId,
|
|
976
953
|
maximumPeerResponseTime,
|
|
977
|
-
|
|
978
|
-
maxInterval,
|
|
979
|
-
updateTimeoutHandler,
|
|
980
|
-
);
|
|
981
|
-
}
|
|
954
|
+
maxIntervalS: maxInterval,
|
|
982
955
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
report.eventReports !== undefined ? normalizeAndDecodeReadEventReport(report.eventReports) : undefined,
|
|
990
|
-
subscriptionId,
|
|
991
|
-
};
|
|
992
|
-
await subscriptionListener(seedReport);
|
|
956
|
+
onData: dataReport => subscriptionListener(DecodedDataReport(dataReport)),
|
|
957
|
+
|
|
958
|
+
onTimeout: updateTimeoutHandler,
|
|
959
|
+
},
|
|
960
|
+
seedReport,
|
|
961
|
+
);
|
|
993
962
|
|
|
994
963
|
if (dataVersionFilters !== undefined && dataVersionFilters.length > 0 && enrichCachedAttributeData) {
|
|
995
964
|
this.#enrichCachedAttributeData(seedReport.attributeReports ?? [], dataVersionFilters);
|
|
@@ -1164,7 +1133,7 @@ export class InteractionClient {
|
|
|
1164
1133
|
invoke: (messenger: InteractionClientMessenger) => Promise<T>,
|
|
1165
1134
|
executeQueued = false,
|
|
1166
1135
|
): Promise<T> {
|
|
1167
|
-
const messenger = await InteractionClientMessenger.create(this
|
|
1136
|
+
const messenger = await InteractionClientMessenger.create(this.#exchangeProvider);
|
|
1168
1137
|
let result: T;
|
|
1169
1138
|
try {
|
|
1170
1139
|
if (executeQueued) {
|
|
@@ -1181,27 +1150,6 @@ export class InteractionClient {
|
|
|
1181
1150
|
return result;
|
|
1182
1151
|
}
|
|
1183
1152
|
|
|
1184
|
-
private registerSubscriptionUpdateTimer(
|
|
1185
|
-
maximumPeerResponseTime: number,
|
|
1186
|
-
subscriptionId: number,
|
|
1187
|
-
maxIntervalS: number,
|
|
1188
|
-
updateTimeoutHandler: Timer.Callback,
|
|
1189
|
-
) {
|
|
1190
|
-
if (!this.#ownSubscriptionIds.has(subscriptionId)) {
|
|
1191
|
-
throw new MatterFlowError(
|
|
1192
|
-
`Cannot register update timer for subscription ${subscriptionId} because it is not owned by this client.`,
|
|
1193
|
-
);
|
|
1194
|
-
}
|
|
1195
|
-
const maxIntervalMs = maxIntervalS * 1000 + maximumPeerResponseTime;
|
|
1196
|
-
|
|
1197
|
-
const timer = Time.getTimer("Subscription timeout", maxIntervalMs, () => {
|
|
1198
|
-
logger.info(`Subscription ${subscriptionId} timed out after ${maxIntervalMs}ms ...`);
|
|
1199
|
-
this.removeSubscription(subscriptionId);
|
|
1200
|
-
updateTimeoutHandler();
|
|
1201
|
-
}).start();
|
|
1202
|
-
this.#subscriptionClient.registerSubscriptionUpdateTimer(subscriptionId, timer);
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
1153
|
removeAllSubscriptions() {
|
|
1206
1154
|
for (const subscriptionId of this.#ownSubscriptionIds) {
|
|
1207
1155
|
this.removeSubscription(subscriptionId);
|
|
@@ -1213,11 +1161,11 @@ export class InteractionClient {
|
|
|
1213
1161
|
}
|
|
1214
1162
|
|
|
1215
1163
|
get session() {
|
|
1216
|
-
return this
|
|
1164
|
+
return this.#exchangeProvider.session;
|
|
1217
1165
|
}
|
|
1218
1166
|
|
|
1219
1167
|
get channelType() {
|
|
1220
|
-
return this
|
|
1168
|
+
return this.#exchangeProvider.channelType;
|
|
1221
1169
|
}
|
|
1222
1170
|
|
|
1223
1171
|
/** Enrich cached data to get complete responses when data version filters were used. */
|