@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
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { ClientRead } from "#action/client/ClientRead.js";
|
|
7
8
|
import { Interactable, InteractionSession } from "#action/Interactable.js";
|
|
8
9
|
import { ClientInvoke, Invoke } from "#action/request/Invoke.js";
|
|
9
10
|
import { Read } from "#action/request/Read.js";
|
|
@@ -28,6 +29,8 @@ import {
|
|
|
28
29
|
Minutes,
|
|
29
30
|
RetrySchedule,
|
|
30
31
|
Seconds,
|
|
32
|
+
Time,
|
|
33
|
+
TimeoutError,
|
|
31
34
|
} from "#general";
|
|
32
35
|
import { InteractionClientMessenger, MessageType } from "#interaction/InteractionMessenger.js";
|
|
33
36
|
import { Subscription } from "#interaction/Subscription.js";
|
|
@@ -35,6 +38,7 @@ import { PeerAddress } from "#peer/index.js";
|
|
|
35
38
|
import { ExchangeProvider } from "#protocol/ExchangeProvider.js";
|
|
36
39
|
import { SecureSession } from "#session/SecureSession.js";
|
|
37
40
|
import { Status, TlvAttributeReport, TlvNoResponse, TlvSubscribeResponse, TypeFromSchema } from "#types";
|
|
41
|
+
import { ClientWrite } from "./ClientWrite.js";
|
|
38
42
|
import { InputChunk } from "./InputChunk.js";
|
|
39
43
|
import { ClientSubscribe } from "./subscription/ClientSubscribe.js";
|
|
40
44
|
import { ClientSubscription } from "./subscription/ClientSubscription.js";
|
|
@@ -53,6 +57,7 @@ export interface ClientInteractionContext {
|
|
|
53
57
|
abort?: Abort.Signal;
|
|
54
58
|
sustainRetries?: RetrySchedule.Configuration;
|
|
55
59
|
exchangeProvider?: ExchangeProvider;
|
|
60
|
+
address?: PeerAddress;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
export const DEFAULT_MIN_INTERVAL_FLOOR = Seconds(1);
|
|
@@ -74,16 +79,17 @@ const DEFAULT_MINIMUM_RESPONSE_TIMEOUT_WITH_FAILSAFE = Seconds(30);
|
|
|
74
79
|
export class ClientInteraction<
|
|
75
80
|
SessionT extends InteractionSession = InteractionSession,
|
|
76
81
|
> implements Interactable<SessionT> {
|
|
77
|
-
readonly
|
|
82
|
+
protected readonly environment: Environment;
|
|
78
83
|
readonly #lifetime: Lifetime;
|
|
79
84
|
readonly #exchanges: ExchangeProvider;
|
|
80
85
|
readonly #interactions = new BasicSet<Read | Write | Invoke | Subscribe>();
|
|
81
86
|
#subscriptions?: ClientSubscriptions;
|
|
82
87
|
readonly #abort: Abort;
|
|
83
88
|
readonly #sustainRetries: RetrySchedule;
|
|
89
|
+
readonly #address?: PeerAddress;
|
|
84
90
|
|
|
85
|
-
constructor({ environment, abort, sustainRetries, exchangeProvider }: ClientInteractionContext) {
|
|
86
|
-
this
|
|
91
|
+
constructor({ environment, abort, sustainRetries, exchangeProvider, address }: ClientInteractionContext) {
|
|
92
|
+
this.environment = environment;
|
|
87
93
|
this.#exchanges = exchangeProvider ?? environment.get(ExchangeProvider);
|
|
88
94
|
if (environment.has(ClientSubscriptions)) {
|
|
89
95
|
this.#subscriptions = environment.get(ClientSubscriptions);
|
|
@@ -93,6 +99,7 @@ export class ClientInteraction<
|
|
|
93
99
|
environment.get(Entropy),
|
|
94
100
|
RetrySchedule.Configuration(SustainedSubscription.DefaultRetrySchedule, sustainRetries),
|
|
95
101
|
);
|
|
102
|
+
this.#address = address;
|
|
96
103
|
|
|
97
104
|
this.#lifetime = environment.join("interactions");
|
|
98
105
|
Object.defineProperties(this.#lifetime.details, {
|
|
@@ -126,7 +133,7 @@ export class ClientInteraction<
|
|
|
126
133
|
|
|
127
134
|
get subscriptions() {
|
|
128
135
|
if (this.#subscriptions === undefined) {
|
|
129
|
-
this.#subscriptions = this
|
|
136
|
+
this.#subscriptions = this.environment.get(ClientSubscriptions);
|
|
130
137
|
}
|
|
131
138
|
return this.#subscriptions;
|
|
132
139
|
}
|
|
@@ -134,7 +141,7 @@ export class ClientInteraction<
|
|
|
134
141
|
/**
|
|
135
142
|
* Read attributes and events.
|
|
136
143
|
*/
|
|
137
|
-
async *read(request:
|
|
144
|
+
async *read(request: ClientRead, session?: SessionT): ReadResult {
|
|
138
145
|
const readPathsCount = (request.attributeRequests?.length ?? 0) + (request.eventRequests?.length ?? 0);
|
|
139
146
|
if (readPathsCount === 0) {
|
|
140
147
|
throw new ImplementationError("When reading attributes and events, at least one must be specified.");
|
|
@@ -182,7 +189,7 @@ export class ClientInteraction<
|
|
|
182
189
|
* Writes with the Matter protocol are generally not atomic, so this method only throws if the entire action fails.
|
|
183
190
|
* You must check each {@link WriteResult.AttributeStatus} to determine whether individual updates failed.
|
|
184
191
|
*/
|
|
185
|
-
async write<T extends
|
|
192
|
+
async write<T extends ClientWrite>(request: T, session?: SessionT): WriteResult<T> {
|
|
186
193
|
await using context = await this.#begin("writing", request, session);
|
|
187
194
|
const { checkAbort, messenger } = context;
|
|
188
195
|
|
|
@@ -419,16 +426,6 @@ export class ClientInteraction<
|
|
|
419
426
|
const responseMessage = await messenger.nextMessage(MessageType.SubscribeResponse);
|
|
420
427
|
const response = TlvSubscribeResponse.decode(responseMessage.payload);
|
|
421
428
|
|
|
422
|
-
logger.info(
|
|
423
|
-
"Subscription successful",
|
|
424
|
-
Mark.INBOUND,
|
|
425
|
-
messenger.exchange.via,
|
|
426
|
-
Diagnostic.dict({
|
|
427
|
-
id: response.subscriptionId,
|
|
428
|
-
interval: Duration.format(Seconds(response.maxInterval)),
|
|
429
|
-
}),
|
|
430
|
-
);
|
|
431
|
-
|
|
432
429
|
const subscription = new PeerSubscription({
|
|
433
430
|
lifetime: this.subscriptions,
|
|
434
431
|
request,
|
|
@@ -440,6 +437,17 @@ export class ClientInteraction<
|
|
|
440
437
|
});
|
|
441
438
|
this.subscriptions.addPeer(subscription);
|
|
442
439
|
|
|
440
|
+
logger.info(
|
|
441
|
+
"Subscription successful",
|
|
442
|
+
Mark.INBOUND,
|
|
443
|
+
messenger.exchange.via,
|
|
444
|
+
Diagnostic.dict({
|
|
445
|
+
id: Subscription.idStrOf(response.subscriptionId),
|
|
446
|
+
interval: Duration.format(Seconds(response.maxInterval)),
|
|
447
|
+
timeout: Duration.format(subscription.timeout),
|
|
448
|
+
}),
|
|
449
|
+
);
|
|
450
|
+
|
|
443
451
|
return subscription;
|
|
444
452
|
};
|
|
445
453
|
|
|
@@ -482,13 +490,28 @@ export class ClientInteraction<
|
|
|
482
490
|
if (this.#abort.aborted) {
|
|
483
491
|
throw new ImplementationError("Client interaction unavailable after close");
|
|
484
492
|
}
|
|
485
|
-
this.#interactions.add(request);
|
|
486
493
|
|
|
487
494
|
const checkAbort = Abort.checkerFor(session);
|
|
488
495
|
|
|
489
|
-
const
|
|
496
|
+
const now = Time.nowMs;
|
|
497
|
+
let messenger: InteractionClientMessenger;
|
|
498
|
+
try {
|
|
499
|
+
messenger = await InteractionClientMessenger.create(this.#exchanges);
|
|
500
|
+
} catch (error) {
|
|
501
|
+
TimeoutError.accept(error);
|
|
502
|
+
|
|
503
|
+
// This logic implements a very basic automatic reconnection mechanism which is a bit like PairedNode
|
|
504
|
+
// The exchange creation fails only when the node is considered to be unavailable, so in this case we
|
|
505
|
+
// either try the last addresses again (if existing), or do a short-timed re-discovery. This would block
|
|
506
|
+
// the execution max 10s. What's missing is that one layer (like Sustained Subscription) would trigger a
|
|
507
|
+
// FullDiscovery instead of just a timed one, but for the tests and currently this should be enough.
|
|
508
|
+
await this.exchanges.reconnectChannel({ asOf: now, resetInitialState: true });
|
|
509
|
+
messenger = await InteractionClientMessenger.create(this.#exchanges);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
this.#interactions.add(request);
|
|
490
513
|
|
|
491
|
-
// Provide via dynamically so is up
|
|
514
|
+
// Provide via dynamically so is up to date if exchange changes due to retry
|
|
492
515
|
Object.defineProperty(lifetime.details, "via", {
|
|
493
516
|
get() {
|
|
494
517
|
return messenger.exchange.via;
|
|
@@ -513,6 +536,22 @@ export class ClientInteraction<
|
|
|
513
536
|
|
|
514
537
|
return context;
|
|
515
538
|
}
|
|
539
|
+
|
|
540
|
+
get channelType() {
|
|
541
|
+
return this.#exchanges.channelType;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** Calculates the current maximum response time for a message use in additional logic like timers. */
|
|
545
|
+
maximumPeerResponseTime(expectedProcessingTime?: Duration) {
|
|
546
|
+
return this.#exchanges.maximumPeerResponseTime(expectedProcessingTime);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
get address() {
|
|
550
|
+
if (this.#address === undefined) {
|
|
551
|
+
throw new ImplementationError("This InteractionClient is not bound to a specific peer.");
|
|
552
|
+
}
|
|
553
|
+
return this.#address;
|
|
554
|
+
}
|
|
516
555
|
}
|
|
517
556
|
|
|
518
557
|
interface RequestContext {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Read } from "#action/request/Read.js";
|
|
8
|
+
import { ClientRequest } from "./ClientRequest.js";
|
|
9
|
+
|
|
10
|
+
export interface ClientRead extends Read, ClientRequest {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents a client request with customizable transmission behavior.
|
|
9
|
+
*/
|
|
10
|
+
export interface ClientRequest {
|
|
11
|
+
/**
|
|
12
|
+
* If true, the request will be queued over all peers of the node.
|
|
13
|
+
* If false, the request will be sent directly.
|
|
14
|
+
* If undefined, the request will be queued if the physical device is thread connected.
|
|
15
|
+
* TODO Adjust this to be owned by some internal network layer that maintains automatic limits per connection type
|
|
16
|
+
* or such
|
|
17
|
+
* @deprecated
|
|
18
|
+
*/
|
|
19
|
+
queued?: boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Write } from "#action/request/Write.js";
|
|
8
|
+
import { ClientRequest } from "./ClientRequest.js";
|
|
9
|
+
|
|
10
|
+
export interface ClientWrite extends Write, ClientRequest {}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
ClientInvoke,
|
|
8
|
+
ClientSubscribe,
|
|
9
|
+
ClientWrite,
|
|
10
|
+
DecodedInvokeResult,
|
|
11
|
+
InteractionSession,
|
|
12
|
+
ReadResult,
|
|
13
|
+
SubscriptionResult,
|
|
14
|
+
WriteResult,
|
|
15
|
+
} from "#action/index.js";
|
|
16
|
+
import { InteractionQueue } from "#peer/index.js";
|
|
17
|
+
import { ClientInteraction, ClientInteractionContext } from "./ClientInteraction.js";
|
|
18
|
+
import { ClientRead } from "./ClientRead.js";
|
|
19
|
+
|
|
20
|
+
export interface QueuedClientInteractionContext extends ClientInteractionContext {
|
|
21
|
+
queue: InteractionQueue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class QueuedClientInteraction<
|
|
25
|
+
SessionT extends InteractionSession = InteractionSession,
|
|
26
|
+
> extends ClientInteraction<SessionT> {
|
|
27
|
+
#queue?: InteractionQueue;
|
|
28
|
+
|
|
29
|
+
constructor(options: QueuedClientInteractionContext) {
|
|
30
|
+
super(options);
|
|
31
|
+
this.#queue = options.queue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected get queue() {
|
|
35
|
+
if (this.#queue === undefined) {
|
|
36
|
+
this.#queue = this.environment.get(InteractionQueue);
|
|
37
|
+
}
|
|
38
|
+
return this.#queue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Read chosen attributes remotely from the node. Known data versions are automatically injected into the request to
|
|
43
|
+
* optimize the read.
|
|
44
|
+
* Therefore, the returned data only contains attributes that have changed since the last read or subscription.
|
|
45
|
+
* TODO: Allow control of data version injection and enrich response with attribute data missing in response due to data versioning?
|
|
46
|
+
*/
|
|
47
|
+
override async *read(request: ClientRead, session?: SessionT): ReadResult {
|
|
48
|
+
using _slot = await this.queue.obtainSlot();
|
|
49
|
+
|
|
50
|
+
yield* super.read(request, session);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Subscribe to remote events and attributes as defined by {@link request}.
|
|
55
|
+
*
|
|
56
|
+
* matter.js updates local state
|
|
57
|
+
*
|
|
58
|
+
* By default, matter.js subscribes to all attributes and events of the peer and updates {@link ClientNode} state
|
|
59
|
+
* automatically. So you normally do not need to subscribe manually.
|
|
60
|
+
*
|
|
61
|
+
* When providing the "sustain" flag, a SustainedSubscription is returned immediately. You need to use the events to
|
|
62
|
+
* know when/if a subscription could be established. This class handles reconnections automatically.
|
|
63
|
+
* When not providing the "sustain" flag, a PeerSubscription is returned after a subscription have been successfully
|
|
64
|
+
* established; or an error is returned if this was not possible.
|
|
65
|
+
*/
|
|
66
|
+
override async subscribe<T extends ClientSubscribe>(request: T, session?: SessionT): SubscriptionResult<T> {
|
|
67
|
+
using _slot = await this.queue.obtainSlot();
|
|
68
|
+
|
|
69
|
+
return super.subscribe(request, session);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Write chosen attributes remotely to the node.
|
|
74
|
+
* The returned attribute writing status information is returned.
|
|
75
|
+
*/
|
|
76
|
+
override async write<T extends ClientWrite>(request: T, session?: SessionT): WriteResult<T> {
|
|
77
|
+
using _slot = await this.queue.obtainSlot();
|
|
78
|
+
|
|
79
|
+
return super.write(request, session);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Invoke a command remotely on the node.
|
|
84
|
+
* The returned command response is returned as response chunks
|
|
85
|
+
*/
|
|
86
|
+
override async *invoke(request: ClientInvoke, session?: SessionT): DecodedInvokeResult {
|
|
87
|
+
using _slot = await this.queue.obtainSlot();
|
|
88
|
+
|
|
89
|
+
yield* super.invoke(request, session);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export * from "./ClientInteraction.js";
|
|
8
|
+
export * from "./ClientRead.js";
|
|
9
|
+
export * from "./ClientRequest.js";
|
|
10
|
+
export * from "./ClientWrite.js";
|
|
8
11
|
export * from "./InputChunk.js";
|
|
12
|
+
export * from "./QueuedClientInteraction.js";
|
|
9
13
|
export * from "./ReadScope.js";
|
|
10
14
|
export * from "./subscription/index.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Subscribe } from "#action/request/Subscribe.js";
|
|
2
|
+
import { ClientRequest } from "../ClientRequest.js";
|
|
2
3
|
|
|
3
|
-
export interface ClientSubscribe extends Subscribe {
|
|
4
|
+
export interface ClientSubscribe extends Subscribe, ClientRequest {
|
|
4
5
|
/**
|
|
5
6
|
* If true the subscription is virtualized and the underlying subscription is reestablished when lost.
|
|
6
7
|
*/
|
|
@@ -54,7 +54,10 @@ export class ClientSubscriptionHandler implements ProtocolHandler {
|
|
|
54
54
|
SecureSession.assert(session);
|
|
55
55
|
const subscription = this.#subscriptions.getPeer(session.peerAddress, subscriptionId);
|
|
56
56
|
if (subscription === undefined) {
|
|
57
|
-
logger.info(
|
|
57
|
+
logger.info(
|
|
58
|
+
"Ignoring data report for unknown subscription ID",
|
|
59
|
+
Diagnostic.strong(Subscription.idStrOf(subscriptionId)),
|
|
60
|
+
);
|
|
58
61
|
await sendInvalid(messenger, subscriptionId);
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
@@ -68,7 +71,10 @@ export class ClientSubscriptionHandler implements ProtocolHandler {
|
|
|
68
71
|
// Read the next report to trigger success message sent out
|
|
69
72
|
const ending = await reports.next();
|
|
70
73
|
if (!ending.done) {
|
|
71
|
-
logger.warn(
|
|
74
|
+
logger.warn(
|
|
75
|
+
"Unexpected data reports after empty report",
|
|
76
|
+
Diagnostic.strong(Subscription.idStrOf(subscriptionId)),
|
|
77
|
+
);
|
|
72
78
|
for await (const _chunk of reports); // Read over these extraneous reports
|
|
73
79
|
}
|
|
74
80
|
} else {
|
|
@@ -125,7 +131,12 @@ async function* processReports(
|
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
if (reportSubscriptionId !== subscriptionId) {
|
|
128
|
-
logger.debug(
|
|
134
|
+
logger.debug(
|
|
135
|
+
"Ignoring data report for incorrect subscription id",
|
|
136
|
+
Diagnostic.strong(Subscription.idStrOf(reportSubscriptionId)),
|
|
137
|
+
"expected",
|
|
138
|
+
Subscription.idStrOf(subscriptionId),
|
|
139
|
+
);
|
|
129
140
|
await sendInvalid(messenger, reportSubscriptionId);
|
|
130
141
|
continue;
|
|
131
142
|
}
|
|
@@ -56,7 +56,7 @@ export class SustainedSubscription extends ClientSubscription {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* Emits when active state changes.
|
|
59
|
+
* Emits when the active state changes.
|
|
60
60
|
*/
|
|
61
61
|
get active() {
|
|
62
62
|
return this.#active;
|
|
@@ -73,7 +73,7 @@ export class SustainedSubscription extends ClientSubscription {
|
|
|
73
73
|
const updated = this.#request.updated?.bind(this.#request);
|
|
74
74
|
|
|
75
75
|
while (true) {
|
|
76
|
-
// Create request and promise that will inform us when the underlying subscription closes
|
|
76
|
+
// Create a request and promise that will inform us when the underlying subscription closes
|
|
77
77
|
const request = { ...this.#request, updated };
|
|
78
78
|
if (this.#request.updated) {
|
|
79
79
|
request.updated = this.#request.updated.bind(request);
|
|
@@ -111,7 +111,7 @@ export class SustainedSubscription extends ClientSubscription {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
// Notify listeners of active subscription
|
|
114
|
+
// Notify listeners of an active subscription
|
|
115
115
|
await this.#inactive.emit(false);
|
|
116
116
|
await this.#active.emit(true);
|
|
117
117
|
if (this.abort.aborted) {
|
|
@@ -121,19 +121,16 @@ export class SustainedSubscription extends ClientSubscription {
|
|
|
121
121
|
// Wait for the subscription to close
|
|
122
122
|
await closed;
|
|
123
123
|
|
|
124
|
-
// Notify listeners of inactive subscription
|
|
124
|
+
// Notify listeners of an inactive subscription
|
|
125
125
|
await this.#active.emit(false);
|
|
126
126
|
await this.#inactive.emit(true);
|
|
127
|
-
if (this.abort.aborted) {
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
127
|
|
|
131
|
-
// If aborted then we're done
|
|
128
|
+
// If aborted, then we're done
|
|
132
129
|
if (this.abort.aborted) {
|
|
133
130
|
break;
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
// If we aren't aborted then we are here due to timeout
|
|
133
|
+
// If we aren't aborted, then we are here due to timeout
|
|
137
134
|
logger.error(`Replacing subscription to ${this.peer} due to timeout`);
|
|
138
135
|
}
|
|
139
136
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { ClientRequest } from "#action/client/ClientRequest.js";
|
|
7
8
|
import { Diagnostic, Duration, isObject } from "#general";
|
|
8
9
|
import { SessionParameters } from "#session/SessionParameters.js";
|
|
9
10
|
import { ClusterType, CommandData, FabricIndex, InvokeRequest, ObjectSchema, TlvSchema, TypeFromSchema } from "#types";
|
|
@@ -17,11 +18,20 @@ export interface InvokeCommandData extends CommandData {
|
|
|
17
18
|
export interface Invoke extends InvokeRequest {
|
|
18
19
|
/** Timeout only relevant for Client Interactions */
|
|
19
20
|
timeout?: Duration;
|
|
21
|
+
|
|
22
|
+
/** Expected processing time of the command on the server side to calculated response timeout */
|
|
20
23
|
expectedProcessingTime?: Duration;
|
|
24
|
+
|
|
25
|
+
/** Whether to use extended timeout for fail-safe messages. Overwrites the expectedProcessingTime if both are set */
|
|
21
26
|
useExtendedFailSafeMessageResponseTimeout?: boolean;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
export interface
|
|
29
|
+
export interface CommandDecodeDetails {
|
|
30
|
+
responseSchema: TlvSchema<any>;
|
|
31
|
+
[Diagnostic.value]: () => unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ClientInvoke extends Invoke, ClientRequest {
|
|
25
35
|
commands: Map<number | undefined, Invoke.CommandRequest<any>>;
|
|
26
36
|
}
|
|
27
37
|
|
|
@@ -234,9 +244,6 @@ export namespace Invoke {
|
|
|
234
244
|
export function commandOf<const R extends CommandRequest>(request: R): ClusterType.Command {
|
|
235
245
|
if (typeof request.command === "string") {
|
|
236
246
|
const cluster = Specifier.clusterFor(request.cluster);
|
|
237
|
-
if (cluster === undefined) {
|
|
238
|
-
throw new MalformedRequestError(`Cannot designate command "${request.command}" without cluster`);
|
|
239
|
-
}
|
|
240
247
|
const command = cluster.commands[request.command];
|
|
241
248
|
if (command === undefined) {
|
|
242
249
|
throw new MalformedRequestError(`Cluster ${cluster.name} does not define command ${request.command}`);
|
|
@@ -45,11 +45,12 @@ export function Read(optionsOrSelector: Read.Options | Read.Selector, ...selecto
|
|
|
45
45
|
} else {
|
|
46
46
|
options = optionsOrSelector;
|
|
47
47
|
}
|
|
48
|
+
const { fabricFilter = true, interactionModelRevision = Specification.INTERACTION_MODEL_REVISION } = options;
|
|
48
49
|
let { attributes: attributeRequests, versionFilters, events: eventRequests, eventFilters } = options;
|
|
49
50
|
|
|
50
51
|
const result = {
|
|
51
|
-
isFabricFiltered:
|
|
52
|
-
interactionModelRevision
|
|
52
|
+
isFabricFiltered: fabricFilter,
|
|
53
|
+
interactionModelRevision,
|
|
53
54
|
[Diagnostic.value]: () =>
|
|
54
55
|
Diagnostic.dict({
|
|
55
56
|
attributes: attributeRequests?.length
|
|
@@ -57,7 +57,10 @@ export namespace Specifier {
|
|
|
57
57
|
/**
|
|
58
58
|
* Extract a cluster type from a cluster specifier.
|
|
59
59
|
*/
|
|
60
|
-
export function clusterFor<const T extends Cluster>(specifier
|
|
60
|
+
export function clusterFor<const T extends Cluster>(specifier?: T) {
|
|
61
|
+
if (specifier === undefined) {
|
|
62
|
+
throw new MalformedRequestError(`Cannot designate command "${specifier}" without a cluster`);
|
|
63
|
+
}
|
|
61
64
|
if ("cluster" in specifier) {
|
|
62
65
|
return specifier["cluster"] as ClusterFor<T>;
|
|
63
66
|
}
|
|
@@ -52,14 +52,22 @@ export function Write(optionsOrData: Write.Options | Write.Attribute, ...data: W
|
|
|
52
52
|
} else {
|
|
53
53
|
options = optionsOrData;
|
|
54
54
|
}
|
|
55
|
-
const {
|
|
55
|
+
const {
|
|
56
|
+
writes: writeRequests = [],
|
|
57
|
+
timed,
|
|
58
|
+
timeout,
|
|
59
|
+
chunkLists,
|
|
60
|
+
suppressResponse,
|
|
61
|
+
interactionModelRevision = Specification.INTERACTION_MODEL_REVISION,
|
|
62
|
+
} = options;
|
|
56
63
|
|
|
57
64
|
const result = {
|
|
58
65
|
timedRequest: !!timed || !!timeout,
|
|
59
66
|
timeout,
|
|
60
67
|
writeRequests,
|
|
61
68
|
moreChunkedMessages: false,
|
|
62
|
-
|
|
69
|
+
suppressResponse,
|
|
70
|
+
interactionModelRevision,
|
|
63
71
|
|
|
64
72
|
[Diagnostic.value]: () =>
|
|
65
73
|
Diagnostic.list(
|
|
@@ -158,6 +166,7 @@ export namespace Write {
|
|
|
158
166
|
timeout?: Duration;
|
|
159
167
|
interactionModelRevision?: number;
|
|
160
168
|
chunkLists?: boolean;
|
|
169
|
+
suppressResponse?: boolean;
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
/**
|
|
@@ -28,7 +28,7 @@ import type {
|
|
|
28
28
|
* Iteration occurs in chunks for performance reasons. A chunk is an iterable of reports, one per output attribute or
|
|
29
29
|
* event.
|
|
30
30
|
*/
|
|
31
|
-
export interface ReadResult<Chunk = ReadResult.Chunk> extends
|
|
31
|
+
export interface ReadResult<Chunk = ReadResult.Chunk> extends AsyncIterable<Chunk> {}
|
|
32
32
|
|
|
33
33
|
export namespace ReadResult {
|
|
34
34
|
export type Chunk = Iterable<Report>;
|
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
CommandId,
|
|
17
17
|
Commands,
|
|
18
18
|
EndpointNumber,
|
|
19
|
+
Event,
|
|
19
20
|
EventId,
|
|
21
|
+
EventNumber,
|
|
20
22
|
EventType,
|
|
21
23
|
Events,
|
|
22
24
|
GlobalAttributeNames,
|
|
@@ -35,15 +37,53 @@ import {
|
|
|
35
37
|
WritableAttribute,
|
|
36
38
|
} from "#types";
|
|
37
39
|
import { DecodedEventData } from "../../interaction/EventDataDecoder.js";
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
|
|
41
|
+
export interface AttributeClientObj<T = any> {
|
|
42
|
+
readonly id: AttributeId;
|
|
43
|
+
readonly attribute: Attribute<T, any>;
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly endpointId: EndpointNumber | undefined;
|
|
46
|
+
readonly clusterId: ClusterId;
|
|
47
|
+
readonly fabricScoped: boolean;
|
|
48
|
+
set(value: T, dataVersion?: number): Promise<void>;
|
|
49
|
+
getLocal(): T | undefined;
|
|
50
|
+
get(requestFromRemote?: boolean, isFabricFiltered?: boolean): Promise<T | undefined>;
|
|
51
|
+
subscribe(
|
|
52
|
+
minIntervalFloorSeconds: number,
|
|
53
|
+
maxIntervalCeilingSeconds: number,
|
|
54
|
+
knownDataVersion?: number,
|
|
55
|
+
isFabricFiltered?: boolean,
|
|
56
|
+
): Promise<{ maxInterval: number }>;
|
|
57
|
+
update(value: T): void;
|
|
58
|
+
addListener(listener: (newValue: T) => void): void;
|
|
59
|
+
removeListener(listener: (newValue: T) => void): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface EventClientObj<T> {
|
|
63
|
+
readonly id: EventId;
|
|
64
|
+
readonly event: Event<T, any>;
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly endpointId: EndpointNumber | undefined;
|
|
67
|
+
readonly clusterId: ClusterId;
|
|
68
|
+
get(minimumEventNumber?: EventNumber, isFabricFiltered?: boolean): Promise<DecodedEventData<T>[] | undefined>;
|
|
69
|
+
subscribe(
|
|
70
|
+
minIntervalFloorSeconds: Duration,
|
|
71
|
+
maxIntervalCeilingSeconds: Duration,
|
|
72
|
+
isUrgent?: boolean,
|
|
73
|
+
minimumEventNumber?: EventNumber,
|
|
74
|
+
isFabricFiltered?: boolean,
|
|
75
|
+
): Promise<{ maxInterval: number }>;
|
|
76
|
+
update(newEvent: DecodedEventData<T>): void;
|
|
77
|
+
addListener(listener: (newValue: DecodedEventData<T>) => void): void;
|
|
78
|
+
removeListener(listener: (newValue: DecodedEventData<T>) => void): void;
|
|
79
|
+
}
|
|
40
80
|
|
|
41
81
|
export type AttributeClients<F extends BitSchema, A extends Attributes> = Merge<
|
|
42
82
|
Merge<
|
|
43
|
-
{ [P in MandatoryAttributeNames<A>]:
|
|
44
|
-
{ [P in OptionalAttributeNames<A>]:
|
|
83
|
+
{ [P in MandatoryAttributeNames<A>]: AttributeClientObj<AttributeJsType<A[P]>> },
|
|
84
|
+
{ [P in OptionalAttributeNames<A>]: AttributeClientObj<AttributeJsType<A[P]> | undefined> }
|
|
45
85
|
>,
|
|
46
|
-
{ [P in GlobalAttributeNames<F>]:
|
|
86
|
+
{ [P in GlobalAttributeNames<F>]: AttributeClientObj<AttributeJsType<GlobalAttributes<F>[P]>> }
|
|
47
87
|
>;
|
|
48
88
|
|
|
49
89
|
export type AttributeClientValues<A extends Attributes> = Merge<
|
|
@@ -52,8 +92,8 @@ export type AttributeClientValues<A extends Attributes> = Merge<
|
|
|
52
92
|
>;
|
|
53
93
|
|
|
54
94
|
export type EventClients<E extends Events> = Merge<
|
|
55
|
-
{ [P in MandatoryEventNames<E>]:
|
|
56
|
-
{ [P in OptionalEventNames<E>]:
|
|
95
|
+
{ [P in MandatoryEventNames<E>]: EventClientObj<EventType<E[P]>> },
|
|
96
|
+
{ [P in OptionalEventNames<E>]: EventClientObj<EventType<E[P]> | undefined> }
|
|
57
97
|
>;
|
|
58
98
|
|
|
59
99
|
export type SignatureFromCommandSpec<C extends Command<any, any, any>> = (
|
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
Bytes,
|
|
11
11
|
Diagnostic,
|
|
12
12
|
Duration,
|
|
13
|
-
hex,
|
|
14
13
|
InternalError,
|
|
15
14
|
Logger,
|
|
16
15
|
MatterFlowError,
|
|
17
16
|
Millis,
|
|
18
17
|
NoResponseTimeoutError,
|
|
18
|
+
Time,
|
|
19
19
|
UnexpectedDataError,
|
|
20
20
|
} from "#general";
|
|
21
21
|
import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
|
|
@@ -1014,7 +1014,7 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
|
|
|
1014
1014
|
|
|
1015
1015
|
#logContextOf(report: DataReport) {
|
|
1016
1016
|
return {
|
|
1017
|
-
subId: report.subscriptionId === undefined ? undefined :
|
|
1017
|
+
subId: report.subscriptionId === undefined ? undefined : Subscription.idStrOf(report.subscriptionId),
|
|
1018
1018
|
dataReportFlags: Diagnostic.asFlags({
|
|
1019
1019
|
empty: !report.attributeReports?.length && !report.eventReports?.length,
|
|
1020
1020
|
suppressResponse: report.suppressResponse,
|
|
@@ -1041,6 +1041,7 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
|
|
|
1041
1041
|
|
|
1042
1042
|
/** Implements a send method with an automatic reconnection mechanism */
|
|
1043
1043
|
override async send(messageType: number, payload: Bytes, options?: ExchangeSendOptions) {
|
|
1044
|
+
const now = Time.nowMs;
|
|
1044
1045
|
try {
|
|
1045
1046
|
if (this.exchange.channel.closed) {
|
|
1046
1047
|
throw new SessionClosedError("The exchange channel is closed. Please connect the device first.");
|
|
@@ -1054,12 +1055,12 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
|
|
|
1054
1055
|
!options?.multipleMessageInteraction
|
|
1055
1056
|
) {
|
|
1056
1057
|
// When retransmission failed (most likely due to a lost connection or invalid session),
|
|
1057
|
-
// try to reconnect if possible and resend the message
|
|
1058
|
+
// try to reconnect if possible and resend the message one more time
|
|
1058
1059
|
logger.debug(
|
|
1059
1060
|
`${error instanceof RetransmissionLimitReachedError ? "Retransmission limit reached" : "Channel not connected"}, trying to reconnect and resend the message.`,
|
|
1060
1061
|
);
|
|
1061
1062
|
await this.exchange.close();
|
|
1062
|
-
if (await this.#exchangeProvider.reconnectChannel()) {
|
|
1063
|
+
if (await this.#exchangeProvider.reconnectChannel({ asOf: now })) {
|
|
1063
1064
|
this.exchange = await this.#exchangeProvider.initiateExchange();
|
|
1064
1065
|
return await this.exchange.send(messageType, payload, options);
|
|
1065
1066
|
}
|