@matter/protocol 0.16.0-alpha.0-20251213-e83db3732 → 0.16.0-alpha.0-20251217-038f88085
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/LICENSE +1 -1
- package/dist/cjs/action/client/ClientInteraction.d.ts +12 -5
- package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/cjs/action/client/ClientInteraction.js +39 -15
- package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
- package/dist/cjs/action/client/ClientRead.d.ts +10 -0
- package/dist/cjs/action/client/ClientRead.d.ts.map +1 -0
- package/dist/cjs/action/client/ClientRead.js +22 -0
- package/dist/cjs/action/client/ClientRead.js.map +6 -0
- package/dist/cjs/action/client/ClientRequest.d.ts +20 -0
- package/dist/cjs/action/client/ClientRequest.d.ts.map +1 -0
- package/dist/cjs/action/client/ClientRequest.js +22 -0
- package/dist/cjs/action/client/ClientRequest.js.map +6 -0
- package/dist/cjs/action/client/ClientWrite.d.ts +10 -0
- package/dist/cjs/action/client/ClientWrite.d.ts.map +1 -0
- package/dist/cjs/action/client/ClientWrite.js +22 -0
- package/dist/cjs/action/client/ClientWrite.js.map +6 -0
- package/dist/cjs/action/client/QueuedClientInteraction.d.ts +49 -0
- package/dist/cjs/action/client/QueuedClientInteraction.d.ts.map +1 -0
- package/dist/cjs/action/client/QueuedClientInteraction.js +160 -0
- package/dist/cjs/action/client/QueuedClientInteraction.js.map +6 -0
- package/dist/cjs/action/client/index.d.ts +4 -0
- package/dist/cjs/action/client/index.d.ts.map +1 -1
- package/dist/cjs/action/client/index.js +4 -0
- package/dist/cjs/action/client/index.js.map +1 -1
- package/dist/cjs/action/client/subscription/ClientSubscribe.d.ts +2 -1
- package/dist/cjs/action/client/subscription/ClientSubscribe.d.ts.map +1 -1
- package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.d.ts.map +1 -1
- package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js +14 -3
- package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
- package/dist/cjs/action/client/subscription/SustainedSubscription.d.ts +1 -1
- package/dist/cjs/action/client/subscription/SustainedSubscription.d.ts.map +1 -1
- package/dist/cjs/action/client/subscription/SustainedSubscription.js +1 -4
- package/dist/cjs/action/client/subscription/SustainedSubscription.js.map +1 -1
- package/dist/cjs/action/request/Invoke.d.ts +7 -1
- package/dist/cjs/action/request/Invoke.d.ts.map +1 -1
- package/dist/cjs/action/request/Invoke.js +0 -3
- package/dist/cjs/action/request/Invoke.js.map +1 -1
- package/dist/cjs/action/request/Read.d.ts.map +1 -1
- package/dist/cjs/action/request/Read.js +3 -2
- package/dist/cjs/action/request/Read.js.map +1 -1
- package/dist/cjs/action/request/Specifier.d.ts +1 -1
- package/dist/cjs/action/request/Specifier.d.ts.map +1 -1
- package/dist/cjs/action/request/Specifier.js +3 -0
- package/dist/cjs/action/request/Specifier.js.map +1 -1
- package/dist/cjs/action/request/Write.d.ts +1 -0
- package/dist/cjs/action/request/Write.d.ts.map +1 -1
- package/dist/cjs/action/request/Write.js +10 -2
- package/dist/cjs/action/request/Write.js.map +1 -1
- package/dist/cjs/action/response/ReadResult.d.ts +1 -1
- package/dist/cjs/action/response/ReadResult.d.ts.map +1 -1
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +37 -8
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/cjs/cluster/client/index.d.ts +0 -3
- package/dist/cjs/cluster/client/index.d.ts.map +1 -1
- package/dist/cjs/cluster/client/index.js +0 -3
- package/dist/cjs/cluster/client/index.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +3 -2
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/SubscriptionClient.js +2 -1
- package/dist/cjs/interaction/SubscriptionClient.js.map +1 -1
- package/dist/cjs/interaction/index.d.ts +1 -1
- package/dist/cjs/interaction/index.d.ts.map +1 -1
- package/dist/cjs/interaction/index.js +1 -1
- package/dist/cjs/interaction/index.js.map +1 -1
- package/dist/cjs/peer/CommissioningError.d.ts +13 -0
- package/dist/cjs/peer/CommissioningError.d.ts.map +1 -0
- package/dist/cjs/peer/CommissioningError.js +32 -0
- package/dist/cjs/peer/CommissioningError.js.map +6 -0
- package/dist/cjs/peer/ControllerCommissioner.d.ts +2 -3
- package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +20 -13
- package/dist/cjs/peer/ControllerCommissioner.js.map +2 -2
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +7 -16
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.js +395 -178
- package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.d.ts +4 -0
- package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.js +6 -3
- package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
- package/dist/cjs/peer/InteractionQueue.d.ts +2 -2
- package/dist/cjs/peer/InteractionQueue.d.ts.map +1 -1
- package/dist/cjs/peer/InteractionQueue.js +1 -1
- package/dist/cjs/peer/InteractionQueue.js.map +1 -1
- package/dist/cjs/peer/PeerAddressStore.d.ts +0 -9
- package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
- package/dist/cjs/peer/PeerAddressStore.js.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts +0 -2
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +32 -18
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/peer/PhysicalDeviceProperties.js +1 -1
- package/dist/cjs/peer/PhysicalDeviceProperties.js.map +1 -1
- 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/DeviceCommissioner.d.ts.map +1 -1
- package/dist/cjs/protocol/DeviceCommissioner.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +2 -2
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeProvider.d.ts +13 -4
- package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeProvider.js +5 -3
- package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +5 -2
- package/dist/cjs/session/NodeSession.d.ts.map +1 -1
- package/dist/cjs/session/NodeSession.js +5 -4
- package/dist/cjs/session/NodeSession.js.map +1 -1
- package/dist/cjs/session/Session.d.ts +5 -3
- package/dist/cjs/session/Session.d.ts.map +1 -1
- package/dist/cjs/session/Session.js +8 -4
- package/dist/cjs/session/Session.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts +8 -0
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +16 -2
- package/dist/cjs/session/SessionManager.js.map +1 -1
- package/dist/esm/action/client/ClientInteraction.d.ts +12 -5
- package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/esm/action/client/ClientInteraction.js +42 -16
- package/dist/esm/action/client/ClientInteraction.js.map +1 -1
- package/dist/esm/action/client/ClientRead.d.ts +10 -0
- package/dist/esm/action/client/ClientRead.d.ts.map +1 -0
- package/dist/esm/action/client/ClientRead.js +6 -0
- package/dist/esm/action/client/ClientRead.js.map +6 -0
- package/dist/esm/action/client/ClientRequest.d.ts +20 -0
- package/dist/esm/action/client/ClientRequest.d.ts.map +1 -0
- package/dist/esm/action/client/ClientRequest.js +6 -0
- package/dist/esm/action/client/ClientRequest.js.map +6 -0
- package/dist/esm/action/client/ClientWrite.d.ts +10 -0
- package/dist/esm/action/client/ClientWrite.d.ts.map +1 -0
- package/dist/esm/action/client/ClientWrite.js +6 -0
- package/dist/esm/action/client/ClientWrite.js.map +6 -0
- package/dist/esm/action/client/QueuedClientInteraction.d.ts +49 -0
- package/dist/esm/action/client/QueuedClientInteraction.d.ts.map +1 -0
- package/dist/esm/action/client/QueuedClientInteraction.js +140 -0
- package/dist/esm/action/client/QueuedClientInteraction.js.map +6 -0
- package/dist/esm/action/client/index.d.ts +4 -0
- package/dist/esm/action/client/index.d.ts.map +1 -1
- package/dist/esm/action/client/index.js +4 -0
- package/dist/esm/action/client/index.js.map +1 -1
- package/dist/esm/action/client/subscription/ClientSubscribe.d.ts +2 -1
- package/dist/esm/action/client/subscription/ClientSubscribe.d.ts.map +1 -1
- package/dist/esm/action/client/subscription/ClientSubscriptionHandler.d.ts.map +1 -1
- package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js +14 -3
- package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
- package/dist/esm/action/client/subscription/SustainedSubscription.d.ts +1 -1
- package/dist/esm/action/client/subscription/SustainedSubscription.d.ts.map +1 -1
- package/dist/esm/action/client/subscription/SustainedSubscription.js +1 -4
- package/dist/esm/action/client/subscription/SustainedSubscription.js.map +1 -1
- package/dist/esm/action/request/Invoke.d.ts +7 -1
- package/dist/esm/action/request/Invoke.d.ts.map +1 -1
- package/dist/esm/action/request/Invoke.js +0 -3
- package/dist/esm/action/request/Invoke.js.map +1 -1
- package/dist/esm/action/request/Read.d.ts.map +1 -1
- package/dist/esm/action/request/Read.js +3 -2
- package/dist/esm/action/request/Read.js.map +1 -1
- package/dist/esm/action/request/Specifier.d.ts +1 -1
- package/dist/esm/action/request/Specifier.d.ts.map +1 -1
- package/dist/esm/action/request/Specifier.js +3 -0
- package/dist/esm/action/request/Specifier.js.map +1 -1
- package/dist/esm/action/request/Write.d.ts +1 -0
- package/dist/esm/action/request/Write.d.ts.map +1 -1
- package/dist/esm/action/request/Write.js +10 -2
- package/dist/esm/action/request/Write.js.map +1 -1
- package/dist/esm/action/response/ReadResult.d.ts +1 -1
- package/dist/esm/action/response/ReadResult.d.ts.map +1 -1
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts +37 -8
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/esm/cluster/client/index.d.ts +0 -3
- package/dist/esm/cluster/client/index.d.ts.map +1 -1
- package/dist/esm/cluster/client/index.js +0 -3
- package/dist/esm/cluster/client/index.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +4 -3
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -1
- package/dist/esm/interaction/SubscriptionClient.js +2 -1
- package/dist/esm/interaction/SubscriptionClient.js.map +1 -1
- package/dist/esm/interaction/index.d.ts +1 -1
- package/dist/esm/interaction/index.d.ts.map +1 -1
- package/dist/esm/interaction/index.js +1 -1
- package/dist/esm/peer/CommissioningError.d.ts +13 -0
- package/dist/esm/peer/CommissioningError.d.ts.map +1 -0
- package/dist/esm/peer/CommissioningError.js +12 -0
- package/dist/esm/peer/CommissioningError.js.map +6 -0
- package/dist/esm/peer/ControllerCommissioner.d.ts +2 -3
- package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +19 -13
- package/dist/esm/peer/ControllerCommissioner.js.map +2 -2
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts +7 -16
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.js +380 -162
- package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.d.ts +4 -0
- package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.js +4 -1
- package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
- package/dist/esm/peer/InteractionQueue.d.ts +2 -2
- package/dist/esm/peer/InteractionQueue.d.ts.map +1 -1
- package/dist/esm/peer/InteractionQueue.js +2 -2
- package/dist/esm/peer/InteractionQueue.js.map +1 -1
- package/dist/esm/peer/PeerAddressStore.d.ts +0 -9
- package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
- package/dist/esm/peer/PeerAddressStore.js.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts +0 -2
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +32 -18
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/peer/PhysicalDeviceProperties.js +1 -1
- package/dist/esm/peer/PhysicalDeviceProperties.js.map +1 -1
- 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/DeviceCommissioner.d.ts.map +1 -1
- package/dist/esm/protocol/DeviceCommissioner.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +2 -2
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.d.ts +13 -4
- package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.js +5 -3
- package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +5 -2
- package/dist/esm/session/NodeSession.d.ts.map +1 -1
- package/dist/esm/session/NodeSession.js +5 -4
- package/dist/esm/session/NodeSession.js.map +1 -1
- package/dist/esm/session/Session.d.ts +5 -3
- package/dist/esm/session/Session.d.ts.map +1 -1
- package/dist/esm/session/Session.js +8 -4
- package/dist/esm/session/Session.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts +8 -0
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +17 -2
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/package.json +6 -6
- package/src/action/client/ClientInteraction.ts +58 -19
- package/src/action/client/ClientRead.ts +10 -0
- package/src/action/client/ClientRequest.ts +20 -0
- package/src/action/client/ClientWrite.ts +10 -0
- package/src/action/client/QueuedClientInteraction.ts +91 -0
- package/src/action/client/index.ts +4 -0
- package/src/action/client/subscription/ClientSubscribe.ts +2 -1
- package/src/action/client/subscription/ClientSubscriptionHandler.ts +14 -3
- package/src/action/client/subscription/SustainedSubscription.ts +6 -9
- package/src/action/request/Invoke.ts +11 -4
- package/src/action/request/Read.ts +3 -2
- package/src/action/request/Specifier.ts +4 -1
- package/src/action/request/Write.ts +11 -2
- package/src/action/response/ReadResult.ts +1 -1
- package/src/cluster/client/ClusterClientTypes.ts +47 -7
- package/src/cluster/client/index.ts +0 -3
- package/src/interaction/InteractionMessenger.ts +5 -4
- package/src/interaction/SubscriptionClient.ts +2 -1
- package/src/interaction/index.ts +1 -1
- package/src/peer/CommissioningError.ts +13 -0
- package/src/peer/ControllerCommissioner.ts +21 -13
- package/src/peer/ControllerCommissioningFlow.ts +418 -186
- package/src/peer/ControllerDiscovery.ts +4 -1
- package/src/peer/InteractionQueue.ts +2 -2
- package/src/peer/PeerAddressStore.ts +0 -9
- package/src/peer/PeerSet.ts +56 -23
- package/src/peer/PhysicalDeviceProperties.ts +1 -1
- package/src/peer/index.ts +1 -0
- package/src/protocol/DeviceCommissioner.ts +0 -1
- package/src/protocol/ExchangeManager.ts +2 -2
- package/src/protocol/ExchangeProvider.ts +9 -7
- package/src/session/NodeSession.ts +5 -4
- package/src/session/Session.ts +8 -4
- package/src/session/SessionManager.ts +19 -2
- package/dist/cjs/cluster/client/AttributeClient.d.ts +0 -75
- package/dist/cjs/cluster/client/AttributeClient.d.ts.map +0 -1
- package/dist/cjs/cluster/client/AttributeClient.js +0 -209
- package/dist/cjs/cluster/client/AttributeClient.js.map +0 -6
- package/dist/cjs/cluster/client/ClusterClient.d.ts +0 -11
- package/dist/cjs/cluster/client/ClusterClient.d.ts.map +0 -1
- package/dist/cjs/cluster/client/ClusterClient.js +0 -335
- package/dist/cjs/cluster/client/ClusterClient.js.map +0 -6
- package/dist/cjs/cluster/client/EventClient.d.ts +0 -33
- package/dist/cjs/cluster/client/EventClient.d.ts.map +0 -1
- package/dist/cjs/cluster/client/EventClient.js +0 -89
- package/dist/cjs/cluster/client/EventClient.js.map +0 -6
- package/dist/cjs/interaction/InteractionClient.d.ts +0 -375
- package/dist/cjs/interaction/InteractionClient.d.ts.map +0 -1
- package/dist/cjs/interaction/InteractionClient.js +0 -1046
- package/dist/cjs/interaction/InteractionClient.js.map +0 -6
- package/dist/esm/cluster/client/AttributeClient.d.ts +0 -75
- package/dist/esm/cluster/client/AttributeClient.d.ts.map +0 -1
- package/dist/esm/cluster/client/AttributeClient.js +0 -189
- package/dist/esm/cluster/client/AttributeClient.js.map +0 -6
- package/dist/esm/cluster/client/ClusterClient.d.ts +0 -11
- package/dist/esm/cluster/client/ClusterClient.d.ts.map +0 -1
- package/dist/esm/cluster/client/ClusterClient.js +0 -320
- package/dist/esm/cluster/client/ClusterClient.js.map +0 -6
- package/dist/esm/cluster/client/EventClient.d.ts +0 -33
- package/dist/esm/cluster/client/EventClient.d.ts.map +0 -1
- package/dist/esm/cluster/client/EventClient.js +0 -69
- package/dist/esm/cluster/client/EventClient.js.map +0 -6
- package/dist/esm/interaction/InteractionClient.d.ts +0 -375
- package/dist/esm/interaction/InteractionClient.d.ts.map +0 -1
- package/dist/esm/interaction/InteractionClient.js +0 -1047
- package/dist/esm/interaction/InteractionClient.js.map +0 -6
- package/src/cluster/client/AttributeClient.ts +0 -230
- package/src/cluster/client/ClusterClient.ts +0 -433
- package/src/cluster/client/EventClient.ts +0 -99
- package/src/interaction/InteractionClient.ts +0 -1614
|
@@ -1,1047 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import { ReadScope } from "#action/client/ReadScope.js";
|
|
7
|
-
import { AccessControl } from "#clusters/access-control";
|
|
8
|
-
import { Mark } from "#common/Mark.js";
|
|
9
|
-
import {
|
|
10
|
-
Diagnostic,
|
|
11
|
-
Duration,
|
|
12
|
-
Environmental,
|
|
13
|
-
ImplementationError,
|
|
14
|
-
Logger,
|
|
15
|
-
MatterFlowError,
|
|
16
|
-
Seconds,
|
|
17
|
-
UnexpectedDataError,
|
|
18
|
-
isDeepEqual,
|
|
19
|
-
serialize
|
|
20
|
-
} from "#general";
|
|
21
|
-
import { Specification } from "#model";
|
|
22
|
-
import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
|
|
23
|
-
import { PeerSet } from "#peer/PeerSet.js";
|
|
24
|
-
import {
|
|
25
|
-
ArraySchema,
|
|
26
|
-
FabricIndex,
|
|
27
|
-
ObjectSchema,
|
|
28
|
-
StatusCode,
|
|
29
|
-
StatusResponseError,
|
|
30
|
-
TlvNoResponse,
|
|
31
|
-
resolveAttributeName,
|
|
32
|
-
resolveCommandName,
|
|
33
|
-
resolveEventName
|
|
34
|
-
} from "#types";
|
|
35
|
-
import { ReconnectableExchangeProvider } from "../protocol/ExchangeProvider.js";
|
|
36
|
-
import { InteractionClientMessenger } from "./InteractionMessenger.js";
|
|
37
|
-
import { Subscription } from "./Subscription.js";
|
|
38
|
-
import { SubscriptionClient } from "./SubscriptionClient.js";
|
|
39
|
-
const logger = Logger.get("InteractionClient");
|
|
40
|
-
const REQUEST_ALL = [{}];
|
|
41
|
-
const DEFAULT_TIMED_REQUEST_TIMEOUT = Seconds(10);
|
|
42
|
-
const DEFAULT_MINIMUM_RESPONSE_TIMEOUT_WITH_FAILSAFE = Seconds(30);
|
|
43
|
-
const AclClusterId = AccessControl.Complete.id;
|
|
44
|
-
const AclAttributeId = AccessControl.Complete.attributes.acl.id;
|
|
45
|
-
const AclExtensionAttributeId = AccessControl.Complete.attributes.extension.id;
|
|
46
|
-
function isAclOrExtensionPath(path) {
|
|
47
|
-
const { clusterId, attributeId } = path;
|
|
48
|
-
return clusterId === AclClusterId && (attributeId === AclAttributeId || attributeId === AclExtensionAttributeId);
|
|
49
|
-
}
|
|
50
|
-
class InteractionClientProvider {
|
|
51
|
-
#peers;
|
|
52
|
-
#clients = new PeerAddressMap();
|
|
53
|
-
#subscriptionClient = new SubscriptionClient();
|
|
54
|
-
constructor(peers) {
|
|
55
|
-
this.#peers = peers;
|
|
56
|
-
this.#peers.deleted.on((peer) => this.#onPeerLoss(peer.address));
|
|
57
|
-
this.#peers.disconnected.on((peer) => this.#onPeerLoss(peer.address));
|
|
58
|
-
}
|
|
59
|
-
static [Environmental.create](env) {
|
|
60
|
-
const instance = new InteractionClientProvider(env.get(PeerSet));
|
|
61
|
-
env.set(InteractionClientProvider, instance);
|
|
62
|
-
return instance;
|
|
63
|
-
}
|
|
64
|
-
get peers() {
|
|
65
|
-
return this.#peers;
|
|
66
|
-
}
|
|
67
|
-
get subscriptionClient() {
|
|
68
|
-
return this.#subscriptionClient;
|
|
69
|
-
}
|
|
70
|
-
async connect(address, options) {
|
|
71
|
-
await this.#peers.connect(address, options);
|
|
72
|
-
return this.getInteractionClient(address, options);
|
|
73
|
-
}
|
|
74
|
-
async interactionClientFor(session) {
|
|
75
|
-
const exchangeProvider = await this.#peers.exchangeProviderFor(session);
|
|
76
|
-
return new InteractionClient(
|
|
77
|
-
exchangeProvider,
|
|
78
|
-
this.#subscriptionClient,
|
|
79
|
-
void 0,
|
|
80
|
-
this.#peers.interactionQueue
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
async getInteractionClient(address, options = {}) {
|
|
84
|
-
let client = this.#clients.get(address);
|
|
85
|
-
if (client !== void 0) {
|
|
86
|
-
return client;
|
|
87
|
-
}
|
|
88
|
-
const isGroupAddress = PeerAddress.isGroup(address);
|
|
89
|
-
const nodeStore = isGroupAddress ? void 0 : this.#peers.get(address)?.descriptor.dataStore;
|
|
90
|
-
await nodeStore?.construction;
|
|
91
|
-
const exchangeProvider = await this.#peers.exchangeProviderFor(address, options);
|
|
92
|
-
client = new InteractionClient(
|
|
93
|
-
exchangeProvider,
|
|
94
|
-
this.#subscriptionClient,
|
|
95
|
-
address,
|
|
96
|
-
this.#peers.interactionQueue,
|
|
97
|
-
nodeStore
|
|
98
|
-
);
|
|
99
|
-
this.#clients.set(address, client);
|
|
100
|
-
return client;
|
|
101
|
-
}
|
|
102
|
-
#onPeerLoss(address) {
|
|
103
|
-
const client = this.#clients.get(address);
|
|
104
|
-
if (client !== void 0) {
|
|
105
|
-
client.close();
|
|
106
|
-
this.#clients.delete(address);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
class InteractionClient {
|
|
111
|
-
#exchangeProvider;
|
|
112
|
-
#nodeStore;
|
|
113
|
-
#ownSubscriptionIds = /* @__PURE__ */ new Set();
|
|
114
|
-
#queue;
|
|
115
|
-
#address;
|
|
116
|
-
isGroupAddress;
|
|
117
|
-
// TODO - SubscriptionClient is used by CommissioningController but not ClientNode. However InteractionClient *is*
|
|
118
|
-
// used by ClientNode to perform commissioning, during which time SubscriptionClient is unnecessary. So this should
|
|
119
|
-
// be set after commissioning
|
|
120
|
-
//
|
|
121
|
-
// If we remove CommissioningController then this entire class goes away; if we first move commissioning to
|
|
122
|
-
// ClientInteraction then this should become required
|
|
123
|
-
#subscriptionClient;
|
|
124
|
-
constructor(exchangeProvider, subscriptionClient, address, queue, nodeStore) {
|
|
125
|
-
this.#exchangeProvider = exchangeProvider;
|
|
126
|
-
this.#nodeStore = nodeStore;
|
|
127
|
-
this.#subscriptionClient = subscriptionClient;
|
|
128
|
-
this.#queue = queue;
|
|
129
|
-
this.#address = address;
|
|
130
|
-
this.isGroupAddress = address !== void 0 ? PeerAddress.isGroup(address) : false;
|
|
131
|
-
}
|
|
132
|
-
get address() {
|
|
133
|
-
if (this.#address === void 0) {
|
|
134
|
-
throw new ImplementationError("This InteractionClient is not bound to a specific peer.");
|
|
135
|
-
}
|
|
136
|
-
return this.#address;
|
|
137
|
-
}
|
|
138
|
-
get isReconnectable() {
|
|
139
|
-
return this.#exchangeProvider instanceof ReconnectableExchangeProvider;
|
|
140
|
-
}
|
|
141
|
-
get channelUpdated() {
|
|
142
|
-
if (this.#exchangeProvider instanceof ReconnectableExchangeProvider) {
|
|
143
|
-
return this.#exchangeProvider.channelUpdated;
|
|
144
|
-
}
|
|
145
|
-
throw new ImplementationError("ExchangeProvider does not support channelUpdated");
|
|
146
|
-
}
|
|
147
|
-
/** Calculates the current maximum response time for a message use in additional logic like timers. */
|
|
148
|
-
maximumPeerResponseTime(expectedProcessingTime) {
|
|
149
|
-
return this.#exchangeProvider.maximumPeerResponseTime(expectedProcessingTime);
|
|
150
|
-
}
|
|
151
|
-
removeSubscription(subscriptionId) {
|
|
152
|
-
this.#ownSubscriptionIds.delete(subscriptionId);
|
|
153
|
-
this.#subscriptionClient?.delete(subscriptionId);
|
|
154
|
-
}
|
|
155
|
-
async getAllAttributes(options = {}) {
|
|
156
|
-
return (await this.getMultipleAttributesAndEvents({
|
|
157
|
-
attributes: REQUEST_ALL,
|
|
158
|
-
...options
|
|
159
|
-
})).attributeReports;
|
|
160
|
-
}
|
|
161
|
-
async getAllEvents(options = {}) {
|
|
162
|
-
return (await this.getMultipleAttributesAndEvents({
|
|
163
|
-
events: REQUEST_ALL,
|
|
164
|
-
...options
|
|
165
|
-
})).eventReports;
|
|
166
|
-
}
|
|
167
|
-
async getAllAttributesAndEvents(options = {}) {
|
|
168
|
-
return this.getMultipleAttributesAndEvents({
|
|
169
|
-
attributes: REQUEST_ALL,
|
|
170
|
-
events: REQUEST_ALL,
|
|
171
|
-
...options
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
async getMultipleAttributes(options = {}) {
|
|
175
|
-
return (await this.getMultipleAttributesAndEvents(options)).attributeReports;
|
|
176
|
-
}
|
|
177
|
-
async getMultipleAttributesAndStatus(options = {}) {
|
|
178
|
-
const { attributeReports, attributeStatus } = await this.getMultipleAttributesAndEvents(options);
|
|
179
|
-
return { attributeData: attributeReports, attributeStatus };
|
|
180
|
-
}
|
|
181
|
-
async getMultipleEvents(options = {}) {
|
|
182
|
-
return (await this.getMultipleAttributesAndEvents(options)).eventReports;
|
|
183
|
-
}
|
|
184
|
-
async getMultipleEventsAndStatus(options = {}) {
|
|
185
|
-
const { eventReports, eventStatus } = await this.getMultipleAttributesAndEvents(options);
|
|
186
|
-
return { eventData: eventReports, eventStatus };
|
|
187
|
-
}
|
|
188
|
-
async getMultipleAttributesAndEvents(options = {}) {
|
|
189
|
-
if (this.isGroupAddress) {
|
|
190
|
-
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
191
|
-
}
|
|
192
|
-
const {
|
|
193
|
-
attributes: attributeRequests,
|
|
194
|
-
dataVersionFilters,
|
|
195
|
-
executeQueued,
|
|
196
|
-
events: eventRequests,
|
|
197
|
-
enrichCachedAttributeData,
|
|
198
|
-
eventFilters,
|
|
199
|
-
isFabricFiltered = true,
|
|
200
|
-
attributeChangeListener
|
|
201
|
-
} = options;
|
|
202
|
-
if (attributeRequests === void 0 && eventRequests === void 0) {
|
|
203
|
-
throw new ImplementationError("When reading attributes and events, at least one must be specified.");
|
|
204
|
-
}
|
|
205
|
-
const readPathsCount = (attributeRequests?.length ?? 0) + (eventRequests?.length ?? 0);
|
|
206
|
-
if (readPathsCount > 9) {
|
|
207
|
-
logger.debug(
|
|
208
|
-
"Read interactions with more then 9 paths might be not allowed by the device. Consider splitting then into several read requests."
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
const result = await this.withMessenger(async (messenger) => {
|
|
212
|
-
return await this.processReadRequest(
|
|
213
|
-
messenger,
|
|
214
|
-
{
|
|
215
|
-
attributeRequests,
|
|
216
|
-
dataVersionFilters: dataVersionFilters?.map(({ endpointId, clusterId, dataVersion }) => ({
|
|
217
|
-
path: { endpointId, clusterId },
|
|
218
|
-
dataVersion
|
|
219
|
-
})),
|
|
220
|
-
eventRequests,
|
|
221
|
-
eventFilters,
|
|
222
|
-
isFabricFiltered,
|
|
223
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION
|
|
224
|
-
},
|
|
225
|
-
attributeChangeListener
|
|
226
|
-
);
|
|
227
|
-
}, executeQueued);
|
|
228
|
-
if (dataVersionFilters !== void 0 && dataVersionFilters.length > 0 && enrichCachedAttributeData) {
|
|
229
|
-
this.#enrichCachedAttributeData(result.attributeReports, dataVersionFilters);
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
async getAttribute(options) {
|
|
234
|
-
const { requestFromRemote } = options;
|
|
235
|
-
const response = await this.getAttributeWithVersion({
|
|
236
|
-
...options,
|
|
237
|
-
requestFromRemote
|
|
238
|
-
});
|
|
239
|
-
return response?.value;
|
|
240
|
-
}
|
|
241
|
-
getStoredAttribute(options) {
|
|
242
|
-
return this.getStoredAttributeWithVersion(options)?.value;
|
|
243
|
-
}
|
|
244
|
-
getStoredAttributeWithVersion(options) {
|
|
245
|
-
if (this.isGroupAddress) {
|
|
246
|
-
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
247
|
-
}
|
|
248
|
-
const { endpointId, clusterId, attribute } = options;
|
|
249
|
-
const { id: attributeId } = attribute;
|
|
250
|
-
if (this.#nodeStore !== void 0) {
|
|
251
|
-
const { value, version } = this.#nodeStore.retrieveAttribute(endpointId, clusterId, attributeId) ?? {};
|
|
252
|
-
if (value !== void 0 && version !== void 0) {
|
|
253
|
-
return { value, version };
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return void 0;
|
|
257
|
-
}
|
|
258
|
-
async getAttributeWithVersion(options) {
|
|
259
|
-
if (this.isGroupAddress) {
|
|
260
|
-
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
261
|
-
}
|
|
262
|
-
const {
|
|
263
|
-
endpointId,
|
|
264
|
-
clusterId,
|
|
265
|
-
attribute,
|
|
266
|
-
requestFromRemote,
|
|
267
|
-
isFabricFiltered,
|
|
268
|
-
executeQueued,
|
|
269
|
-
attributeChangeListener
|
|
270
|
-
} = options;
|
|
271
|
-
const { id: attributeId } = attribute;
|
|
272
|
-
if (this.#nodeStore !== void 0) {
|
|
273
|
-
if (!requestFromRemote) {
|
|
274
|
-
const { value, version } = this.#nodeStore.retrieveAttribute(endpointId, clusterId, attributeId) ?? {};
|
|
275
|
-
if (value !== void 0 && version !== void 0) {
|
|
276
|
-
return { value, version };
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (requestFromRemote === false) {
|
|
280
|
-
return void 0;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
const { attributeReports } = await this.getMultipleAttributesAndEvents({
|
|
284
|
-
attributes: [{ endpointId, clusterId, attributeId }],
|
|
285
|
-
isFabricFiltered,
|
|
286
|
-
executeQueued,
|
|
287
|
-
attributeChangeListener
|
|
288
|
-
});
|
|
289
|
-
if (attributeReports.length === 0) {
|
|
290
|
-
return void 0;
|
|
291
|
-
}
|
|
292
|
-
if (attributeReports.length > 1) {
|
|
293
|
-
throw new UnexpectedDataError("Unexpected response with more then one attribute");
|
|
294
|
-
}
|
|
295
|
-
return { value: attributeReports[0].value, version: attributeReports[0].version };
|
|
296
|
-
}
|
|
297
|
-
async getEvent(options) {
|
|
298
|
-
const { endpointId, clusterId, event, minimumEventNumber, isFabricFiltered = true, executeQueued } = options;
|
|
299
|
-
const { id: eventId } = event;
|
|
300
|
-
const response = await this.getMultipleAttributesAndEvents({
|
|
301
|
-
events: [{ endpointId, clusterId, eventId }],
|
|
302
|
-
eventFilters: minimumEventNumber !== void 0 ? [{ eventMin: minimumEventNumber }] : void 0,
|
|
303
|
-
isFabricFiltered,
|
|
304
|
-
executeQueued
|
|
305
|
-
});
|
|
306
|
-
return response?.eventReports[0]?.events;
|
|
307
|
-
}
|
|
308
|
-
async processReadRequest(messenger, request, attributeChangeListener) {
|
|
309
|
-
const { attributeRequests, eventRequests, dataVersionFilters, eventFilters, isFabricFiltered } = request;
|
|
310
|
-
logger.debug(() => [
|
|
311
|
-
"Read",
|
|
312
|
-
Mark.OUTBOUND,
|
|
313
|
-
messenger.exchange.via,
|
|
314
|
-
Diagnostic.dict({
|
|
315
|
-
attributes: attributeRequests?.length ? attributeRequests?.map((path) => resolveAttributeName(path)).join(", ") : void 0,
|
|
316
|
-
events: eventRequests?.length ? eventRequests?.map((path) => resolveEventName(path)).join(", ") : void 0,
|
|
317
|
-
dataVersionFilters: dataVersionFilters?.length ? dataVersionFilters.map(
|
|
318
|
-
({ path: { endpointId, clusterId }, dataVersion }) => `${endpointId}/${clusterId}=${dataVersion}`
|
|
319
|
-
).join(", ") : void 0,
|
|
320
|
-
eventFilters: eventFilters?.length ? eventFilters.map(({ nodeId, eventMin }) => `${nodeId}=${eventMin}`).join(", ") : void 0,
|
|
321
|
-
fabricFiltered: isFabricFiltered
|
|
322
|
-
})
|
|
323
|
-
]);
|
|
324
|
-
await messenger.sendReadRequest(request);
|
|
325
|
-
const scope = ReadScope(request);
|
|
326
|
-
const response = await messenger.readAggregateDataReport(
|
|
327
|
-
(chunk) => this.processAttributeUpdates(scope, chunk, attributeChangeListener)
|
|
328
|
-
);
|
|
329
|
-
const { attributeReports, attributeStatus, eventReports, eventStatus } = response;
|
|
330
|
-
if (attributeReports.length || eventReports.length || attributeStatus?.length || eventStatus?.length) {
|
|
331
|
-
logger.debug(() => [
|
|
332
|
-
"Read",
|
|
333
|
-
Mark.INBOUND,
|
|
334
|
-
messenger.exchange.via,
|
|
335
|
-
Diagnostic.dict({
|
|
336
|
-
attributes: attributeReports.length ? attributeReports.map(({ path, value }) => `${resolveAttributeName(path)}=${serialize(value)}`).join(", ") : void 0,
|
|
337
|
-
events: eventReports.length ? eventReports.map(({ path }) => resolveEventName(path)).join(", ") : void 0,
|
|
338
|
-
attributeStatus: attributeStatus?.length ? attributeStatus.map(({ path }) => resolveAttributeName(path)).join(", ") : void 0,
|
|
339
|
-
eventStatus: eventStatus?.length ? eventStatus.map(({ path }) => resolveEventName(path)).join(", ") : void 0,
|
|
340
|
-
fabricFiltered: isFabricFiltered
|
|
341
|
-
})
|
|
342
|
-
]);
|
|
343
|
-
} else {
|
|
344
|
-
logger.debug("Read", Mark.INBOUND, messenger.exchange.via, "empty response");
|
|
345
|
-
}
|
|
346
|
-
return response;
|
|
347
|
-
}
|
|
348
|
-
async setAttribute(options) {
|
|
349
|
-
const { attributeData, asTimedRequest, timedRequestTimeout, suppressResponse, executeQueued, chunkLists } = options;
|
|
350
|
-
const { endpointId, clusterId, attribute, value, dataVersion } = attributeData;
|
|
351
|
-
const response = await this.setMultipleAttributes({
|
|
352
|
-
attributes: [{ endpointId, clusterId, attribute, value, dataVersion }],
|
|
353
|
-
asTimedRequest,
|
|
354
|
-
timedRequestTimeout,
|
|
355
|
-
suppressResponse,
|
|
356
|
-
executeQueued,
|
|
357
|
-
chunkLists
|
|
358
|
-
});
|
|
359
|
-
if (response.length) {
|
|
360
|
-
const {
|
|
361
|
-
path: { endpointId: endpointId2, clusterId: clusterId2, attributeId },
|
|
362
|
-
status
|
|
363
|
-
} = response[0];
|
|
364
|
-
if (status !== void 0 && status !== StatusCode.Success) {
|
|
365
|
-
throw new StatusResponseError(
|
|
366
|
-
`Error setting attribute ${endpointId2}/${clusterId2}/${attributeId}`,
|
|
367
|
-
status
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
async setMultipleAttributes(options) {
|
|
373
|
-
const { executeQueued } = options;
|
|
374
|
-
const {
|
|
375
|
-
attributes,
|
|
376
|
-
asTimedRequest,
|
|
377
|
-
timedRequestTimeout = DEFAULT_TIMED_REQUEST_TIMEOUT,
|
|
378
|
-
suppressResponse = this.isGroupAddress,
|
|
379
|
-
chunkLists = true
|
|
380
|
-
// Should be true currently to stay in sync with chip sdk
|
|
381
|
-
} = options;
|
|
382
|
-
if (this.isGroupAddress) {
|
|
383
|
-
if (!suppressResponse) {
|
|
384
|
-
throw new ImplementationError("Writing attributes on a group address can not return a response.");
|
|
385
|
-
}
|
|
386
|
-
if (attributes.some(
|
|
387
|
-
({ endpointId, clusterId, attribute }) => endpointId !== void 0 || clusterId === void 0 || attribute.id === void 0
|
|
388
|
-
)) {
|
|
389
|
-
throw new ImplementationError("Not all attribute write paths are valid for group address writes.");
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
const writeRequests = attributes.flatMap(
|
|
393
|
-
({ endpointId, clusterId, attribute: { id, schema }, value, dataVersion }) => {
|
|
394
|
-
if (chunkLists && Array.isArray(value) && schema instanceof ArraySchema && // As implemented for Matter 1.4.2 in https://github.com/project-chip/connectedhomeip/pull/38263
|
|
395
|
-
// Acl writes will no longer be chunked by default, all others still
|
|
396
|
-
// Will be streamlined later ... see https://github.com/project-chip/connectedhomeip/issues/38270
|
|
397
|
-
!isAclOrExtensionPath({ clusterId, attributeId: id })) {
|
|
398
|
-
return schema.encodeAsChunkedArray(value, { forWriteInteraction: true }).map(({ element: data, listIndex }) => ({
|
|
399
|
-
path: { endpointId, clusterId, attributeId: id, listIndex },
|
|
400
|
-
data,
|
|
401
|
-
dataVersion
|
|
402
|
-
}));
|
|
403
|
-
}
|
|
404
|
-
return [
|
|
405
|
-
{
|
|
406
|
-
path: { endpointId, clusterId, attributeId: id },
|
|
407
|
-
data: schema.encodeTlv(value, { forWriteInteraction: true }),
|
|
408
|
-
dataVersion
|
|
409
|
-
}
|
|
410
|
-
];
|
|
411
|
-
}
|
|
412
|
-
);
|
|
413
|
-
const timedRequest = attributes.some(({ attribute: { timed } }) => timed) || asTimedRequest === true || options.timedRequestTimeout !== void 0;
|
|
414
|
-
if (this.isGroupAddress && timedRequest) {
|
|
415
|
-
throw new ImplementationError("Timed requests are not supported for group address writes.");
|
|
416
|
-
}
|
|
417
|
-
const response = await this.withMessenger(
|
|
418
|
-
async (messenger) => {
|
|
419
|
-
if (timedRequest) {
|
|
420
|
-
await messenger.sendTimedRequest(timedRequestTimeout);
|
|
421
|
-
}
|
|
422
|
-
logger.debug(() => [
|
|
423
|
-
"Write",
|
|
424
|
-
Mark.OUTBOUND,
|
|
425
|
-
messenger.exchange.via,
|
|
426
|
-
Diagnostic.dict({
|
|
427
|
-
attributes: attributes.map(
|
|
428
|
-
({ endpointId, clusterId, attribute: { id }, value, dataVersion }) => `${resolveAttributeName({ endpointId, clusterId, attributeId: id })} = ${Diagnostic.json(
|
|
429
|
-
value
|
|
430
|
-
)} (version=${dataVersion})`
|
|
431
|
-
).join(", ")
|
|
432
|
-
})
|
|
433
|
-
]);
|
|
434
|
-
return await messenger.sendWriteCommand({
|
|
435
|
-
suppressResponse,
|
|
436
|
-
timedRequest,
|
|
437
|
-
writeRequests,
|
|
438
|
-
moreChunkedMessages: false,
|
|
439
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION
|
|
440
|
-
});
|
|
441
|
-
},
|
|
442
|
-
executeQueued
|
|
443
|
-
);
|
|
444
|
-
if (response === void 0) {
|
|
445
|
-
if (!suppressResponse) {
|
|
446
|
-
throw new MatterFlowError(`No response received from write interaction but expected.`);
|
|
447
|
-
}
|
|
448
|
-
return [];
|
|
449
|
-
}
|
|
450
|
-
return response.writeResponses.flatMap(({ status: { status, clusterStatus }, path: { nodeId, endpointId, clusterId, attributeId } }) => {
|
|
451
|
-
return {
|
|
452
|
-
path: { nodeId, endpointId, clusterId, attributeId },
|
|
453
|
-
status: status ?? clusterStatus ?? StatusCode.Failure
|
|
454
|
-
};
|
|
455
|
-
}).filter(({ status }) => status !== StatusCode.Success);
|
|
456
|
-
}
|
|
457
|
-
async subscribeAttribute(options) {
|
|
458
|
-
if (this.isGroupAddress) {
|
|
459
|
-
throw new ImplementationError("Subscribing to attributes on a group address is not supported.");
|
|
460
|
-
}
|
|
461
|
-
const {
|
|
462
|
-
endpointId,
|
|
463
|
-
clusterId,
|
|
464
|
-
attribute,
|
|
465
|
-
minIntervalFloorSeconds,
|
|
466
|
-
maxIntervalCeilingSeconds,
|
|
467
|
-
isFabricFiltered = true,
|
|
468
|
-
listener,
|
|
469
|
-
knownDataVersion,
|
|
470
|
-
keepSubscriptions = true,
|
|
471
|
-
updateTimeoutHandler,
|
|
472
|
-
updateReceived,
|
|
473
|
-
executeQueued
|
|
474
|
-
} = options;
|
|
475
|
-
const { id: attributeId } = attribute;
|
|
476
|
-
if (!keepSubscriptions) {
|
|
477
|
-
for (const subscriptionId2 of this.#ownSubscriptionIds) {
|
|
478
|
-
logger.debug(
|
|
479
|
-
`Removing subscription ${Subscription.idStrOf(subscriptionId2)} from InteractionClient because new subscription replaces it`
|
|
480
|
-
);
|
|
481
|
-
this.removeSubscription(subscriptionId2);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
const request = {
|
|
485
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION,
|
|
486
|
-
attributeRequests: [{ endpointId, clusterId, attributeId }],
|
|
487
|
-
dataVersionFilters: knownDataVersion !== void 0 ? [{ path: { endpointId, clusterId }, dataVersion: knownDataVersion }] : void 0,
|
|
488
|
-
keepSubscriptions,
|
|
489
|
-
minIntervalFloorSeconds,
|
|
490
|
-
maxIntervalCeilingSeconds,
|
|
491
|
-
isFabricFiltered
|
|
492
|
-
};
|
|
493
|
-
const scope = ReadScope(request);
|
|
494
|
-
const {
|
|
495
|
-
subscribeResponse: { subscriptionId, maxInterval },
|
|
496
|
-
report,
|
|
497
|
-
maximumPeerResponseTime
|
|
498
|
-
} = await this.withMessenger(async (messenger) => {
|
|
499
|
-
logger.debug(() => [
|
|
500
|
-
"Subscribe",
|
|
501
|
-
Mark.OUTBOUND,
|
|
502
|
-
messenger.exchange.via,
|
|
503
|
-
Diagnostic.dict({
|
|
504
|
-
attributes: resolveAttributeName({ endpointId, clusterId, attributeId }),
|
|
505
|
-
dataVersionFilter: knownDataVersion,
|
|
506
|
-
fabricFiltered: isFabricFiltered,
|
|
507
|
-
minInterval: Duration.format(Seconds(minIntervalFloorSeconds)),
|
|
508
|
-
maxInterval: Duration.format(Seconds(maxIntervalCeilingSeconds))
|
|
509
|
-
})
|
|
510
|
-
]);
|
|
511
|
-
await messenger.sendSubscribeRequest(request);
|
|
512
|
-
const { subscribeResponse, report: report2 } = await messenger.readAggregateSubscribeResponse();
|
|
513
|
-
return {
|
|
514
|
-
subscribeResponse,
|
|
515
|
-
report: report2,
|
|
516
|
-
maximumPeerResponseTime: this.maximumPeerResponseTime()
|
|
517
|
-
};
|
|
518
|
-
}, executeQueued);
|
|
519
|
-
const subscriptionListener = async (dataReport) => {
|
|
520
|
-
const { attributeReports } = dataReport;
|
|
521
|
-
if (attributeReports.length === 0) {
|
|
522
|
-
throw new MatterFlowError("Subscription result reporting undefined/no value not specified");
|
|
523
|
-
}
|
|
524
|
-
if (attributeReports.length > 1) {
|
|
525
|
-
throw new UnexpectedDataError("Unexpected response with more then one attribute");
|
|
526
|
-
}
|
|
527
|
-
const { value, version } = attributeReports[0];
|
|
528
|
-
if (value === void 0)
|
|
529
|
-
throw new MatterFlowError("Subscription result reporting undefined value not specified.");
|
|
530
|
-
await this.#nodeStore?.persistAttributes(attributeReports, scope);
|
|
531
|
-
listener?.(value, version);
|
|
532
|
-
updateReceived?.();
|
|
533
|
-
};
|
|
534
|
-
await this.#registerSubscription(
|
|
535
|
-
{
|
|
536
|
-
id: subscriptionId,
|
|
537
|
-
maximumPeerResponseTime,
|
|
538
|
-
maxInterval: Seconds(maxInterval),
|
|
539
|
-
onData: subscriptionListener,
|
|
540
|
-
onTimeout: updateTimeoutHandler
|
|
541
|
-
},
|
|
542
|
-
report
|
|
543
|
-
);
|
|
544
|
-
return { maxInterval };
|
|
545
|
-
}
|
|
546
|
-
async #registerSubscription(subscription, initialReport) {
|
|
547
|
-
this.#ownSubscriptionIds.add(subscription.id);
|
|
548
|
-
this.#subscriptionClient?.add(subscription);
|
|
549
|
-
await subscription.onData(initialReport);
|
|
550
|
-
}
|
|
551
|
-
async subscribeEvent(options) {
|
|
552
|
-
if (this.isGroupAddress) {
|
|
553
|
-
throw new ImplementationError("Subscribing to events on a group address is not supported.");
|
|
554
|
-
}
|
|
555
|
-
const {
|
|
556
|
-
endpointId,
|
|
557
|
-
clusterId,
|
|
558
|
-
event,
|
|
559
|
-
minIntervalFloor,
|
|
560
|
-
maxIntervalCeiling,
|
|
561
|
-
isUrgent,
|
|
562
|
-
minimumEventNumber,
|
|
563
|
-
isFabricFiltered = true,
|
|
564
|
-
listener,
|
|
565
|
-
updateTimeoutHandler,
|
|
566
|
-
updateReceived,
|
|
567
|
-
executeQueued
|
|
568
|
-
} = options;
|
|
569
|
-
const { id: eventId } = event;
|
|
570
|
-
const {
|
|
571
|
-
report,
|
|
572
|
-
subscribeResponse: { subscriptionId, maxInterval },
|
|
573
|
-
maximumPeerResponseTime
|
|
574
|
-
} = await this.withMessenger(async (messenger) => {
|
|
575
|
-
logger.debug(() => [
|
|
576
|
-
"Subscribe",
|
|
577
|
-
Mark.OUTBOUND,
|
|
578
|
-
messenger.exchange.via,
|
|
579
|
-
Diagnostic.dict({
|
|
580
|
-
events: resolveEventName({ endpointId, clusterId, eventId }),
|
|
581
|
-
fabricFiltered: isFabricFiltered,
|
|
582
|
-
minInterval: Duration.format(minIntervalFloor),
|
|
583
|
-
maxInterval: Duration.format(maxIntervalCeiling)
|
|
584
|
-
})
|
|
585
|
-
]);
|
|
586
|
-
await messenger.sendSubscribeRequest({
|
|
587
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION,
|
|
588
|
-
eventRequests: [{ endpointId, clusterId, eventId, isUrgent }],
|
|
589
|
-
eventFilters: minimumEventNumber !== void 0 ? [{ eventMin: minimumEventNumber }] : void 0,
|
|
590
|
-
keepSubscriptions: true,
|
|
591
|
-
minIntervalFloorSeconds: Seconds.of(minIntervalFloor),
|
|
592
|
-
maxIntervalCeilingSeconds: Seconds.of(maxIntervalCeiling),
|
|
593
|
-
isFabricFiltered
|
|
594
|
-
});
|
|
595
|
-
const { subscribeResponse, report: report2 } = await messenger.readAggregateSubscribeResponse();
|
|
596
|
-
return {
|
|
597
|
-
subscribeResponse,
|
|
598
|
-
report: report2,
|
|
599
|
-
maximumPeerResponseTime: this.maximumPeerResponseTime()
|
|
600
|
-
};
|
|
601
|
-
}, executeQueued);
|
|
602
|
-
const subscriptionListener = (dataReport) => {
|
|
603
|
-
const { eventReports } = dataReport;
|
|
604
|
-
if (eventReports.length === 0) {
|
|
605
|
-
throw new MatterFlowError("Received empty subscription result value.");
|
|
606
|
-
}
|
|
607
|
-
if (eventReports.length > 1) {
|
|
608
|
-
throw new UnexpectedDataError("Unexpected response with more then one attribute.");
|
|
609
|
-
}
|
|
610
|
-
const { events } = eventReports[0];
|
|
611
|
-
if (events === void 0)
|
|
612
|
-
throw new MatterFlowError("Subscription result reporting undefined value not specified.");
|
|
613
|
-
events.forEach((event2) => listener?.(event2));
|
|
614
|
-
updateReceived?.();
|
|
615
|
-
};
|
|
616
|
-
await this.#registerSubscription(
|
|
617
|
-
{
|
|
618
|
-
id: subscriptionId,
|
|
619
|
-
maximumPeerResponseTime,
|
|
620
|
-
maxInterval: Seconds(maxInterval),
|
|
621
|
-
onData: subscriptionListener,
|
|
622
|
-
onTimeout: updateTimeoutHandler
|
|
623
|
-
},
|
|
624
|
-
report
|
|
625
|
-
);
|
|
626
|
-
return { maxInterval };
|
|
627
|
-
}
|
|
628
|
-
async subscribeAllAttributesAndEvents(options) {
|
|
629
|
-
const { isUrgent } = options;
|
|
630
|
-
return this.subscribeMultipleAttributesAndEvents({
|
|
631
|
-
...options,
|
|
632
|
-
attributes: REQUEST_ALL,
|
|
633
|
-
events: [{ isUrgent }]
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
async subscribeMultipleAttributesAndEvents(options) {
|
|
637
|
-
if (this.isGroupAddress) {
|
|
638
|
-
throw new ImplementationError("Subscribing to attributes or events on a group address is not supported.");
|
|
639
|
-
}
|
|
640
|
-
const {
|
|
641
|
-
attributes: attributeRequests = [],
|
|
642
|
-
events: eventRequests = [],
|
|
643
|
-
executeQueued,
|
|
644
|
-
minIntervalFloorSeconds,
|
|
645
|
-
maxIntervalCeilingSeconds,
|
|
646
|
-
keepSubscriptions = true,
|
|
647
|
-
isFabricFiltered = true,
|
|
648
|
-
attributeListener,
|
|
649
|
-
eventListener,
|
|
650
|
-
eventFilters,
|
|
651
|
-
dataVersionFilters,
|
|
652
|
-
updateTimeoutHandler,
|
|
653
|
-
updateReceived,
|
|
654
|
-
enrichCachedAttributeData
|
|
655
|
-
} = options;
|
|
656
|
-
const subscriptionPathsCount = (attributeRequests?.length ?? 0) + (eventRequests?.length ?? 0);
|
|
657
|
-
if (subscriptionPathsCount > 3) {
|
|
658
|
-
logger.debug("Subscribe interactions with more then 3 paths might be not allowed by the device.");
|
|
659
|
-
}
|
|
660
|
-
if (!keepSubscriptions) {
|
|
661
|
-
for (const subscriptionId2 of this.#ownSubscriptionIds) {
|
|
662
|
-
logger.debug(
|
|
663
|
-
`Removing subscription with ID ${Subscription.idStrOf(subscriptionId2)} from InteractionClient because new subscription replaces it`
|
|
664
|
-
);
|
|
665
|
-
this.removeSubscription(subscriptionId2);
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
const request = {
|
|
669
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION,
|
|
670
|
-
attributeRequests,
|
|
671
|
-
eventRequests,
|
|
672
|
-
keepSubscriptions,
|
|
673
|
-
minIntervalFloorSeconds,
|
|
674
|
-
maxIntervalCeilingSeconds,
|
|
675
|
-
isFabricFiltered,
|
|
676
|
-
eventFilters,
|
|
677
|
-
dataVersionFilters: dataVersionFilters?.map(({ endpointId, clusterId, dataVersion }) => ({
|
|
678
|
-
path: { endpointId, clusterId },
|
|
679
|
-
dataVersion
|
|
680
|
-
}))
|
|
681
|
-
};
|
|
682
|
-
const scope = ReadScope(request);
|
|
683
|
-
let processNewAttributeChangesInListener = false;
|
|
684
|
-
const {
|
|
685
|
-
report,
|
|
686
|
-
subscribeResponse: { subscriptionId, maxInterval },
|
|
687
|
-
maximumPeerResponseTime
|
|
688
|
-
} = await this.withMessenger(async (messenger) => {
|
|
689
|
-
logger.debug(() => [
|
|
690
|
-
"Subscribe",
|
|
691
|
-
Mark.OUTBOUND,
|
|
692
|
-
messenger.exchange.via,
|
|
693
|
-
Diagnostic.dict({
|
|
694
|
-
attributes: attributeRequests.length ? attributeRequests.map((path) => resolveAttributeName(path)).join(", ") : void 0,
|
|
695
|
-
events: eventRequests.length ? eventRequests.map((path) => resolveEventName(path)).join(", ") : void 0,
|
|
696
|
-
dataVersionFilter: dataVersionFilters?.length ? dataVersionFilters.map(
|
|
697
|
-
({ endpointId, clusterId, dataVersion }) => `${endpointId}/${clusterId}=${dataVersion}`
|
|
698
|
-
).join(", ") : void 0,
|
|
699
|
-
eventFilters: eventFilters?.length ? eventFilters.map(({ nodeId, eventMin }) => `${nodeId}=${eventMin}`).join(", ") : void 0,
|
|
700
|
-
fabricFiltered: isFabricFiltered,
|
|
701
|
-
keepSubscriptions,
|
|
702
|
-
minInterval: Duration.format(Seconds(minIntervalFloorSeconds)),
|
|
703
|
-
maxInterval: Duration.format(Seconds(maxIntervalCeilingSeconds))
|
|
704
|
-
})
|
|
705
|
-
]);
|
|
706
|
-
await messenger.sendSubscribeRequest(request);
|
|
707
|
-
const { subscribeResponse, report: report2 } = await messenger.readAggregateSubscribeResponse(
|
|
708
|
-
(attributeReports) => this.processAttributeUpdates(scope, attributeReports, attributeListener)
|
|
709
|
-
);
|
|
710
|
-
logger.info(
|
|
711
|
-
"Subscription successful",
|
|
712
|
-
Mark.INBOUND,
|
|
713
|
-
messenger.exchange.via,
|
|
714
|
-
Diagnostic.dict({
|
|
715
|
-
...Subscription.diagnosticOf(subscribeResponse.subscriptionId),
|
|
716
|
-
maxInterval: Duration.format(Seconds(subscribeResponse.maxInterval))
|
|
717
|
-
})
|
|
718
|
-
);
|
|
719
|
-
return {
|
|
720
|
-
subscribeResponse,
|
|
721
|
-
report: report2,
|
|
722
|
-
maximumPeerResponseTime: this.maximumPeerResponseTime()
|
|
723
|
-
};
|
|
724
|
-
}, executeQueued);
|
|
725
|
-
const subscriptionListener = async (dataReport) => {
|
|
726
|
-
if ((!Array.isArray(dataReport.attributeReports) || !dataReport.attributeReports.length) && (!Array.isArray(dataReport.eventReports) || !dataReport.eventReports.length)) {
|
|
727
|
-
updateReceived?.();
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
|
-
const { attributeReports, eventReports } = dataReport;
|
|
731
|
-
if (eventReports?.length) {
|
|
732
|
-
let maxEventNumber = this.#nodeStore?.maxEventNumber ?? eventReports[0].events[0].eventNumber;
|
|
733
|
-
eventReports.forEach((data) => {
|
|
734
|
-
logger.debug(
|
|
735
|
-
`Event update ${Mark.INBOUND} ${resolveEventName(data.path)}: ${Diagnostic.json(data.events)}`
|
|
736
|
-
);
|
|
737
|
-
const { events } = data;
|
|
738
|
-
maxEventNumber = events.length === 1 ? events[0].eventNumber : events.reduce(
|
|
739
|
-
(max, { eventNumber }) => max < eventNumber ? eventNumber : max,
|
|
740
|
-
maxEventNumber
|
|
741
|
-
);
|
|
742
|
-
eventListener?.(data);
|
|
743
|
-
});
|
|
744
|
-
await this.#nodeStore?.updateLastEventNumber(maxEventNumber);
|
|
745
|
-
}
|
|
746
|
-
if (processNewAttributeChangesInListener && attributeReports !== void 0) {
|
|
747
|
-
await this.processAttributeUpdates(scope, attributeReports, attributeListener);
|
|
748
|
-
}
|
|
749
|
-
updateReceived?.();
|
|
750
|
-
};
|
|
751
|
-
await this.#registerSubscription(
|
|
752
|
-
{
|
|
753
|
-
id: subscriptionId,
|
|
754
|
-
maximumPeerResponseTime,
|
|
755
|
-
maxInterval: Seconds(maxInterval),
|
|
756
|
-
onData: (dataReport) => subscriptionListener(dataReport),
|
|
757
|
-
onTimeout: updateTimeoutHandler
|
|
758
|
-
},
|
|
759
|
-
report
|
|
760
|
-
);
|
|
761
|
-
processNewAttributeChangesInListener = true;
|
|
762
|
-
if (dataVersionFilters !== void 0 && dataVersionFilters.length > 0 && enrichCachedAttributeData) {
|
|
763
|
-
this.#enrichCachedAttributeData(report.attributeReports, dataVersionFilters);
|
|
764
|
-
}
|
|
765
|
-
return {
|
|
766
|
-
...report,
|
|
767
|
-
maxInterval
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Process changed attributes, detect changes and persist them to the node store
|
|
772
|
-
*/
|
|
773
|
-
async processAttributeUpdates(scope, attributeReports, attributeListener) {
|
|
774
|
-
for (const data of attributeReports) {
|
|
775
|
-
const {
|
|
776
|
-
path: { endpointId, clusterId, attributeId },
|
|
777
|
-
value,
|
|
778
|
-
version
|
|
779
|
-
} = data;
|
|
780
|
-
if (value === void 0) {
|
|
781
|
-
throw new MatterFlowError("Received empty subscription result value.");
|
|
782
|
-
}
|
|
783
|
-
const { value: oldValue, version: oldVersion } = this.#nodeStore?.retrieveAttribute(endpointId, clusterId, attributeId) ?? {};
|
|
784
|
-
const changed = oldValue !== void 0 ? !isDeepEqual(oldValue, value) : void 0;
|
|
785
|
-
if (changed !== false || version !== oldVersion) {
|
|
786
|
-
await this.#nodeStore?.persistAttributes([data], scope);
|
|
787
|
-
}
|
|
788
|
-
logger.debug(
|
|
789
|
-
`Attribute update ${Mark.INBOUND}${changed ? " (value changed)" : ""}: ${resolveAttributeName({
|
|
790
|
-
endpointId,
|
|
791
|
-
clusterId,
|
|
792
|
-
attributeId
|
|
793
|
-
})} = ${serialize(value)} (version=${version})`
|
|
794
|
-
);
|
|
795
|
-
attributeListener?.(data, changed, oldValue);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
async invoke(options) {
|
|
799
|
-
const { executeQueued } = options;
|
|
800
|
-
const {
|
|
801
|
-
endpointId,
|
|
802
|
-
clusterId,
|
|
803
|
-
command: { requestId, requestSchema, responseId, responseSchema, optional, timed },
|
|
804
|
-
asTimedRequest,
|
|
805
|
-
timedRequestTimeout: timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT,
|
|
806
|
-
expectedProcessingTime,
|
|
807
|
-
useExtendedFailSafeMessageResponseTimeout = false,
|
|
808
|
-
skipValidation
|
|
809
|
-
} = options;
|
|
810
|
-
let { request } = options;
|
|
811
|
-
const timedRequest = timed && !skipValidation || asTimedRequest === true || options.timedRequestTimeout !== void 0;
|
|
812
|
-
if (this.isGroupAddress) {
|
|
813
|
-
if (endpointId !== void 0) {
|
|
814
|
-
throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
|
|
815
|
-
}
|
|
816
|
-
if (timedRequest) {
|
|
817
|
-
throw new ImplementationError("Timed requests are not supported for group address invokes.");
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
if (requestSchema instanceof ObjectSchema) {
|
|
821
|
-
if (request === void 0) {
|
|
822
|
-
request = {};
|
|
823
|
-
}
|
|
824
|
-
if (requestSchema.isFabricScoped && request.fabricIndex === void 0) {
|
|
825
|
-
request.fabricIndex = FabricIndex.NO_FABRIC;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
logger.debug(
|
|
829
|
-
`Invoking command: ${resolveCommandName({
|
|
830
|
-
endpointId,
|
|
831
|
-
clusterId,
|
|
832
|
-
commandId: requestId
|
|
833
|
-
})} with ${Diagnostic.json(request)}`
|
|
834
|
-
);
|
|
835
|
-
if (!skipValidation) {
|
|
836
|
-
requestSchema.validate(request);
|
|
837
|
-
}
|
|
838
|
-
const commandFields = requestSchema.encodeTlv(request);
|
|
839
|
-
const invokeResponse = await this.withMessenger(async (messenger) => {
|
|
840
|
-
if (timedRequest) {
|
|
841
|
-
await messenger.sendTimedRequest(timedRequestTimeoutMs);
|
|
842
|
-
}
|
|
843
|
-
const response = await messenger.sendInvokeCommand(
|
|
844
|
-
{
|
|
845
|
-
invokeRequests: [{ commandPath: { endpointId, clusterId, commandId: requestId }, commandFields }],
|
|
846
|
-
timedRequest,
|
|
847
|
-
suppressResponse: false,
|
|
848
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION
|
|
849
|
-
},
|
|
850
|
-
expectedProcessingTime ?? (useExtendedFailSafeMessageResponseTimeout ? DEFAULT_MINIMUM_RESPONSE_TIMEOUT_WITH_FAILSAFE : void 0)
|
|
851
|
-
);
|
|
852
|
-
if (response === void 0) {
|
|
853
|
-
throw new MatterFlowError("No response received from invoke interaction but expected.");
|
|
854
|
-
}
|
|
855
|
-
return response;
|
|
856
|
-
}, executeQueued);
|
|
857
|
-
const { invokeResponses } = invokeResponse;
|
|
858
|
-
if (invokeResponses.length === 0) {
|
|
859
|
-
throw new MatterFlowError("Received invoke response with no invoke results.");
|
|
860
|
-
}
|
|
861
|
-
const { command, status } = invokeResponses[0];
|
|
862
|
-
if (status !== void 0) {
|
|
863
|
-
const resultCode = status.status.status;
|
|
864
|
-
if (resultCode !== StatusCode.Success)
|
|
865
|
-
throw new StatusResponseError(
|
|
866
|
-
`Received non-success result: ${resultCode}`,
|
|
867
|
-
resultCode ?? StatusCode.Failure,
|
|
868
|
-
status.status.clusterStatus
|
|
869
|
-
);
|
|
870
|
-
if (responseSchema !== TlvNoResponse)
|
|
871
|
-
throw new MatterFlowError("A response was expected for this command.");
|
|
872
|
-
return void 0;
|
|
873
|
-
}
|
|
874
|
-
if (command !== void 0) {
|
|
875
|
-
const {
|
|
876
|
-
commandPath: { commandId },
|
|
877
|
-
commandFields: commandFields2
|
|
878
|
-
} = command;
|
|
879
|
-
if (commandId !== responseId) {
|
|
880
|
-
throw new MatterFlowError(
|
|
881
|
-
`Received invoke response with unexpected command ID ${commandId}, expected ${responseId}.`
|
|
882
|
-
);
|
|
883
|
-
}
|
|
884
|
-
if (commandFields2 === void 0) {
|
|
885
|
-
if (responseSchema !== TlvNoResponse)
|
|
886
|
-
throw new MatterFlowError(`A response was expected for command ${requestId}.`);
|
|
887
|
-
return void 0;
|
|
888
|
-
}
|
|
889
|
-
const response = responseSchema.decodeTlv(commandFields2);
|
|
890
|
-
logger.debug(
|
|
891
|
-
"Invoke",
|
|
892
|
-
Mark.INBOUND,
|
|
893
|
-
resolveCommandName({
|
|
894
|
-
endpointId,
|
|
895
|
-
clusterId,
|
|
896
|
-
commandId: requestId
|
|
897
|
-
}),
|
|
898
|
-
"with",
|
|
899
|
-
Diagnostic.json(response)
|
|
900
|
-
);
|
|
901
|
-
return response;
|
|
902
|
-
}
|
|
903
|
-
if (optional) {
|
|
904
|
-
return void 0;
|
|
905
|
-
}
|
|
906
|
-
throw new MatterFlowError("Received invoke response with no result nor response.");
|
|
907
|
-
}
|
|
908
|
-
// TODO Add to ClusterClient when needed/when Group communication is implemented
|
|
909
|
-
// TODO Additionally support it without endpoint
|
|
910
|
-
async invokeWithSuppressedResponse(options) {
|
|
911
|
-
const { executeQueued } = options;
|
|
912
|
-
const {
|
|
913
|
-
endpointId,
|
|
914
|
-
clusterId,
|
|
915
|
-
request,
|
|
916
|
-
command: { requestId, requestSchema, timed },
|
|
917
|
-
asTimedRequest,
|
|
918
|
-
timedRequestTimeout = DEFAULT_TIMED_REQUEST_TIMEOUT
|
|
919
|
-
} = options;
|
|
920
|
-
const timedRequest = timed || asTimedRequest === true || options.timedRequestTimeout !== void 0;
|
|
921
|
-
if (this.isGroupAddress) {
|
|
922
|
-
if (timed) {
|
|
923
|
-
throw new ImplementationError("Timed requests are not supported for group address invokes.");
|
|
924
|
-
}
|
|
925
|
-
if (endpointId !== void 0) {
|
|
926
|
-
throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
logger.debug(
|
|
930
|
-
`Invoking command with suppressedResponse: ${resolveCommandName({
|
|
931
|
-
endpointId,
|
|
932
|
-
clusterId,
|
|
933
|
-
commandId: requestId
|
|
934
|
-
})} with ${Diagnostic.json(request)}`
|
|
935
|
-
);
|
|
936
|
-
const commandFields = requestSchema.encodeTlv(request);
|
|
937
|
-
await this.withMessenger(async (messenger) => {
|
|
938
|
-
if (timedRequest) {
|
|
939
|
-
await messenger.sendTimedRequest(timedRequestTimeout);
|
|
940
|
-
}
|
|
941
|
-
const response = await messenger.sendInvokeCommand({
|
|
942
|
-
invokeRequests: [{ commandPath: { endpointId, clusterId, commandId: requestId }, commandFields }],
|
|
943
|
-
timedRequest,
|
|
944
|
-
suppressResponse: true,
|
|
945
|
-
interactionModelRevision: Specification.INTERACTION_MODEL_REVISION
|
|
946
|
-
});
|
|
947
|
-
if (response !== void 0) {
|
|
948
|
-
throw new MatterFlowError(
|
|
949
|
-
"Response received from invoke interaction but none expected because response is suppressed."
|
|
950
|
-
);
|
|
951
|
-
}
|
|
952
|
-
}, executeQueued);
|
|
953
|
-
logger.debug(
|
|
954
|
-
"Invoke successful",
|
|
955
|
-
Mark.INBOUND,
|
|
956
|
-
resolveCommandName({
|
|
957
|
-
endpointId,
|
|
958
|
-
clusterId,
|
|
959
|
-
commandId: requestId
|
|
960
|
-
})
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
async withMessenger(invoke, executeQueued = false) {
|
|
964
|
-
const messenger = await InteractionClientMessenger.create(this.#exchangeProvider);
|
|
965
|
-
let result;
|
|
966
|
-
try {
|
|
967
|
-
if (executeQueued) {
|
|
968
|
-
if (this.#queue === void 0) {
|
|
969
|
-
throw new ImplementationError("Cannot execute queued operation without a queue.");
|
|
970
|
-
}
|
|
971
|
-
return await this.#queue.add(() => invoke(messenger));
|
|
972
|
-
}
|
|
973
|
-
result = await invoke(messenger);
|
|
974
|
-
} finally {
|
|
975
|
-
messenger.close().catch((error) => logger.info(`Error closing messenger: ${error}`));
|
|
976
|
-
}
|
|
977
|
-
return result;
|
|
978
|
-
}
|
|
979
|
-
removeAllSubscriptions() {
|
|
980
|
-
for (const subscriptionId of this.#ownSubscriptionIds) {
|
|
981
|
-
this.removeSubscription(subscriptionId);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
close() {
|
|
985
|
-
this.removeAllSubscriptions();
|
|
986
|
-
}
|
|
987
|
-
get session() {
|
|
988
|
-
return this.#exchangeProvider.session;
|
|
989
|
-
}
|
|
990
|
-
get channelType() {
|
|
991
|
-
return this.#exchangeProvider.channelType;
|
|
992
|
-
}
|
|
993
|
-
/** Enrich cached data to get complete responses when data version filters were used. */
|
|
994
|
-
#enrichCachedAttributeData(attributeReports, dataVersionFilters) {
|
|
995
|
-
if (this.#nodeStore === void 0) {
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
const candidates = /* @__PURE__ */ new Map();
|
|
999
|
-
for (const { endpointId, clusterId, dataVersion } of dataVersionFilters) {
|
|
1000
|
-
if (!candidates.has(endpointId)) {
|
|
1001
|
-
candidates.set(endpointId, /* @__PURE__ */ new Map());
|
|
1002
|
-
}
|
|
1003
|
-
candidates.get(endpointId)?.set(clusterId, this.#nodeStore.getClusterDataVersion(endpointId, clusterId) ?? dataVersion);
|
|
1004
|
-
}
|
|
1005
|
-
attributeReports.forEach(({ path: { endpointId, clusterId } }) => {
|
|
1006
|
-
if (candidates.has(endpointId)) {
|
|
1007
|
-
candidates.get(endpointId)?.delete(clusterId);
|
|
1008
|
-
}
|
|
1009
|
-
});
|
|
1010
|
-
for (const [endpointId, clusters] of candidates) {
|
|
1011
|
-
for (const [clusterId, version] of clusters) {
|
|
1012
|
-
const clusterValues = this.#nodeStore.retrieveAttributes(endpointId, clusterId);
|
|
1013
|
-
logger.debug(
|
|
1014
|
-
`Enriching cached data (${clusterValues.length} attributes) for ${endpointId}/${clusterId} with version=${version}`
|
|
1015
|
-
);
|
|
1016
|
-
attributeReports.push(...clusterValues);
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
/**
|
|
1021
|
-
* Returns the list (optionally filtered by endpointId and/or clusterId) of the dataVersions of the currently cached
|
|
1022
|
-
* values to use them as knownDataVersion for read or subscription requests.
|
|
1023
|
-
*/
|
|
1024
|
-
getCachedClusterDataVersions(filter) {
|
|
1025
|
-
if (this.#nodeStore === void 0) {
|
|
1026
|
-
return [];
|
|
1027
|
-
}
|
|
1028
|
-
const { endpointId, clusterId } = filter ?? {};
|
|
1029
|
-
return this.#nodeStore.getClusterDataVersions(endpointId, clusterId);
|
|
1030
|
-
}
|
|
1031
|
-
get maxKnownEventNumber() {
|
|
1032
|
-
return this.#nodeStore?.maxEventNumber;
|
|
1033
|
-
}
|
|
1034
|
-
cleanupAttributeData(endpointId, clusterIds) {
|
|
1035
|
-
return this.#nodeStore?.cleanupAttributeData(endpointId, clusterIds);
|
|
1036
|
-
}
|
|
1037
|
-
getAllCachedClusterData() {
|
|
1038
|
-
const result = new Array();
|
|
1039
|
-
this.#enrichCachedAttributeData(result, this.getCachedClusterDataVersions());
|
|
1040
|
-
return result;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
export {
|
|
1044
|
-
InteractionClient,
|
|
1045
|
-
InteractionClientProvider
|
|
1046
|
-
};
|
|
1047
|
-
//# sourceMappingURL=InteractionClient.js.map
|